]> git.lizzy.rs Git - dragonnet.git/blob - typegen/main.c
2f045bd15e7a6440722385ecf81344ccee80c5d4
[dragonnet.git] / typegen / main.c
1 #include <ctype.h>
2 #include <dragonport/asprintf.h>
3 #include <dragontype/number.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 static size_t split(char ***strs, char *s, const char *delim)
9 {
10         size_t i = 0;
11         *strs = malloc((1+i) * sizeof(char *));
12
13         // Can't be allocated on the stack for some reason
14         char *str = malloc(1+strlen(s));
15         strcpy(str, s);
16
17         char *tok = strtok(str, delim);
18         while (tok != NULL) {
19                 *strs = realloc(*strs, (1+i) * sizeof(char *));
20                 (*strs)[i++] = strdup(tok);
21                 tok = strtok(NULL, delim);
22         }
23
24         free(str);
25         return i;
26 }
27
28 static void free_split(char **strs, size_t n)
29 {
30         for (size_t i = 0; i < n; ++i)
31                 free(strs[i]);
32
33         free(strs);
34 }
35
36 // Socket based
37
38 static void gen_serializers(FILE *c_fp)
39 {
40         for (u8 bits = 8; bits <= 64; bits *= 2) {
41                 char *fmt_u = "__attribute__((unused)) static void send_u%d(DragonnetPeer *p, bool submit, u%d v)\n";
42                 char *fmt_s = "__attribute__((unused)) static void send_s%d(DragonnetPeer *p, bool submit, s%d v)\n";
43
44                 fprintf(c_fp, fmt_u, bits, bits);
45                 fprintf(c_fp, "{\n");
46                 fprintf(c_fp, "\tu%d be = htobe%d(v);\n", bits, bits);
47                 fprintf(c_fp, "\tdragonnet_send_raw(p, submit, &be, sizeof be);\n");
48                 fprintf(c_fp, "}\n\n");
49
50                 fprintf(c_fp, fmt_s, bits, bits, "");
51                 fprintf(c_fp, "{\n");
52                 fprintf(c_fp, "\tsend_u%d(p, submit, (u%d) v);\n", bits, bits);
53                 fprintf(c_fp, "}\n\n");
54
55                 if (bits >= 32) {
56                         char *fmt_f = "static void send_f%d(DragonnetPeer *p, bool submit, f%d v)\n";
57
58                         fprintf(c_fp, fmt_f, bits, bits);
59                         fprintf(c_fp, "{\n");
60                         fprintf(c_fp, "\tsend_u%d(p, submit, (u%d) v);\n", bits, bits);
61                         fprintf(c_fp, "}\n\n");
62                 }
63         }
64
65         for (u8 elems = 2; elems <= 4; ++elems) {
66                 for (u8 bits = 8; bits <= 64; bits *= 2) {
67                         char *fmt_u = "__attribute__((unused)) static void send_v%du%d(DragonnetPeer *p, bool submit, v%du%d v)\n";
68                         char *fmt_s = "__attribute__((unused)) static void send_v%ds%d(DragonnetPeer *p, bool submit, v%ds%d v)\n";
69
70                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
71                         fprintf(c_fp, "{\n");
72                         fprintf(c_fp, "\tu%d *ptr = &v.x;\n", bits);
73                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
74                         fprintf(c_fp, "\t\tsend_u%d(p, (i == %d-1) ? submit : false, *ptr++);\n", bits, elems);
75                         fprintf(c_fp, "\t}\n");
76                         fprintf(c_fp, "}\n\n");
77
78                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
79                         fprintf(c_fp, "{\n");
80                         fprintf(c_fp, "\ts%d *ptr = &v.x;\n", bits);
81                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
82                         fprintf(c_fp, "\t\tsend_s%d(p, (i == %d-1) ? submit : false, *ptr++);\n", bits, elems);
83                         fprintf(c_fp, "\t}\n");
84                         fprintf(c_fp, "}\n\n");
85
86                         if (bits >= 32) {
87                                 char *fmt_f = "__attribute__((unused)) static void send_v%df%d(DragonnetPeer *p, bool submit, v%df%d v)\n";
88
89                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
90                                 fprintf(c_fp, "{\n");
91                                 fprintf(c_fp, "\tf%d *ptr = &v.x;\n", bits);
92                                 fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
93                                 fprintf(c_fp, "\t\tsend_f%d(p, (i == %d-1) ? submit : false, *ptr++);\n", bits, elems);
94                                 fprintf(c_fp, "\t}\n");
95                                 fprintf(c_fp, "}\n\n");
96                         }
97                 }
98         }
99
100         for (u8 elems = 2; elems <= 4; ++elems) {
101                 for (u8 bits = 8; bits <= 64; bits *= 2) {
102                         char *fmt_u = "__attribute__((unused)) static void send_aabb%du%d(DragonnetPeer *p, bool submit, aabb%du%d v)\n";
103                         char *fmt_s = "__attribute__((unused)) static void send_aabb%ds%d(DragonnetPeer *p, bool submit, aabb%ds%d v)\n";
104
105                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
106                         fprintf(c_fp, "{\n");
107                         fprintf(c_fp, "\tv%du%d *ptr = &v.min;\n", elems, bits);
108                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
109                         fprintf(c_fp, "\t\tsend_v%du%d(p, (i == 1) ? submit : false, *ptr++);\n", elems, bits);
110                         fprintf(c_fp, "\t}\n");
111                         fprintf(c_fp, "}\n\n");
112
113                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
114                         fprintf(c_fp, "{\n");
115                         fprintf(c_fp, "\tv%ds%d *ptr = &v.min;\n", elems, bits);
116                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
117                         fprintf(c_fp, "\t\tsend_v%ds%d(p, (i == 1) ? submit : false, *ptr++);\n", elems, bits);
118                         fprintf(c_fp, "\t}\n");
119                         fprintf(c_fp, "}\n\n");
120
121                         if (bits >= 32) {
122                                 char *fmt_f = "__attribute__((unused)) static void send_aabb%df%d(DragonnetPeer *p, bool submit, aabb%df%d v)\n";
123
124                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
125                                 fprintf(c_fp, "{\n");
126                                 fprintf(c_fp, "\tv%df%d *ptr = &v.min;\n", elems, bits);
127                                 fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
128                                 fprintf(c_fp, "\t\tsend_v%df%d(p, (i == 1) ? submit : false, *ptr++);\n", elems, bits);
129                                 fprintf(c_fp, "\t}\n");
130                                 fprintf(c_fp, "}\n\n");
131                         }
132                 }
133         }
134
135         fprintf(c_fp, "__attribute__((unused)) static void send_string(DragonnetPeer *p, bool submit, string v)\n");
136         fprintf(c_fp, "{\n");
137         fprintf(c_fp, "\tdragonnet_send_raw(p, submit, v, strlen(v));\n");
138         fprintf(c_fp, "}\n\n");
139
140         fprintf(c_fp, "__attribute__((unused)) static void send_Blob(DragonnetPeer *p, bool submit, Blob *v)\n\n");
141         fprintf(c_fp, "{\n");
142         fprintf(c_fp, "\tsend_u32(p, false, v->siz);\n");
143         fprintf(c_fp, "\tdragonnet_send_raw(p, submit, v->data, v->siz);\n");
144         fprintf(c_fp, "}\n\n");
145 }
146
147 static void gen_deserializers(FILE *c_fp)
148 {
149         for (u8 bits = 8; bits <= 64; bits *= 2) {
150                 char *fmt = "__attribute__((unused)) static void recv_n%d(DragonnetPeer *p, void *buf)\n";
151
152                 fprintf(c_fp, fmt, bits);
153                 fprintf(c_fp, "{\n");
154                 fprintf(c_fp, "\tu%d be;\n", bits);
155                 fprintf(c_fp, "\tdragonnet_recv_raw(p, &be, sizeof be);\n");
156                 fprintf(c_fp, "\tbe = be%dtoh(be);\n", bits);
157                 fprintf(c_fp, "\tmemcpy(buf, &be, sizeof be);\n");
158                 fprintf(c_fp, "}\n\n");
159         }
160
161         for (u8 elems = 2; elems <= 4; ++elems) {
162                 for (u8 bits = 8; bits <= 64; bits *= 2) {
163                         char *fmt = "__attribute__((unused)) static void recv_v%dn%d(DragonnetPeer *p, void *buf)\n";
164
165                         fprintf(c_fp, fmt, elems, bits);
166                         fprintf(c_fp, "{\n");
167                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i)\n", elems);
168                         fprintf(c_fp, "\t\trecv_n%d(p, buf);\n", bits);
169                         fprintf(c_fp, "}\n\n");
170                 }
171         }
172
173         for (u8 elems = 2; elems <= 4; ++elems) {
174                 for (u8 bits = 8; bits <= 64; bits *= 2) {
175                         char *fmt = "__attribute__((unused)) static void recv_aabb%dn%d(DragonnetPeer *p, void *buf)\n";
176
177                         fprintf(c_fp, fmt, elems, bits);
178                         fprintf(c_fp, "{\n");
179                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i)\n");
180                         fprintf(c_fp, "\t\trecv_v%dn%d(p, buf);\n", elems, bits);
181                         fprintf(c_fp, "}\n\n");
182                 }
183         }
184
185         fprintf(c_fp, "__attribute__((unused)) static void recv_string(DragonnetPeer *p, void *buf)\n");
186         fprintf(c_fp, "{\n");
187         fprintf(c_fp, "\tstring v = malloc(1 + (u16) ~0);\n\n");
188         fprintf(c_fp, "\tchar ch;\n");
189         fprintf(c_fp, "\tfor (u16 i = 0; ch != '\\0'; ++i) {\n");
190         fprintf(c_fp, "\t\trecv_n8(p, &ch);\n");
191         fprintf(c_fp, "\t\tv[i] = ch;\n");
192         fprintf(c_fp, "\t}\n\n");
193         fprintf(c_fp, "\tv = realloc(v, strlen(v));\n");
194         fprintf(c_fp, "\tmemcpy(buf, v, strlen(v));\n");
195         fprintf(c_fp, "}\n\n");
196
197         fprintf(c_fp, "__attribute__((unused)) static void recv_Blob(DragonnetPeer *p, void *buf)\n\n");
198         fprintf(c_fp, "{\n");
199         fprintf(c_fp, "\tBlob *v = malloc(sizeof *v);\n");
200         fprintf(c_fp, "\trecv_n32(p, &v->siz);\n");
201         fprintf(c_fp, "\tv->data = malloc(v->siz);\n");
202         fprintf(c_fp, "\tdragonnet_recv_raw(p, v->data, v->siz);\n\n");
203         fprintf(c_fp, "\tmemcpy(buf, v->data, v->siz);\n");
204         fprintf(c_fp, "}\n\n");
205 }
206
207 // Buffer based
208
209 static void gen_buffer_serializers(FILE *c_fp)
210 {
211         for (u8 bits = 8; bits <= 64; bits *= 2) {
212                 char *fmt_u = "__attribute__((unused)) static void buf_write_u%d(u8 **buf, size_t *n, u%d v)\n";
213                 char *fmt_s = "__attribute__((unused)) static void buf_write_s%d(u8 **buf, size_t *n, s%d v)\n";
214
215                 fprintf(c_fp, fmt_u, bits, bits);
216                 fprintf(c_fp, "{\n");
217                 fprintf(c_fp, "\tu%d be = htobe%d(v);\n", bits, bits);
218                 fprintf(c_fp, "\tdragonnet_write_raw(buf, n, &be, sizeof be);\n");
219                 fprintf(c_fp, "}\n\n");
220
221                 fprintf(c_fp, fmt_s, bits, bits, "");
222                 fprintf(c_fp, "{\n");
223                 fprintf(c_fp, "\tbuf_write_u%d(buf, n, (u%d) v);\n", bits, bits);
224                 fprintf(c_fp, "}\n\n");
225
226                 if (bits >= 32) {
227                         char *fmt_f = "static void buf_write_f%d(u8 **buf, size_t *n, f%d v)\n";
228
229                         fprintf(c_fp, fmt_f, bits, bits);
230                         fprintf(c_fp, "{\n");
231                         fprintf(c_fp, "\tbuf_write_u%d(buf, n, (u%d) v);\n", bits, bits);
232                         fprintf(c_fp, "}\n\n");
233                 }
234         }
235
236         for (u8 elems = 2; elems <= 4; ++elems) {
237                 for (u8 bits = 8; bits <= 64; bits *= 2) {
238                         char *fmt_u = "__attribute__((unused)) static void buf_write_v%du%d(u8 **buf, size_t *n, v%du%d v)\n";
239                         char *fmt_s = "__attribute__((unused)) static void buf_write_v%ds%d(u8 **buf, size_t *n, v%ds%d v)\n";
240
241                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
242                         fprintf(c_fp, "{\n");
243                         fprintf(c_fp, "\tu%d *ptr = &v.x;\n", bits);
244                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
245                         fprintf(c_fp, "\t\tbuf_write_u%d(buf, n, *ptr++);\n", bits);
246                         fprintf(c_fp, "\t}\n");
247                         fprintf(c_fp, "}\n\n");
248
249                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
250                         fprintf(c_fp, "{\n");
251                         fprintf(c_fp, "\ts%d *ptr = &v.x;\n", bits);
252                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
253                         fprintf(c_fp, "\t\tbuf_write_s%d(buf, n, *ptr++);\n", bits);
254                         fprintf(c_fp, "\t}\n");
255                         fprintf(c_fp, "}\n\n");
256
257                         if (bits >= 32) {
258                                 char *fmt_f = "__attribute__((unused)) static void buf_write_v%df%d(u8 **buf, size_t *n, v%df%d v)\n";
259
260                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
261                                 fprintf(c_fp, "{\n");
262                                 fprintf(c_fp, "\tf%d *ptr = &v.x;\n", bits);
263                                 fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
264                                 fprintf(c_fp, "\t\tbuf_write_f%d(buf, n, *ptr++);\n", bits);
265                                 fprintf(c_fp, "\t}\n");
266                                 fprintf(c_fp, "}\n\n");
267                         }
268                 }
269         }
270
271         for (u8 elems = 2; elems <= 4; ++elems) {
272                 for (u8 bits = 8; bits <= 64; bits *= 2) {
273                         char *fmt_u = "__attribute__((unused)) static void buf_write_aabb%du%d(u8 **buf, size_t *n, aabb%du%d v)\n";
274                         char *fmt_s = "__attribute__((unused)) static void buf_write_aabb%ds%d(u8 **buf, size_t *n, aabb%ds%d v)\n";
275
276                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
277                         fprintf(c_fp, "{\n");
278                         fprintf(c_fp, "\tv%du%d *ptr = &v.min;\n", elems, bits);
279                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
280                         fprintf(c_fp, "\t\tbuf_write_v%du%d(buf, n, *ptr++);\n", elems, bits);
281                         fprintf(c_fp, "\t}\n");
282                         fprintf(c_fp, "}\n\n");
283
284                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
285                         fprintf(c_fp, "{\n");
286                         fprintf(c_fp, "\tv%ds%d *ptr = &v.min;\n", elems, bits);
287                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
288                         fprintf(c_fp, "\t\tbuf_write_v%ds%d(buf, n, *ptr++);\n", elems, bits);
289                         fprintf(c_fp, "\t}\n");
290                         fprintf(c_fp, "}\n\n");
291
292                         if (bits >= 32) {
293                                 char *fmt_f = "__attribute__((unused)) static void buf_write_aabb%df%d(u8 **buf, size_t *n, aabb%df%d v)\n";
294
295                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
296                                 fprintf(c_fp, "{\n");
297                                 fprintf(c_fp, "\tv%df%d *ptr = &v.min;\n", elems, bits);
298                                 fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
299                                 fprintf(c_fp, "\t\tbuf_write_v%df%d(buf, n, *ptr++);\n", elems, bits);
300                                 fprintf(c_fp, "\t}\n");
301                                 fprintf(c_fp, "}\n\n");
302                         }
303                 }
304         }
305
306         fprintf(c_fp, "__attribute__((unused)) static void buf_write_string(u8 **buf, size_t *n, string v)\n");
307         fprintf(c_fp, "{\n");
308         fprintf(c_fp, "\tdragonnet_write_raw(buf, n, v, strlen(v));\n");
309         fprintf(c_fp, "}\n\n");
310
311         fprintf(c_fp, "__attribute__((unused)) static void buf_write_Blob(u8 **buf, size_t *n, Blob *v)\n\n");
312         fprintf(c_fp, "{\n");
313         fprintf(c_fp, "\tbuf_write_u32(buf, n, v->siz);\n");
314         fprintf(c_fp, "\tdragonnet_write_raw(buf, n, v->data, v->siz);\n");
315         fprintf(c_fp, "}\n\n");
316 }
317
318 static void gen_buffer_deserializers(FILE *c_fp)
319 {
320         for (u8 bits = 8; bits <= 64; bits *= 2) {
321                 char *fmt_u = "__attribute__((unused)) static u%d buf_read_u%d(u8 **buf, size_t *n)\n";
322                 char *fmt_s = "__attribute__((unused)) static s%d buf_read_s%d(u8 **buf, size_t *n)\n";
323
324                 fprintf(c_fp, fmt_u, bits, bits);
325                 fprintf(c_fp, "{\n");
326                 fprintf(c_fp, "\tu%d be;\n", bits);
327                 fprintf(c_fp, "\tdragonnet_read_raw(buf, n, &be, sizeof be);\n");
328                 fprintf(c_fp, "\treturn be%dtoh(be);\n", bits);
329                 fprintf(c_fp, "}\n\n");
330
331                 fprintf(c_fp, fmt_s, bits, bits);
332                 fprintf(c_fp, "{\n");
333                 fprintf(c_fp, "\treturn (s%d) buf_read_u%d(buf, n);\n", bits, bits);
334                 fprintf(c_fp, "}\n\n");
335
336                 if (bits >= 32) {
337                         char *fmt_f = "__attribute__((unused)) static f%d buf_read_f%d(u8 **buf, size_t *n)\n";
338
339                         fprintf(c_fp, fmt_f, bits, bits);
340                         fprintf(c_fp, "{\n");
341                         fprintf(c_fp, "\treturn (f%d) buf_read_u%d(buf, n);\n", bits, bits);
342                         fprintf(c_fp, "}\n\n");
343                 }
344         }
345
346         for (u8 elems = 2; elems <= 4; ++elems) {
347                 for (u8 bits = 8; bits <= 64; bits *= 2) {
348                         char *fmt_u = "__attribute__((unused)) static v%du%d buf_read_v%du%d(u8 **buf, size_t *n)\n";
349                         char *fmt_s = "__attribute__((unused)) static v%ds%d buf_read_v%ds%d(u8 **buf, size_t *n)\n";
350
351                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
352                         fprintf(c_fp, "{\n");
353                         fprintf(c_fp, "\tv%du%d v = {0};\n", elems, bits);
354                         fprintf(c_fp, "\tu%d *ptr = &v.x;\n\n", bits);
355                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
356                         fprintf(c_fp, "\t\t*ptr++ = buf_read_u%d(buf, n);\n", bits);
357                         fprintf(c_fp, "\t}\n\n");
358                         fprintf(c_fp, "\treturn v;\n");
359                         fprintf(c_fp, "}\n\n");
360
361                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
362                         fprintf(c_fp, "{\n");
363                         fprintf(c_fp, "\tv%ds%d v = {0};\n", elems, bits);
364                         fprintf(c_fp, "\ts%d *ptr = &v.x;\n\n", bits);
365                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
366                         fprintf(c_fp, "\t\t*ptr++ = buf_read_s%d(buf, n);\n", bits);
367                         fprintf(c_fp, "\t}\n\n");
368                         fprintf(c_fp, "\treturn v;\n");
369                         fprintf(c_fp, "}\n\n");
370
371                         if (bits >= 32) {
372                                 char *fmt_f = "__attribute__((unused)) static v%df%d buf_read_v%df%d(u8 **buf, size_t *n)\n";
373
374                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
375                                 fprintf(c_fp, "{\n");
376                                 fprintf(c_fp, "\tv%df%d v = {0};\n", elems, bits);
377                                 fprintf(c_fp, "\tf%d *ptr = &v.x;\n\n", bits);
378                                 fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
379                                 fprintf(c_fp, "\t\t*ptr++ = buf_read_f%d(buf, n);\n", bits);
380                                 fprintf(c_fp, "\t}\n\n");
381                                 fprintf(c_fp, "\treturn v;\n");
382                                 fprintf(c_fp, "}\n\n");
383                         }
384                 }
385         }
386
387         for (u8 elems = 2; elems <= 4; ++elems) {
388                 for (u8 bits = 8; bits <= 64; bits *= 2) {
389                         char *fmt_u = "__attribute__((unused)) static aabb%du%d buf_read_aabb%du%d(u8 **buf, size_t *n)\n";
390                         char *fmt_s = "__attribute__((unused)) static aabb%ds%d buf_read_aabb%ds%d(u8 **buf, size_t *n)\n";
391
392                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
393                         fprintf(c_fp, "{\n");
394                         fprintf(c_fp, "\taabb%du%d v = {0};\n", elems, bits);
395                         fprintf(c_fp, "\tv%du%d *ptr = &v.min;\n\n", elems, bits);
396                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
397                         fprintf(c_fp, "\t\t*ptr++ = buf_read_v%du%d(buf, n);\n", elems, bits);
398                         fprintf(c_fp, "\t}\n\n");
399                         fprintf(c_fp, "\treturn v;\n");
400                         fprintf(c_fp, "}\n\n");
401
402                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
403                         fprintf(c_fp, "{\n");
404                         fprintf(c_fp, "\taabb%ds%d v = {0};\n", elems, bits);
405                         fprintf(c_fp, "\tv%ds%d *ptr = &v.min;\n\n", elems, bits);
406                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
407                         fprintf(c_fp, "\t\t*ptr++ = buf_read_v%ds%d(buf, n);\n", elems, bits);
408                         fprintf(c_fp, "\t}\n\n");
409                         fprintf(c_fp, "\treturn v;\n");
410                         fprintf(c_fp, "}\n\n");
411
412                         if (bits >= 32) {
413                                 char *fmt_f = "__attribute__((unused)) static aabb%df%d buf_read_aabb%df%d(u8 **buf, size_t *n)\n";
414
415                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
416                                 fprintf(c_fp, "{\n");
417                                 fprintf(c_fp, "\taabb%df%d v = {0};\n", elems, bits);
418                                 fprintf(c_fp, "\tv%df%d *ptr = &v.min;\n\n", elems, bits);
419                                 fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
420                                 fprintf(c_fp, "\t\t*ptr++ = buf_read_v%df%d(buf, n);\n", elems, bits);
421                                 fprintf(c_fp, "\t}\n\n");
422                                 fprintf(c_fp, "\treturn v;\n");
423                                 fprintf(c_fp, "}\n\n");
424                         }
425                 }
426         }
427
428         fprintf(c_fp, "__attribute__((unused)) static string buf_read_string(u8 **buf, size_t *n)\n");
429         fprintf(c_fp, "{\n");
430         fprintf(c_fp, "\tstring v = malloc(sizeof(u16));\n\n");
431         fprintf(c_fp, "\tchar ch;\n");
432         fprintf(c_fp, "\tfor (u16 i = 0; ch != '\\0'; ++i) {\n");
433         fprintf(c_fp, "\t\tch = buf_read_s8(buf, n);\n");
434         fprintf(c_fp, "\t\tv[i] = ch;\n");
435         fprintf(c_fp, "\t}\n\n");
436         fprintf(c_fp, "\tv = realloc(v, strlen(v));\n");
437         fprintf(c_fp, "\treturn v;\n");
438         fprintf(c_fp, "}\n\n");
439
440         fprintf(c_fp, "__attribute__((unused)) static Blob *buf_read_Blob(u8 **buf, size_t *n)\n\n");
441         fprintf(c_fp, "{\n");
442         fprintf(c_fp, "\tBlob *v = malloc(sizeof *v);\n");
443         fprintf(c_fp, "\tv->siz = buf_read_u32(buf, n);\n");
444         fprintf(c_fp, "\tv->data = malloc(v->siz);\n");
445         fprintf(c_fp, "\tdragonnet_read_raw(buf, n, v->data, v->siz);\n\n");
446         fprintf(c_fp, "\treturn v;\n");
447         fprintf(c_fp, "}\n\n");
448 }
449
450 int main(__attribute((unused)) int argc, __attribute((unused)) char **argv)
451 {
452         FILE *fp = fopen("types.dnet", "r");
453
454         char data[1 << 16];
455         memset(data, '\0', sizeof data);
456         fread(data, sizeof *data, sizeof data, fp);
457
458         fclose(fp);
459         fp = NULL;
460
461         FILE *c_fp = fopen("dnet-types.c", "w");
462         fprintf(c_fp, "#include <stdlib.h>\n");
463         fprintf(c_fp, "#include <string.h>\n");
464         fprintf(c_fp, "#include <dragonnet/recv.h>\n");
465         fprintf(c_fp, "#include <dragonnet/send.h>\n\n");
466         fprintf(c_fp, "#include \"dnet-types.h\"\n\n");
467
468         FILE *h_fp = fopen("dnet-types.h", "w");
469         fprintf(h_fp, "#include <dragontype/number.h>\n\n");
470         fprintf(h_fp, "#define htobe8(x) (x)\n");
471         fprintf(h_fp, "#define be8toh(x) (x)\n\n");
472         fprintf(h_fp, "typedef char *string;\n");
473         fprintf(h_fp, "typedef struct {\n\tu32 siz;\n\tu8 *data;\n} Blob;\n\n");
474
475         gen_serializers(c_fp);
476         gen_deserializers(c_fp);
477
478         gen_buffer_serializers(c_fp);
479         gen_buffer_deserializers(c_fp);
480
481         char **msgs;
482         size_t msgs_len = split(&msgs, data, "\n");
483
484         // Create data types
485         char *msg = NULL;
486         for (size_t i = 0; i < msgs_len; ++i) {
487                 if (msgs[i][0] != '\t') {
488                         if (msg != NULL)
489                                 fprintf(h_fp, "} %s;\n\n", msg);
490
491                         msg = msgs[i];
492                         fprintf(h_fp, "typedef struct {\n");
493                 } else {
494                         char **tokens;
495                         size_t tokens_len = split(&tokens, msgs[i], " ");
496
497                         fprintf(h_fp, "\t%s %s;\n", &tokens[0][1], tokens[1]);
498                         free_split(tokens, tokens_len);
499                         tokens = NULL;
500                 }
501         }
502
503         fprintf(h_fp, "} %s;\n\n", msg);
504         msg = NULL;
505
506         // Create (de)serialization functions
507         for (size_t i = 0; i < msgs_len; ++i) {
508                 if (msgs[i][0] != '\t') {
509                         if (msg != NULL)
510                                 fprintf(c_fp, "}\n\n");
511
512                         msg = msgs[i];
513                         fprintf(c_fp, "__attribute__((unused)) static void send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg);
514                 } else {
515                         char **tokens;
516                         size_t tokens_len = split(&tokens, msgs[i], " ");
517
518                         fprintf(c_fp, "\tsend_%s(p, false, type.%s);\n", &tokens[0][1], tokens[1]);
519                         free_split(tokens, tokens_len);
520                         tokens = NULL;
521                 }
522         }
523
524         fprintf(c_fp, "}\n\n");
525         msg = NULL;
526
527         for (size_t i = 0; i < msgs_len; ++i) {
528                 if (msgs[i][0] != '\t') {
529                         if (msg != NULL)
530                                 fprintf(c_fp, "}\n\n");
531
532                         msg = msgs[i];
533                         fprintf(h_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s *type);\n", msg, msg);
534                         fprintf(c_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s *type)\n{\n", msg, msg);
535
536                         char upper[1 + strlen(msgs[i])];
537                         char *ptr = upper;
538                         strcpy(upper, msg);
539
540                         while ((*ptr = *ptr ? toupper(*ptr) : '\0'))
541                                 ++ptr;
542
543                         fprintf(c_fp, "\tsend_u16(p, false, DRAGONNET_TYPE_%s);\n", upper);
544                 } else {
545                         char **tokens;
546                         size_t tokens_len = split(&tokens, msgs[i], " ");
547
548                         if (i >= msgs_len-1 || msgs[1+i][0] != '\t')
549                                 fprintf(c_fp, "\tsend_%s(p, true, type->%s);\n", &tokens[0][1], tokens[1]);
550                         else
551                                 fprintf(c_fp, "\tsend_%s(p, false, type->%s);\n", &tokens[0][1], tokens[1]);
552
553                         free_split(tokens, tokens_len);
554                         tokens = NULL;
555                 }
556         }
557
558         fprintf(c_fp, "}\n\n");
559         msg = NULL;
560
561         for (size_t i = 0; i < msgs_len; ++i) {
562                 if (msgs[i][0] != '\t') {
563                         if (msg != NULL) {
564                                 fprintf(c_fp, "}\n\n");
565                         }
566
567                         msg = msgs[i];
568                         fprintf(c_fp, "static void dragonnet_peer_recv_%s(DragonnetPeer *p, void *buf)\n{\n", msg);
569                         fprintf(c_fp, "\t%s *type = (%s *) buf;\n", msg, msg);
570                 } else {
571                         char **tokens;
572                         size_t tokens_len = split(&tokens, msgs[i], " ");
573
574                         char type[strlen(&tokens[0][1])];
575                         strcpy(type, &tokens[0][1]);
576
577                         for (size_t bits = 8; bits <= 64; bits *= 2) {
578                                 const char *fmt[] = {"u%d", "s%d", "f%d"};
579                                 for (size_t j = 0; j < sizeof fmt / sizeof *fmt; ++j) {
580                                         char *cmp;
581                                         asprintf(&cmp, fmt[j], bits);
582
583                                         if (strcmp(type, cmp) == 0)
584                                                 sprintf(type, "n%ld", bits);
585
586                                         free(cmp);
587                                 }
588                         }
589
590                         fprintf(c_fp, "\trecv_%s(p, &type->%s);\n", type, tokens[1]);
591                         free_split(tokens, tokens_len);
592                         tokens = NULL;
593                 }
594         }
595
596         fprintf(c_fp, "}\n");
597         msg = NULL;
598
599         // Buffer (de)serialization
600         for (size_t i = 0; i < msgs_len; ++i) {
601                 if (msgs[i][0] != '\t') {
602                         if (msg != NULL)
603                                 fprintf(c_fp, "}\n\n");
604
605                         msg = msgs[i];
606                         fprintf(c_fp, "void dragonnet_buf_write_%s(u8 **buf, size_t *n, %s type)\n{\n", msg, msg);
607                 } else {
608                         char **tokens;
609                         size_t tokens_len = split(&tokens, msgs[i], " ");
610
611                         fprintf(c_fp, "\tbuf_write_%s(buf, n, type.%s);\n", &tokens[0][1], tokens[1]);
612
613                         free_split(tokens, tokens_len);
614                         tokens = NULL;
615                 }
616         }
617
618         fprintf(c_fp, "}\n\n");
619         msg = NULL;
620
621         for (size_t i = 0; i < msgs_len; ++i) {
622                 if (msgs[i][0] != '\t') {
623                         if (msg != NULL) {
624                                 fprintf(c_fp, "\treturn type;\n");
625                                 fprintf(c_fp, "}\n\n");
626                         }
627
628                         msg = msgs[i];
629                         fprintf(h_fp, "%s dragonnet_buf_read_%s(u8 **buf, size_t *n);\n", msg, msg);
630                         fprintf(c_fp, "%s dragonnet_buf_read_%s(u8 **buf, size_t *n)\n{\n", msg, msg);
631                         fprintf(c_fp, "\t%s type = {0};\n", msg);
632                 } else {
633                         char **tokens;
634                         size_t tokens_len = split(&tokens, msgs[i], " ");
635
636                         fprintf(c_fp, "\ttype.%s = buf_read_%s(buf, n);\n", tokens[1], &tokens[0][1]);
637                         free_split(tokens, tokens_len);
638                         tokens = NULL;
639                 }
640         }
641
642         fprintf(h_fp, "\n");
643         fprintf(c_fp, "\treturn type;\n");
644         fprintf(c_fp, "}\n\n");
645         msg = NULL;
646
647         // Create type enum
648         fprintf(h_fp, "typedef enum {\n");
649         for (size_t i = 0; i < msgs_len; ++i) {
650                 if (msgs[i][0] == '\t')
651                         continue;
652
653                 char upper[1 + strlen(msgs[i])];
654                 char *ptr = upper;
655                 strcpy(upper, msgs[i]);
656
657                 while ((*ptr = *ptr ? toupper(*ptr) : '\0'))
658                         ++ptr;
659
660                 fprintf(h_fp, "\tDRAGONNET_TYPE_%s,\n", upper);
661         }
662
663         fprintf(h_fp, "\tDRAGONNET_NUM_TYPES\n");
664         fprintf(h_fp, "} DragonnetTypeNum;\n");
665
666         // ABI
667         fprintf(c_fp, "u16 dragonnet_num_types = DRAGONNET_NUM_TYPES;\n");
668         fprintf(c_fp, "DragonnetType dragonnet_types[] = {\n");
669
670         for (size_t i = 0; i < msgs_len; ++i) {
671                 if (msgs[i][0] == '\t')
672                         continue;
673
674                 fprintf(c_fp, "\t{\n");
675                 fprintf(c_fp, "\t\t.siz = sizeof(%s),\n", msgs[i]);
676                 fprintf(c_fp, "\t\t.deserialize = &dragonnet_peer_recv_%s\n", msgs[i]);
677                 fprintf(c_fp, "\t},\n");
678         }
679
680         fprintf(c_fp, "};\n");
681
682         free_split(msgs, msgs_len);
683         msgs = NULL;
684
685         fclose(c_fp);
686         fclose(h_fp);
687         c_fp = NULL;
688         h_fp = NULL;
689 }