]> git.lizzy.rs Git - dragonnet.git/blob - typegen/main.c
e591a278ad98686dbd251734260fe1bdcf4c457e
[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 = "static void dragonnet_send_u%d(DragonnetPeer *p, bool submit, u%d v)\n";
42                 char *fmt_s = "static void dragonnet_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 dragonnet_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, "\tdragonnet_send_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 = "static void dragonnet_send_v%du%d(DragonnetPeer *p, bool submit, v%du%d v)\n";
68                         char *fmt_s = "static void dragonnet_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, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
73                         fprintf(c_fp, "\t\tdragonnet_send_u%d(p, (i == %d-1) ? submit : false, v[i]);\n", bits, elems);
74                         fprintf(c_fp, "\t}\n");
75                         fprintf(c_fp, "}\n\n");
76
77                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
78                         fprintf(c_fp, "{\n");
79                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
80                         fprintf(c_fp, "\t\tdragonnet_send_s%d(p, (i == %d-1) ? submit : false, v[i]);\n", bits, elems);
81                         fprintf(c_fp, "\t}\n");
82                         fprintf(c_fp, "}\n\n");
83
84                         if (bits >= 32) {
85                                 char *fmt_f = "static void dragonnet_send_v%df%d(DragonnetPeer *p, bool submit, v%df%d v)\n";
86
87                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
88                                 fprintf(c_fp, "{\n");
89                                 fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
90                                 fprintf(c_fp, "\t\tdragonnet_send_s%d(p, (i == %d-1) ? submit : false, v[i]);\n", bits, elems);
91                                 fprintf(c_fp, "\t}\n");
92                                 fprintf(c_fp, "}\n\n");
93                         }
94                 }
95         }
96
97         for (u8 elems = 2; elems <= 4; ++elems) {
98                 for (u8 bits = 8; bits <= 64; bits *= 2) {
99                         char *fmt_u = "static void dragonnet_send_aabb%du%d(DragonnetPeer *p, bool submit, aabb%du%d v)\n";
100                         char *fmt_s = "static void dragonnet_send_aabb%ds%d(DragonnetPeer *p, bool submit, aabb%ds%d v)\n";
101
102                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
103                         fprintf(c_fp, "{\n");
104                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
105                         fprintf(c_fp, "\t\tdragonnet_send_v%du%d(p, (i == 1) ? submit : false, v[i]);\n", elems, bits);
106                         fprintf(c_fp, "\t}\n");
107                         fprintf(c_fp, "}\n\n");
108
109                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
110                         fprintf(c_fp, "{\n");
111                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
112                         fprintf(c_fp, "\t\tdragonnet_send_v%ds%d(p, (i == 1) ? submit : false, v[i]);\n", elems, bits);
113                         fprintf(c_fp, "\t}\n");
114                         fprintf(c_fp, "}\n\n");
115
116                         if (bits >= 32) {
117                                 char *fmt_f = "static void dragonnet_send_aabb%df%d(DragonnetPeer *p, bool submit, aabb%df%d v);\n";
118
119                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
120                                 fprintf(c_fp, "{\n");
121                                 fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
122                                 fprintf(c_fp, "\t\tdragonnet_send_v%df%d(p, (i == 1) ? submit : false, v[i]);\n", elems, bits);
123                                 fprintf(c_fp, "\t}\n");
124                                 fprintf(c_fp, "}\n\n");
125                         }
126                 }
127         }
128
129         fprintf(c_fp, "static void dragonnet_send_string(DragonnetPeer *p, bool submit, string v)\n");
130         fprintf(c_fp, "{\n");
131         fprintf(c_fp, "\tdragonnet_send_raw(p, submit, v, strlen(v));\n");
132         fprintf(c_fp, "}\n\n");
133
134         fprintf(c_fp, "static void dragonnet_send_Blob(DragonnetPeer *p, bool submit, Blob *v)\n\n");
135         fprintf(c_fp, "{\n");
136         fprintf(c_fp, "\tdragonnet_send_u32(p, false, v->siz);\n");
137         fprintf(c_fp, "\tdragonnet_send_raw(p, submit, v->data, v->siz);\n");
138         fprintf(c_fp, "}\n\n");
139 }
140
141 static void gen_deserializers(FILE *c_fp)
142 {
143         for (u8 bits = 8; bits <= 64; bits *= 2) {
144                 char *fmt_u = "static u%d dragonnet_recv_u%d(DragonnetPeer *p)\n";
145                 char *fmt_s = "static s%d dragonnet_recv_s%d(DragonnetPeer *p)\n";
146
147                 fprintf(c_fp, fmt_u, bits, bits);
148                 fprintf(c_fp, "{\n");
149                 fprintf(c_fp, "\tu%d be = dragonnet_recv_raw(p, &be, sizeof be);\n", bits);
150                 fprintf(c_fp, "\treturn be%dtoh(be);\n", bits);
151                 fprintf(c_fp, "}\n\n");
152
153                 fprintf(c_fp, fmt_s, bits, bits);
154                 fprintf(c_fp, "{\n");
155                 fprintf(c_fp, "\treturn (s%d) dragonnet_recv_u%d(p);\n", bits, bits);
156                 fprintf(c_fp, "}\n\n");
157
158                 if (bits >= 32) {
159                         char *fmt_f = "static f%d dragonnet_recv_f%d(DragonnetPeer *p)\n";
160
161                         fprintf(c_fp, fmt_f, bits, bits);
162                         fprintf(c_fp, "{\n");
163                         fprintf(c_fp, "\treturn (f%d) dragonnet_recv_u%d(p);\n", bits, bits);
164                         fprintf(c_fp, "}\n\n");
165                 }
166         }
167
168         for (u8 elems = 2; elems <= 4; ++elems) {
169                 for (u8 bits = 8; bits <= 64; bits *= 2) {
170                         char *fmt_u = "static v%du%d dragonnet_recv_v%du%d(DragonnetPeer *p)\n";
171                         char *fmt_s = "static v%ds%d dragonnet_recv_v%ds%d(DragonnetPeer *p)\n";
172
173                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
174                         fprintf(c_fp, "{\n");
175                         fprintf(c_fp, "\tv%du%d v = {0};\n", elems, bits);
176                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
177                         fprintf(c_fp, "\t\tv[i] = dragonnet_recv_u%d(p);\n", bits);
178                         fprintf(c_fp, "\t}\n\n");
179                         fprintf(c_fp, "\treturn v;\n");
180                         fprintf(c_fp, "}\n\n");
181
182                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
183                         fprintf(c_fp, "{\n");
184                         fprintf(c_fp, "\tv%ds%d v = {0};\n", elems, bits);
185                         fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
186                         fprintf(c_fp, "\t\tv[i] = dragonnet_recv_s%d(p);\n", bits);
187                         fprintf(c_fp, "\t}\n\n");
188                         fprintf(c_fp, "\treturn v;\n");
189                         fprintf(c_fp, "}\n\n");
190
191                         if (bits >= 32) {
192                                 char *fmt_f = "static v%df%d dragonnet_recv_v%df%d(DragonnetPeer *p)\n";
193
194                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
195                                 fprintf(c_fp, "{\n");
196                                 fprintf(c_fp, "\tv%df%d v = {0};\n", elems, bits);
197                                 fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
198                                 fprintf(c_fp, "\t\tv[i] = dragonnet_recv_f%d(p);\n", bits);
199                                 fprintf(c_fp, "\t}\n\n");
200                                 fprintf(c_fp, "\treturn v;\n");
201                                 fprintf(c_fp, "}\n\n");
202                         }
203                 }
204         }
205
206         for (u8 elems = 2; elems <= 4; ++elems) {
207                 for (u8 bits = 8; bits <= 64; bits *= 2) {
208                         char *fmt_u = "static aabb%du%d dragonnet_recv_aabb%du%d(DragonnetPeer *p)\n";
209                         char *fmt_s = "static aabb%ds%d dragonnet_recv_aabb%ds%d(DragonnetPeer *p)\n";
210
211                         fprintf(c_fp, fmt_u, elems, bits, elems, bits);
212                         fprintf(c_fp, "{\n");
213                         fprintf(c_fp, "\taabb%du%d v = {0};\n", elems, bits);
214                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
215                         fprintf(c_fp, "\t\tv[i] = dragonnet_recv_v%du%d(p);\n", elems, bits);
216                         fprintf(c_fp, "\t}\n\n");
217                         fprintf(c_fp, "\treturn v;\n");
218                         fprintf(c_fp, "}\n\n");
219
220                         fprintf(c_fp, fmt_s, elems, bits, elems, bits);
221                         fprintf(c_fp, "{\n");
222                         fprintf(c_fp, "\taabb%ds%d v = {0};\n", elems, bits);
223                         fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
224                         fprintf(c_fp, "\t\tv[i] = dragonnet_recv_v%ds%d(p);\n", elems, bits);
225                         fprintf(c_fp, "\t}\n\n");
226                         fprintf(c_fp, "\treturn v;\n");
227                         fprintf(c_fp, "}\n\n");
228
229                         if (bits >= 32) {
230                                 char *fmt_f = "static aabb%df%d dragonnet_recv_aabb%df%d(DragonnetPeer *p)\n";
231
232                                 fprintf(c_fp, fmt_f, elems, bits, elems, bits);
233                                 fprintf(c_fp, "{\n");
234                                 fprintf(c_fp, "\taabb%df%d v = {0};\n", elems, bits);
235                                 fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
236                                 fprintf(c_fp, "\t\tv[i] = dragonnet_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                 }
242         }
243
244         fprintf(c_fp, "static string dragonnet_recv_string(DragonnetPeer *p)\n");
245         fprintf(c_fp, "{\n");
246         fprintf(c_fp, "\tstring v = malloc(sizeof(u16));\n\n");
247         fprintf(c_fp, "\tchar ch;\n");
248         fprintf(c_fp, "\tfor (u16 i = 0; ch != '\\0'; ++i) {\n");
249         fprintf(c_fp, "\t\tch = dragonnet_recv_s8(p);\n");
250         fprintf(c_fp, "\t\tv[i] = ch;\n");
251         fprintf(c_fp, "\t}\n\n");
252         fprintf(c_fp, "\tv = realloc(v, strlen(v));\n");
253         fprintf(c_fp, "\treturn v;\n");
254         fprintf(c_fp, "}\n\n");
255
256         fprintf(c_fp, "static Blob *dragonnet_recv_Blob(DragonnetPeer *p)\n\n");
257         fprintf(c_fp, "{\n");
258         fprintf(c_fp, "\tBlob *v = malloc(sizeof *v);\n");
259         fprintf(c_fp, "\tv->siz = dragonnet_recv_u32(p, false, v->siz);\n");
260         fprintf(c_fp, "\tv->data = malloc(v->siz);\n");
261         fprintf(c_fp, "\tdragonnet_recv_raw(p, v->data, v->siz);\n\n");
262         fprintf(c_fp, "\treturn v;\n");
263         fprintf(c_fp, "}\n\n");
264 }
265
266 int main(__attribute((unused)) int argc, __attribute((unused)) char **argv)
267 {
268         FILE *fp = fopen("types.dnet", "r");
269
270         char data[1 << 16];
271         memset(data, '\0', sizeof data);
272         fread(data, sizeof *data, sizeof data, fp);
273
274         fclose(fp);
275         fp = NULL;
276
277         FILE *c_fp = fopen("dnet-types.c", "w");
278         fprintf(c_fp, "#include <dragonnet/recv.h>\n");
279         fprintf(c_fp, "#include <dragonnet/send.h>\n\n");
280         fprintf(c_fp, "#include \"dnet-types.h\"\n\n");
281
282         FILE *h_fp = fopen("dnet-types.h", "w");
283         fprintf(h_fp, "#include <dragontype/number.h>\n\n");
284         fprintf(h_fp, "#define htobe8(x) (x)\n");
285         fprintf(h_fp, "#define be8toh(x) (x)\n\n");
286
287         gen_serializers(c_fp, h_fp);
288         gen_deserializers(c_fp);
289
290         char **msgs;
291         size_t msgs_len = split(&msgs, data, "\n");
292
293         // Create data types
294         char *msg = NULL;
295         for (size_t i = 0; i < msgs_len; ++i) {
296                 if (msgs[i][0] != '\t') {
297                         if (msg != NULL)
298                                 fprintf(h_fp, "} %s;\n\n", msg);
299
300                         msg = msgs[i];
301                         fprintf(h_fp, "typedef struct {\n");
302                 } else {
303                         char **tokens;
304                         size_t tokens_len = split(&tokens, msgs[i], " ");
305
306                         fprintf(h_fp, "\t%s %s;\n", &tokens[0][1], tokens[1]);
307                         free_split(tokens, tokens_len);
308                         tokens = NULL;
309                 }
310         }
311
312         fprintf(h_fp, "} %s;\n\n", msg);
313         msg = NULL;
314
315         // Create (de)serialization functions
316         for (size_t i = 0; i < msgs_len; ++i) {
317                 if (msgs[i][0] != '\t') {
318                         if (msg != NULL)
319                                 fprintf(c_fp, "}\n\n");
320
321                         msg = msgs[i];
322                         fprintf(c_fp, "static void dragonnet_send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg);
323                 } else {
324                         char **tokens;
325                         size_t tokens_len = split(&tokens, msgs[i], " ");
326
327                         fprintf(c_fp, "\tdragonnet_send_%s(p, false, type.%s);\n", &tokens[0][1], tokens[1]);
328
329                         free_split(tokens, tokens_len);
330                         tokens = NULL;
331                 }
332         }
333
334         fprintf(c_fp, "}\n\n");
335         msg = NULL;
336
337         for (size_t i = 0; i < msgs_len; ++i) {
338                 if (msgs[i][0] != '\t') {
339                         if (msg != NULL)
340                                 fprintf(c_fp, "}\n\n");
341
342                         msg = msgs[i];
343                         fprintf(h_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s type);\n", msg, msg);
344                         fprintf(c_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg);
345                 } else {
346                         char **tokens;
347                         size_t tokens_len = split(&tokens, msgs[i], " ");
348
349                         if (i >= msgs_len-1 || msgs[1+i][0] != '\t')
350                                 fprintf(c_fp, "\tdragonnet_send_%s(p, true, type.%s);\n", &tokens[0][1], tokens[1]);
351                         else
352                                 fprintf(c_fp, "\tdragonnet_send_%s(p, false, type.%s);\n", &tokens[0][1], tokens[1]);
353
354                         free_split(tokens, tokens_len);
355                         tokens = NULL;
356                 }
357         }
358
359         fprintf(c_fp, "}\n\n");
360         msg = NULL;
361
362         for (size_t i = 0; i < msgs_len; ++i) {
363                 if (msgs[i][0] != '\t') {
364                         if (msg != NULL) {
365                                 fprintf(c_fp, "\treturn type;\n");
366                                 fprintf(c_fp, "}\n\n");
367                         }
368
369                         msg = msgs[i];
370                         fprintf(h_fp, "%s dragonnet_peer_recv_%s(DragonnetPeer *p);\n", msg, msg);
371                         fprintf(c_fp, "%s dragonnet_peer_recv_%s(DragonnetPeer *p)\n{\n", msg, msg);
372                         fprintf(c_fp, "\t%s type = {0};\n", msg);
373                 } else {
374                         char **tokens;
375                         size_t tokens_len = split(&tokens, msgs[i], " ");
376
377                         fprintf(c_fp, "\ttype.%s = dragonnet_recv_%s(p);\n", tokens[1], &tokens[0][1]);
378                         free_split(tokens, tokens_len);
379                         tokens = NULL;
380                 }
381         }
382
383         fprintf(h_fp, "\n");
384         fprintf(c_fp, "\treturn type;\n");
385         fprintf(c_fp, "}\n");
386         msg = NULL;
387
388         // Create type enum
389         size_t last_msg = 0;
390         for (size_t i = 0; i < msgs_len; ++i)
391                 if (msgs[i][0] != '\t')
392                         last_msg = i;
393
394         fprintf(h_fp, "typedef enum {\n");
395         for (size_t i = 0; i < msgs_len; ++i) {
396                 if (msgs[i][0] == '\t')
397                         continue;
398
399                 char upper[1 + strlen(msgs[i])];
400                 char *ptr = upper;
401                 strcpy(upper, msgs[i]);
402
403                 while ((*ptr = *ptr ? toupper(*ptr) : '\0'))
404                         ++ptr;
405
406                 if (i == last_msg)
407                         fprintf(h_fp, "\tDRAGONNET_TYPE_%s\n", upper);
408                 else
409                         fprintf(h_fp, "\tDRAGONNET_TYPE_%s,\n", upper);
410         }
411
412         fprintf(h_fp, "} DragonnetType;\n");
413
414         free_split(msgs, msgs_len);
415         msgs = NULL;
416
417         fclose(c_fp);
418         fclose(h_fp);
419         c_fp = NULL;
420         h_fp = NULL;
421 }