git.haldean.org ubik / dea1665
graphviz output for port system Haldean Brown 4 years ago
3 changed file(s) with 131 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
1818
1919 #pragma once
2020 #include "ubik/rt.h"
21 #include "ubik/stream.h"
2122 #include "ubik/vector.h"
2223
2324 enum ubik_port_type
5960 {
6061 ubik_port_source source;
6162 ubik_port_sink sink;
63
6264 /* Elements of plugs vector are ubik_plug pointers. Users should
6365 * not add to this vector directly; instead, they should use
6466 * ubik_port_attach. */
6567 struct ubik_vector plugs;
68
6669 struct ubik_value *head;
70
71 /* All elements of this struct are only used for implementing
72 * ubik_port_dump(). */
73 struct {
74 char *name;
75 } debug;
76
6777 enum ubik_port_type type;
6878 };
6979
93103 * freed causes undefined behavior. */
94104 void
95105 ubik_port_free(struct ubik_port *p);
106
107 /* Dumps all information about a set of ports in GraphViz dot format
108 * into the given stream. */
109 void
110 ubik_port_dump(struct ubik_stream *s, struct ubik_port **ports, size_t n);
1818
1919 #include "ubik/assert.h"
2020 #include "ubik/ports.h"
21 #include "ubik/string.h"
2122
2223 #include <stdlib.h>
2324
132133 p->head = NULL;
133134 p->type = 0;
134135 }
136
137 void
138 ubik_port_dump(struct ubik_stream *s, struct ubik_port **ports, size_t n)
139 {
140 size_t i;
141 size_t j;
142 struct ubik_port *p;
143 struct ubik_plug *plug;
144
145 ubik_fprintf(s, "digraph {\n");
146 for (i = 0; i < n; i++)
147 {
148 p = ports[i];
149 /* Need the "n" prefix because otherwise 0xABC gets
150 * parsed as a malformed number by graphviz. */
151 ubik_fprintf(s, " n%p [", (void *) p);
152 if (p->type & UBIK_PORT_SOURCE)
153 ubik_fprintf(s, "shape=box");
154 else if (p->type & UBIK_PORT_SINK)
155 ubik_fprintf(s, "shape=trapezium");
156 else
157 ubik_fprintf(s, "shape=octagon");
158
159 if (p->type & UBIK_PORT_SINK)
160 ubik_fprintf(s, ", style=bold");
161 else
162 ubik_fprintf(s, ", style=solid");
163
164 if (p->debug.name != NULL)
165 ubik_fprintf(s, ", label=\"%s\"", p->debug.name);
166 else
167 ubik_fprintf(s, ", label=\"\"");
168
169 ubik_fprintf(s, "]\n");
170
171 for (j = 0; j < p->plugs.n; j++)
172 {
173 plug = p->plugs.elems[j];
174 ubik_fprintf(s, " n%p -> n%p",
175 (void *) p, (void *) plug->dst);
176 if (plug->func != NULL)
177 ubik_fprintf(s, " [style=dashed]");
178 ubik_fprintf(s, "\n");
179 }
180 }
181 ubik_fprintf(s, "}\n");
182 }
4545 {
4646 unused(p);
4747 return ubik_raise(ERR_PRESENT, "expected error");
48 }
49
50 static ubik_error
51 xform(struct ubik_value **res, struct ubik_port *p)
52 {
53 *res = p->head;
54 return OK;
4855 }
4956
5057 test_t
111118 return ok;
112119 }
113120
121 test_t
122 dump_graphviz()
123 {
124 struct ubik_port p1 = {
125 .type = UBIK_PORT_SOURCE,
126 .debug = { .name = "stdio" },
127 };
128 struct ubik_port p2 = {
129 .type = UBIK_PORT_PIPE,
130 .debug = { .name = "P" },
131 };
132 struct ubik_port p3 = {
133 .type = UBIK_PORT_SOURCE,
134 .debug = { .name = "clock" },
135 };
136 struct ubik_port p4 = {
137 .type = UBIK_PORT_PIPE,
138 };
139 struct ubik_port p5 = {
140 .type = UBIK_PORT_PIPE,
141 };
142 struct ubik_port p6 = {
143 .type = UBIK_PORT_SINK,
144 .debug = { .name = "stdout" },
145 };
146 struct ubik_port p7 = {
147 .type = UBIK_PORT_SINK,
148 };
149 struct ubik_port p8 = {
150 .type = UBIK_PORT_SOURCE,
151 };
152 struct ubik_port *ps[] = { &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8 };
153 struct ubik_stream out;
154
155 assert(ubik_port_attach(&p1, &p2, NULL) == OK);
156 assert(ubik_port_attach(&p1, &p4, &xform) == OK);
157 assert(ubik_port_attach(&p3, &p2, NULL) == OK);
158 assert(ubik_port_attach(&p1, &p5, NULL) == OK);
159 assert(ubik_port_attach(&p5, &p6, NULL) == OK);
160 assert(ubik_port_attach(&p4, &p5, NULL) == OK);
161 assert(ubik_port_attach(&p2, &p7, &xform) == OK);
162 assert(ubik_port_attach(&p5, &p7, NULL) == OK);
163 assert(ubik_port_attach(&p8, &p7, NULL) == OK);
164 assert(ubik_stream_wfile(&out, "/tmp/ubik-test-unit-port.dot") == OK);
165
166 ubik_port_dump(&out, ps, sizeof(ps) / sizeof(ps[0]));
167
168 ubik_stream_close(&out);
169 ubik_port_free(&p1);
170 ubik_port_free(&p2);
171 ubik_port_free(&p3);
172 ubik_port_free(&p4);
173 ubik_port_free(&p5);
174 ubik_port_free(&p6);
175 ubik_port_free(&p7);
176 ubik_port_free(&p8);
177
178 return ok;
179 }
180
114181 int
115182 main()
116183 {
118185 run(attach_moves_value_forward);
119186 run(poll_moves_value_forward);
120187 run(sink_error_returns_error);
188 run(dump_graphviz);
121189 finish();
122190 }