]> git.lizzy.rs Git - dragonnet.git/blob - typegen/main.c
cbaa11104136b6267964e02ab6e9afa9d19c3e53
[dragonnet.git] / typegen / main.c
1 #include <ctype.h>
2 #include <dragontype/number.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 static size_t split(char ***strs, char *s, const char *delim)
8 {
9         size_t i = 0;
10         *strs = malloc((1+i) * sizeof(char *));
11
12         // Can't be allocated on the stack for some reason
13         char *str = malloc(1+strlen(s));
14         strcpy(str, s);
15
16         char *tok = strtok(str, delim);
17         while (tok != NULL) {
18                 *strs = realloc(*strs, (1+i) * sizeof(char *));
19                 (*strs)[i++] = strdup(tok);
20                 tok = strtok(NULL, delim);
21         }
22
23         free(str);
24         return i;
25 }
26
27 static void free_split(char **strs, size_t n)
28 {
29         for (size_t i = 0; i < n; ++i)
30                 free(strs[i]);
31
32         free(strs);
33 }
34
35 static void gen_serializers(FILE *c_fp, FILE *h_fp)
36 {
37         fprintf(h_fp, "typedef char *string;\n");
38         fprintf(h_fp, "typedef struct {\n\tu32 siz;\n\tu8 *data;\n} Blob;\n\n");
39
40         for (u8 bits = 8; bits <= 64; bits *= 2) {
41                 char *fmt_u = "void send_u%d(DragonnetPeer *p, bool submit, u%d v)%s\n";
42                 char *fmt_s = "void send_s%d(DragonnetPeer *p, bool submit, s%d v)%s\n";
43
44                 fprintf(h_fp, fmt_u, bits, bits, ";");
45                 fprintf(h_fp, fmt_s, bits, bits, ";");
46
47                 fprintf(c_fp, fmt_u, bits, bits, "");
48                 fprintf(c_fp, "{\n");
49                 fprintf(c_fp, "\tu%d be = htobe%d(v);\n", bits, bits);
50                 fprintf(c_fp, "\tsend_raw(p, submit, &be, sizeof be);\n");
51                 fprintf(c_fp, "}\n\n");
52
53                 fprintf(c_fp, fmt_s, bits, bits, "");
54                 fprintf(c_fp, "{\n");
55                 fprintf(c_fp, "\tsend_u%d(p, submit, (u%d) v);\n", bits, bits);
56                 fprintf(c_fp, "}\n\n");
57
58                 if (bits >= 32) {
59                         char *fmt_f = "void send_f%d(DragonnetPeer *p, bool submit, f%d v)%s\n";
60                         fprintf(h_fp, fmt_f, bits, bits, ";");
61
62                         fprintf(c_fp, fmt_f, bits, bits, "");
63                         fprintf(c_fp, "{\n");
64                         fprintf(c_fp, "\tsend_u%d(p, submit, (u%d) v);\n", bits, bits);
65                         fprintf(c_fp, "}\n\n");
66                 }
67         }
68
69         fprintf(h_fp, "\n");
70
71         for (u8 elems = 2; elems <= 4; ++elems) {
72                 for (u8 bits = 8; bits <= 64; bits *= 2) {
73                         char *fmt_u = "void send_v%du%d(DragonnetPeer *p, bool submit, v%du%d v)%s\n";
74                         char *fmt_s = "void send_v%ds%d(DragonnetPeer *p, bool submit, v%ds%d v)%s\n";
75
76                         fprintf(h_fp, fmt_u, elems, bits, elems, bits, ";");
77                         fprintf(h_fp, fmt_s, elems, bits, elems, bits, ";");
78
79                         fprintf(c_fp, fmt_u, elems, bits, elems, bits, "");
80                         fprintf(c_fp, "{\n");
81                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
82                         fprintf(c_fp, "\t\tsend_u%d(p, (i == %d-1) ? submit : false, v[i]);\n", bits, elems);
83                         fprintf(c_fp, "\t}\n");
84                         fprintf(c_fp, "}\n\n");
85
86                         fprintf(c_fp, fmt_s, elems, bits, elems, bits, "");
87                         fprintf(c_fp, "{\n");
88                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
89                         fprintf(c_fp, "\t\tsend_s%d(p, (i == %d-1) ? submit : false, v[i]);\n", bits, elems);
90                         fprintf(c_fp, "\t}\n");
91                         fprintf(c_fp, "}\n\n");
92
93                         if (bits >= 32) {
94                                 char *fmt_f = "void send_v%df%d(DragonnetPeer *p, bool submit, v%df%d v)%s\n";
95                                 fprintf(h_fp, fmt_f, elems, bits, elems, bits, ";");
96
97                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits, "");
98                                 fprintf(c_fp, "{\n");
99                                 fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
100                                 fprintf(c_fp, "\t\tsend_s%d(p, (i == %d-1) ? submit : false, v[i]);\n", bits, elems);
101                                 fprintf(c_fp, "\t}\n");
102                                 fprintf(c_fp, "}\n\n");
103                         }
104                 }
105         }
106
107         fprintf(h_fp, "\n");
108
109         for (u8 elems = 2; elems <= 4; ++elems) {
110                 for (u8 bits = 8; bits <= 64; bits *= 2) {
111                         char *fmt_u = "void send_aabb%du%d(DragonnetPeer *p, bool submit, aabb%du%d v)\n";
112                         char *fmt_s = "void send_aabb%ds%d(DragonnetPeer *p, bool submit, aabb%ds%d v)\n";
113
114                         fprintf(h_fp, fmt_u, elems, bits, elems, bits, ";");
115                         fprintf(h_fp, fmt_s, elems, bits, elems, bits, ";");
116
117                         fprintf(c_fp, fmt_u, elems, bits, elems, bits, "");
118                         fprintf(c_fp, "{\n");
119                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
120                         fprintf(c_fp, "\t\tsend_v%du%d(p, (i == 1) ? submit : false, v[i]);\n", elems, bits);
121                         fprintf(c_fp, "\t}\n");
122                         fprintf(c_fp, "}\n\n");
123
124                         fprintf(c_fp, fmt_s, elems, bits, elems, bits, "");
125                         fprintf(c_fp, "{\n");
126                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
127                         fprintf(c_fp, "\t\tsend_v%ds%d(p, (i == 1) ? submit : false, v[i]);\n", elems, bits);
128                         fprintf(c_fp, "\t}\n");
129                         fprintf(c_fp, "}\n\n");
130
131                         if (bits >= 32) {
132                                 char *fmt_f = "void send_aabb%df%d(DragonnetPeer *p, bool submit, aabb%df%d v);\n";
133                                 fprintf(h_fp, fmt_f, elems, bits, elems, bits, ";");
134
135                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits, "");
136                                 fprintf(c_fp, "{\n");
137                                 fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
138                                 fprintf(c_fp, "\t\tsend_v%df%d(p, (i == 1) ? submit : false, v[i]);\n", elems, bits);
139                                 fprintf(c_fp, "\t}\n");
140                                 fprintf(c_fp, "}\n\n");
141                         }
142                 }
143         }
144
145         fprintf(h_fp, "\n");
146
147         char *fmt_str = "void send_string(DragonnetPeer *p, bool submit, string v)%s\n";
148         char *fmt_blob = "void send_Blob(DragonnetPeer *p, bool submit, Blob *v)%s\n\n";
149
150         fprintf(h_fp, fmt_str, ";");
151         fprintf(h_fp, fmt_blob, ";");
152
153         fprintf(c_fp, fmt_str, "");
154         fprintf(c_fp, "{\n");
155         fprintf(c_fp, "\tsend_raw(p, submit, v, strlen(v));\n");
156         fprintf(c_fp, "}\n\n");
157
158         fprintf(c_fp, fmt_blob, "");
159         fprintf(c_fp, "{\n");
160         fprintf(c_fp, "\tsend_u32(p, false, v->siz);\n");
161         fprintf(c_fp, "\tsend_raw(p, submit, v->data, v->siz);\n");
162         fprintf(c_fp, "}\n\n");
163 }
164
165 static void gen_deserializers(FILE *c_fp, FILE *h_fp)
166 {
167         c_fp = c_fp;
168         for (u8 bits = 8; bits <= 64; bits *= 2) {
169                 char *fmt_u = "u%d recv_u%d(DragonnetPeer *p)%s\n";
170                 char *fmt_s = "s%d recv_s%d(DragonnetPeer *p)%s\n";
171
172                 fprintf(h_fp, fmt_u, bits, bits, ";");
173                 fprintf(h_fp, fmt_s, bits, bits, ";");
174
175                 fprintf(c_fp, fmt_u, bits, bits, "");
176                 fprintf(c_fp, "{\n");
177                 fprintf(c_fp, "\tu%d be = recv_raw(p, &be, sizeof be);\n", bits);
178                 fprintf(c_fp, "\treturn be%dtoh(be);\n", bits);
179                 fprintf(c_fp, "}\n\n");
180
181                 fprintf(c_fp, fmt_s, bits, bits, "");
182                 fprintf(c_fp, "{\n");
183                 fprintf(c_fp, "\treturn (s%d) recv_u%d(p);\n", bits, bits);
184                 fprintf(c_fp, "}\n\n");
185
186                 if (bits >= 32) {
187                         char *fmt_f = "f%d recv_f%d(DragonnetPeer *p)%s\n";
188                         fprintf(h_fp, fmt_f, bits, bits, ";");
189
190                         fprintf(c_fp, fmt_f, bits, bits, "");
191                         fprintf(c_fp, "{\n");
192                         fprintf(c_fp, "\treturn (f%d) recv_u%d(p);\n", bits, bits);
193                         fprintf(c_fp, "}\n\n");
194                 }
195         }
196
197         fprintf(h_fp, "\n");
198
199         for (u8 elems = 2; elems <= 4; ++elems) {
200                 for (u8 bits = 8; bits <= 64; bits *= 2) {
201                         char *fmt_u = "v%du%d recv_v%du%d(DragonnetPeer *p)%s\n";
202                         char *fmt_s = "v%ds%d recv_v%ds%d(DragonnetPeer *p)%s\n";
203
204                         fprintf(h_fp, fmt_u, elems, bits, elems, bits, ";");
205                         fprintf(h_fp, fmt_s, elems, bits, elems, bits, ";");
206
207                         fprintf(c_fp, fmt_u, elems, bits, elems, bits, "");
208                         fprintf(c_fp, "{\n");
209                         fprintf(c_fp, "\tv%du%d v = {0};\n", elems, bits);
210                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
211                         fprintf(c_fp, "\t\tv[i] = recv_u%d(p);\n", bits);
212                         fprintf(c_fp, "\t}\n\n");
213                         fprintf(c_fp, "\treturn v;\n");
214                         fprintf(c_fp, "}\n\n");
215
216                         fprintf(c_fp, fmt_s, elems, bits, elems, bits, "");
217                         fprintf(c_fp, "{\n");
218                         fprintf(c_fp, "\tv%ds%d v = {0};\n", elems, bits);
219                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
220                         fprintf(c_fp, "\t\tv[i] = recv_s%d(p);\n", bits);
221                         fprintf(c_fp, "\t}\n\n");
222                         fprintf(c_fp, "\treturn v;\n");
223                         fprintf(c_fp, "}\n\n");
224
225                         if (bits >= 32) {
226                                 char *fmt_f = "v%df%d recv_v%df%d(DragonnetPeer *p)%s\n";
227                                 fprintf(h_fp, fmt_f, elems, bits, elems, bits, ";");
228
229                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits, "");
230                                 fprintf(c_fp, "{\n");
231                                 fprintf(c_fp, "\tv%df%d v = {0};\n", elems, bits);
232                                 fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
233                                 fprintf(c_fp, "\t\tv[i] = recv_f%d(p);\n", bits);
234                                 fprintf(c_fp, "\t}\n\n");
235                                 fprintf(c_fp, "\treturn v;\n");
236                                 fprintf(c_fp, "}\n\n");
237                         }
238                 }
239         }
240
241         fprintf(h_fp, "\n");
242
243         for (u8 elems = 2; elems <= 4; ++elems) {
244                 for (u8 bits = 8; bits <= 64; bits *= 2) {
245                         char *fmt_u = "aabb%du%d recv_aabb%du%d(DragonnetPeer *p)%s\n";
246                         char *fmt_s = "aabb%ds%d recv_aabb%ds%d(DragonnetPeer *p)%s\n";
247
248                         fprintf(h_fp, fmt_u, elems, bits, elems, bits, ";");
249                         fprintf(h_fp, fmt_s, elems, bits, elems, bits, ";");
250
251                         fprintf(c_fp, fmt_u, elems, bits, elems, bits, "");
252                         fprintf(c_fp, "{\n");
253                         fprintf(c_fp, "\taabb%du%d v = {0};\n", elems, bits);
254                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
255                         fprintf(c_fp, "\t\tv[i] = recv_v%du%d(p);\n", elems, bits);
256                         fprintf(c_fp, "\t}\n\n");
257                         fprintf(c_fp, "\treturn v;\n");
258                         fprintf(c_fp, "}\n\n");
259
260                         fprintf(c_fp, fmt_s, elems, bits, elems, bits, "");
261                         fprintf(c_fp, "{\n");
262                         fprintf(c_fp, "\taabb%ds%d v = {0};\n", elems, bits);
263                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
264                         fprintf(c_fp, "\t\tv[i] = recv_v%ds%d(p);\n", elems, bits);
265                         fprintf(c_fp, "\t}\n\n");
266                         fprintf(c_fp, "\treturn v;\n");
267                         fprintf(c_fp, "}\n\n");
268
269                         if (bits >= 32) {
270                                 char *fmt_f = "aabb%df%d recv_aabb%df%d(DragonnetPeer *p)%s\n";
271                                 fprintf(h_fp, fmt_f, elems, bits, elems, bits, ";");
272
273                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits, "");
274                                 fprintf(c_fp, "{\n");
275                                 fprintf(c_fp, "\taabb%df%d v = {0};\n", elems, bits);
276                                 fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
277                                 fprintf(c_fp, "\t\tv[i] = recv_v%ds%d(p);\n", elems, bits);
278                                 fprintf(c_fp, "\t}\n\n");
279                                 fprintf(c_fp, "\treturn v;\n");
280                                 fprintf(c_fp, "}\n\n");
281                         }
282                 }
283         }
284
285         fprintf(h_fp, "\n");
286
287         char *fmt_str = "string recv_string(DragonnetPeer *p)%s\n";
288         char *fmt_blob = "Blob *recv_Blob(DragonnetPeer *p)%s\n\n";
289
290         fprintf(h_fp, fmt_str, ";");
291         fprintf(h_fp, fmt_blob, ";");
292
293         fprintf(c_fp, fmt_str, "");
294         fprintf(c_fp, "{\n");
295         fprintf(c_fp, "\tstring v = malloc(sizeof(u16));\n\n");
296         fprintf(c_fp, "\tchar ch;\n");
297         fprintf(c_fp, "\tfor (u16 i = 0; ch != '\\0'; ++i) {\n");
298         fprintf(c_fp, "\t\tch = recv_s8(p);\n");
299         fprintf(c_fp, "\t\tv[i] = ch;\n");
300         fprintf(c_fp, "\t}\n\n");
301         fprintf(c_fp, "\tv = realloc(v, strlen(v));\n");
302         fprintf(c_fp, "\treturn v;\n");
303         fprintf(c_fp, "}\n\n");
304
305         fprintf(c_fp, fmt_blob, "");
306         fprintf(c_fp, "{\n");
307         fprintf(c_fp, "\tBlob *v = malloc(sizeof *v);\n");
308         fprintf(c_fp, "\tv->siz = recv_u32(p, false, v->siz);\n");
309         fprintf(c_fp, "\tv->data = malloc(v->siz);\n");
310         fprintf(c_fp, "\trecv_raw(p, v->data, v->siz);\n\n");
311         fprintf(c_fp, "\treturn v;\n");
312         fprintf(c_fp, "}\n\n");
313 }
314
315 int main(__attribute((unused)) int argc, __attribute((unused)) char **argv)
316 {
317         FILE *fp = fopen("types.dnet", "r");
318
319         char data[1 << 16];
320         memset(data, '\0', sizeof data);
321         fread(data, sizeof *data, sizeof data, fp);
322
323         fclose(fp);
324         fp = NULL;
325
326         FILE *c_fp = fopen("dnet-types.c", "w");
327         fprintf(c_fp, "#include <dragonnet/recv.h>\n");
328         fprintf(c_fp, "#include <dragonnet/send.h>\n\n");
329         fprintf(c_fp, "#include \"dnet-types.h\"\n\n");
330
331         FILE *h_fp = fopen("dnet-types.h", "w");
332         fprintf(h_fp, "#include <dragontype/number.h>\n\n");
333         fprintf(h_fp, "#define htobe8(x) (x)\n");
334         fprintf(h_fp, "#define be8toh(x) (x)\n\n");
335
336         gen_serializers(c_fp, h_fp);
337         gen_deserializers(c_fp, h_fp);
338
339         char **msgs;
340         size_t msgs_len = split(&msgs, data, "\n");
341
342         // Create data types
343         char *msg = NULL;
344         for (size_t i = 0; i < msgs_len; ++i) {
345                 if (msgs[i][0] != '\t') {
346                         if (msg != NULL)
347                                 fprintf(h_fp, "} %s;\n\n", msg);
348
349                         msg = msgs[i];
350                         fprintf(h_fp, "typedef struct {\n");
351                 } else {
352                         char **tokens;
353                         size_t tokens_len = split(&tokens, msgs[i], " ");
354
355                         fprintf(h_fp, "\t%s %s;\n", &tokens[0][1], tokens[1]);
356                         free_split(tokens, tokens_len);
357                         tokens = NULL;
358                 }
359         }
360
361         fprintf(h_fp, "} %s;\n\n", msg);
362         msg = NULL;
363
364         // Create (de)serialization functions
365         for (size_t i = 0; i < msgs_len; ++i) {
366                 if (msgs[i][0] != '\t') {
367                         if (msg != NULL)
368                                 fprintf(c_fp, "}\n\n");
369
370                         msg = msgs[i];
371                         fprintf(c_fp, "void dragonnet_send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg);
372                 } else {
373                         char **tokens;
374                         size_t tokens_len = split(&tokens, msgs[i], " ");
375
376                         if (i >= msgs_len-1 || msgs[1+i][0] != '\t')
377                                 fprintf(c_fp, "\tsend_%s(p, true, type.%s);\n", &tokens[0][1], tokens[1]);
378                         else
379                                 fprintf(c_fp, "\tsend_%s(p, false, type.%s);\n", &tokens[0][1], tokens[1]);
380
381                         free_split(tokens, tokens_len);
382                         tokens = NULL;
383                 }
384         }
385
386         fprintf(c_fp, "}\n\n");
387         msg = NULL;
388
389         for (size_t i = 0; i < msgs_len; ++i) {
390                 if (msgs[i][0] != '\t') {
391                         if (msg != NULL) {
392                                 fprintf(c_fp, "\treturn type;\n");
393                                 fprintf(c_fp, "}\n\n");
394                         }
395
396                         msg = msgs[i];
397                         fprintf(c_fp, "%s dragonnet_recv_%s(DragonnetPeer *p)\n{\n", msg, msg);
398                         fprintf(c_fp, "\t%s type = {0};\n", msg);
399                 } else {
400                         char **tokens;
401                         size_t tokens_len = split(&tokens, msgs[i], " ");
402
403                         fprintf(c_fp, "\ttype.%s = recv_%s(p);\n", tokens[1], &tokens[0][1]);
404                         free_split(tokens, tokens_len);
405                         tokens = NULL;
406                 }
407         }
408
409         fprintf(c_fp, "\treturn type;\n");
410         fprintf(c_fp, "}\n");
411         msg = NULL;
412
413         // Create type enum
414         size_t last_msg = 0;
415         for (size_t i = 0; i < msgs_len; ++i)
416                 if (msgs[i][0] != '\t')
417                         last_msg = i;
418
419         fprintf(h_fp, "typedef enum {\n");
420         for (size_t i = 0; i < msgs_len; ++i) {
421                 if (msgs[i][0] == '\t')
422                         continue;
423
424                 char upper[1 + strlen(msgs[i])];
425                 char *ptr = upper;
426                 strcpy(upper, msgs[i]);
427
428                 while ((*ptr = *ptr ? toupper(*ptr) : '\0'))
429                         ++ptr;
430
431                 if (i == last_msg)
432                         fprintf(h_fp, "\tDRAGONNET_TYPE_%s\n", upper);
433                 else
434                         fprintf(h_fp, "\tDRAGONNET_TYPE_%s,\n", upper);
435         }
436
437         fprintf(h_fp, "} DragonnetType;\n");
438
439         free_split(msgs, msgs_len);
440         msgs = NULL;
441
442         fclose(c_fp);
443         fclose(h_fp);
444         c_fp = NULL;
445         h_fp = NULL;
446 }