]> git.lizzy.rs Git - dragonnet.git/blob - typegen/main.c
acf9f73c58b32734bc93ae5fbd81f87a94e71036
[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 = "__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_u = "__attribute__((unused)) static u%d recv_u%d(DragonnetPeer *p)\n";
151                 char *fmt_s = "__attribute__((unused)) static s%d recv_s%d(DragonnetPeer *p)\n";
152
153                 fprintf(c_fp, fmt_u, bits, bits);
154                 fprintf(c_fp, "{\n");
155                 fprintf(c_fp, "\tu%d be;\n", bits);
156                 fprintf(c_fp, "\tdragonnet_recv_raw(p, &be, sizeof be);\n");
157                 fprintf(c_fp, "\treturn be%dtoh(be);\n", bits);
158                 fprintf(c_fp, "}\n\n");
159
160                 fprintf(c_fp, fmt_s, bits, bits);
161                 fprintf(c_fp, "{\n");
162                 fprintf(c_fp, "\treturn (s%d) recv_u%d(p);\n", bits, bits);
163                 fprintf(c_fp, "}\n\n");
164
165                 if (bits >= 32) {
166                         char *fmt_f = "__attribute__((unused)) static f%d recv_f%d(DragonnetPeer *p)\n";
167
168                         fprintf(c_fp, fmt_f, bits, bits);
169                         fprintf(c_fp, "{\n");
170                         fprintf(c_fp, "\treturn (f%d) recv_u%d(p);\n", bits, bits);
171                         fprintf(c_fp, "}\n\n");
172                 }
173         }
174
175         for (u8 elems = 2; elems <= 4; ++elems) {
176                 for (u8 bits = 8; bits <= 64; bits *= 2) {
177                         char *fmt_u = "__attribute__((unused)) static v%du%d recv_v%du%d(DragonnetPeer *p)\n";
178                         char *fmt_s = "__attribute__((unused)) static v%ds%d recv_v%ds%d(DragonnetPeer *p)\n";
179
180                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
181                         fprintf(c_fp, "{\n");
182                         fprintf(c_fp, "\tv%du%d v = {0};\n", elems, bits);
183                         fprintf(c_fp, "\tu%d *ptr = &v.x;\n\n", bits);
184                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
185                         fprintf(c_fp, "\t\t*ptr++ = recv_u%d(p);\n", bits);
186                         fprintf(c_fp, "\t}\n\n");
187                         fprintf(c_fp, "\treturn v;\n");
188                         fprintf(c_fp, "}\n\n");
189
190                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
191                         fprintf(c_fp, "{\n");
192                         fprintf(c_fp, "\tv%ds%d v = {0};\n", elems, bits);
193                         fprintf(c_fp, "\ts%d *ptr = &v.x;\n\n", bits);
194                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
195                         fprintf(c_fp, "\t\t*ptr++ = recv_s%d(p);\n", bits);
196                         fprintf(c_fp, "\t}\n\n");
197                         fprintf(c_fp, "\treturn v;\n");
198                         fprintf(c_fp, "}\n\n");
199
200                         if (bits >= 32) {
201                                 char *fmt_f = "__attribute__((unused)) static v%df%d recv_v%df%d(DragonnetPeer *p)\n";
202
203                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
204                                 fprintf(c_fp, "{\n");
205                                 fprintf(c_fp, "\tv%df%d v = {0};\n", elems, bits);
206                                 fprintf(c_fp, "\tf%d *ptr = &v.x;\n\n", bits);
207                                 fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
208                                 fprintf(c_fp, "\t\t*ptr++ = recv_f%d(p);\n", bits);
209                                 fprintf(c_fp, "\t}\n\n");
210                                 fprintf(c_fp, "\treturn v;\n");
211                                 fprintf(c_fp, "}\n\n");
212                         }
213                 }
214         }
215
216         for (u8 elems = 2; elems <= 4; ++elems) {
217                 for (u8 bits = 8; bits <= 64; bits *= 2) {
218                         char *fmt_u = "__attribute__((unused)) static aabb%du%d recv_aabb%du%d(DragonnetPeer *p)\n";
219                         char *fmt_s = "__attribute__((unused)) static aabb%ds%d recv_aabb%ds%d(DragonnetPeer *p)\n";
220
221                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
222                         fprintf(c_fp, "{\n");
223                         fprintf(c_fp, "\taabb%du%d v = {0};\n", elems, bits);
224                         fprintf(c_fp, "\tv%du%d *ptr = &v.min;\n\n", elems, bits);
225                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
226                         fprintf(c_fp, "\t\t*ptr++ = recv_v%du%d(p);\n", elems, bits);
227                         fprintf(c_fp, "\t}\n\n");
228                         fprintf(c_fp, "\treturn v;\n");
229                         fprintf(c_fp, "}\n\n");
230
231                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
232                         fprintf(c_fp, "{\n");
233                         fprintf(c_fp, "\taabb%ds%d v = {0};\n", elems, bits);
234                         fprintf(c_fp, "\tv%ds%d *ptr = &v.min;\n\n", elems, bits);
235                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
236                         fprintf(c_fp, "\t\t*ptr++ = recv_v%ds%d(p);\n", elems, bits);
237                         fprintf(c_fp, "\t}\n\n");
238                         fprintf(c_fp, "\treturn v;\n");
239                         fprintf(c_fp, "}\n\n");
240
241                         if (bits >= 32) {
242                                 char *fmt_f = "__attribute__((unused)) static aabb%df%d recv_aabb%df%d(DragonnetPeer *p)\n";
243
244                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
245                                 fprintf(c_fp, "{\n");
246                                 fprintf(c_fp, "\taabb%df%d v = {0};\n", elems, bits);
247                                 fprintf(c_fp, "\tv%df%d *ptr = &v.min;\n\n", elems, bits);
248                                 fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
249                                 fprintf(c_fp, "\t\t*ptr++ = recv_v%df%d(p);\n", elems, bits);
250                                 fprintf(c_fp, "\t}\n\n");
251                                 fprintf(c_fp, "\treturn v;\n");
252                                 fprintf(c_fp, "}\n\n");
253                         }
254                 }
255         }
256
257         fprintf(c_fp, "__attribute__((unused)) static string recv_string(DragonnetPeer *p)\n");
258         fprintf(c_fp, "{\n");
259         fprintf(c_fp, "\tstring v = malloc(sizeof(u16));\n\n");
260         fprintf(c_fp, "\tchar ch;\n");
261         fprintf(c_fp, "\tfor (u16 i = 0; ch != '\\0'; ++i) {\n");
262         fprintf(c_fp, "\t\tch = recv_s8(p);\n");
263         fprintf(c_fp, "\t\tv[i] = ch;\n");
264         fprintf(c_fp, "\t}\n\n");
265         fprintf(c_fp, "\tv = realloc(v, strlen(v));\n");
266         fprintf(c_fp, "\treturn v;\n");
267         fprintf(c_fp, "}\n\n");
268
269         fprintf(c_fp, "__attribute__((unused)) static Blob *recv_Blob(DragonnetPeer *p)\n\n");
270         fprintf(c_fp, "{\n");
271         fprintf(c_fp, "\tBlob *v = malloc(sizeof *v);\n");
272         fprintf(c_fp, "\tv->siz = recv_u32(p);\n");
273         fprintf(c_fp, "\tv->data = malloc(v->siz);\n");
274         fprintf(c_fp, "\tdragonnet_recv_raw(p, v->data, v->siz);\n\n");
275         fprintf(c_fp, "\treturn v;\n");
276         fprintf(c_fp, "}\n\n");
277 }
278
279 int main(__attribute((unused)) int argc, __attribute((unused)) char **argv)
280 {
281         FILE *fp = fopen("types.dnet", "r");
282
283         char data[1 << 16];
284         memset(data, '\0', sizeof data);
285         fread(data, sizeof *data, sizeof data, fp);
286
287         fclose(fp);
288         fp = NULL;
289
290         FILE *c_fp = fopen("dnet-types.c", "w");
291         fprintf(c_fp, "#include <stdlib.h>\n");
292         fprintf(c_fp, "#include <string.h>\n");
293         fprintf(c_fp, "#include <dragonnet/recv.h>\n");
294         fprintf(c_fp, "#include <dragonnet/send.h>\n\n");
295         fprintf(c_fp, "#include \"dnet-types.h\"\n\n");
296
297         FILE *h_fp = fopen("dnet-types.h", "w");
298         fprintf(h_fp, "#include <dragontype/number.h>\n\n");
299         fprintf(h_fp, "#define htobe8(x) (x)\n");
300         fprintf(h_fp, "#define be8toh(x) (x)\n\n");
301
302         gen_serializers(c_fp, h_fp);
303         gen_deserializers(c_fp);
304
305         char **msgs;
306         size_t msgs_len = split(&msgs, data, "\n");
307
308         // Create data types
309         char *msg = NULL;
310         for (size_t i = 0; i < msgs_len; ++i) {
311                 if (msgs[i][0] != '\t') {
312                         if (msg != NULL)
313                                 fprintf(h_fp, "} %s;\n\n", msg);
314
315                         msg = msgs[i];
316                         fprintf(h_fp, "typedef struct {\n");
317                 } else {
318                         char **tokens;
319                         size_t tokens_len = split(&tokens, msgs[i], " ");
320
321                         fprintf(h_fp, "\t%s %s;\n", &tokens[0][1], tokens[1]);
322                         free_split(tokens, tokens_len);
323                         tokens = NULL;
324                 }
325         }
326
327         fprintf(h_fp, "} %s;\n\n", msg);
328         msg = NULL;
329
330         // Create (de)serialization functions
331         for (size_t i = 0; i < msgs_len; ++i) {
332                 if (msgs[i][0] != '\t') {
333                         if (msg != NULL)
334                                 fprintf(c_fp, "}\n\n");
335
336                         msg = msgs[i];
337                         fprintf(c_fp, "__attribute__((unused)) static void send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg);
338                 } else {
339                         char **tokens;
340                         size_t tokens_len = split(&tokens, msgs[i], " ");
341
342                         fprintf(c_fp, "\tsend_%s(p, false, type.%s);\n", &tokens[0][1], tokens[1]);
343
344                         free_split(tokens, tokens_len);
345                         tokens = NULL;
346                 }
347         }
348
349         fprintf(c_fp, "}\n\n");
350         msg = NULL;
351
352         for (size_t i = 0; i < msgs_len; ++i) {
353                 if (msgs[i][0] != '\t') {
354                         if (msg != NULL)
355                                 fprintf(c_fp, "}\n\n");
356
357                         msg = msgs[i];
358                         fprintf(h_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s type);\n", msg, msg);
359                         fprintf(c_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg);
360
361                         char upper[1 + strlen(msgs[i])];
362                         char *ptr = upper;
363                         strcpy(upper, msg);
364
365                         while ((*ptr = *ptr ? toupper(*ptr) : '\0'))
366                                 ++ptr;
367
368                         fprintf(c_fp, "\tsend_u16(p, false, DRAGONNET_TYPE_%s);\n", upper);
369                 } else {
370                         char **tokens;
371                         size_t tokens_len = split(&tokens, msgs[i], " ");
372
373                         if (i >= msgs_len-1 || msgs[1+i][0] != '\t')
374                                 fprintf(c_fp, "\tsend_%s(p, true, type.%s);\n", &tokens[0][1], tokens[1]);
375                         else
376                                 fprintf(c_fp, "\tsend_%s(p, false, type.%s);\n", &tokens[0][1], tokens[1]);
377
378                         free_split(tokens, tokens_len);
379                         tokens = NULL;
380                 }
381         }
382
383         fprintf(c_fp, "}\n\n");
384         msg = NULL;
385
386         for (size_t i = 0; i < msgs_len; ++i) {
387                 if (msgs[i][0] != '\t') {
388                         if (msg != NULL) {
389                                 fprintf(c_fp, "\treturn type;\n");
390                                 fprintf(c_fp, "}\n\n");
391                         }
392
393                         msg = msgs[i];
394                         fprintf(h_fp, "%s dragonnet_peer_recv_%s(DragonnetPeer *p);\n", msg, msg);
395                         fprintf(c_fp, "%s dragonnet_peer_recv_%s(DragonnetPeer *p)\n{\n", msg, msg);
396                         fprintf(c_fp, "\t%s type = {0};\n", msg);
397                 } else {
398                         char **tokens;
399                         size_t tokens_len = split(&tokens, msgs[i], " ");
400
401                         fprintf(c_fp, "\ttype.%s = recv_%s(p);\n", tokens[1], &tokens[0][1]);
402                         free_split(tokens, tokens_len);
403                         tokens = NULL;
404                 }
405         }
406
407         fprintf(h_fp, "\n");
408         fprintf(c_fp, "\treturn type;\n");
409         fprintf(c_fp, "}\n");
410         msg = NULL;
411
412         // Create type enum
413         size_t last_msg = 0;
414         for (size_t i = 0; i < msgs_len; ++i)
415                 if (msgs[i][0] != '\t')
416                         last_msg = i;
417
418         fprintf(h_fp, "typedef enum {\n");
419         for (size_t i = 0; i < msgs_len; ++i) {
420                 if (msgs[i][0] == '\t')
421                         continue;
422
423                 char upper[1 + strlen(msgs[i])];
424                 char *ptr = upper;
425                 strcpy(upper, msgs[i]);
426
427                 while ((*ptr = *ptr ? toupper(*ptr) : '\0'))
428                         ++ptr;
429
430                 if (i == last_msg)
431                         fprintf(h_fp, "\tDRAGONNET_TYPE_%s\n", upper);
432                 else
433                         fprintf(h_fp, "\tDRAGONNET_TYPE_%s,\n", upper);
434         }
435
436         fprintf(h_fp, "} DragonnetType;\n");
437
438         free_split(msgs, msgs_len);
439         msgs = NULL;
440
441         fclose(c_fp);
442         fclose(h_fp);
443         c_fp = NULL;
444         h_fp = NULL;
445 }