]> git.lizzy.rs Git - dragonnet.git/blob - typegen/main.c
86cc706dd1cae72ffedf7d626cc61babb29bd15d
[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 int main(__attribute((unused)) int argc, __attribute((unused)) char **argv)
36 {
37         FILE *fp = fopen("types.dnet", "r");
38
39         char data[1 << 16];
40         memset(data, '\0', sizeof data);
41         fread(data, sizeof *data, sizeof data, fp);
42
43         fclose(fp);
44         fp = NULL;
45
46         FILE *c_fp = fopen("dnet-types.c", "w");
47         fprintf(c_fp, "#include <dragonnet/recv.h>\n");
48         fprintf(c_fp, "#include <dragonnet/send.h>\n\n");
49         fprintf(c_fp, "#include \"dnet-types.h\"\n\n");
50
51         FILE *h_fp = fopen("dnet-types.h", "w");
52         fprintf(h_fp, "#include <dragontype/number.h>\n\n");
53
54         char **msgs;
55         size_t msgs_len = split(&msgs, data, "\n");
56
57         // Create data types
58         char *msg = NULL;
59         for (size_t i = 0; i < msgs_len; ++i) {
60                 if (msgs[i][0] != '\t') {
61                         if (msg != NULL)
62                                 fprintf(h_fp, "} %s;\n\n", msg);
63
64                         msg = msgs[i];
65                         fprintf(h_fp, "typedef struct {\n");
66                 } else {
67                         char **tokens;
68                         size_t tokens_len = split(&tokens, msgs[i], " ");
69
70                         fprintf(h_fp, "\t%s %s;\n", &tokens[0][1], tokens[1]);
71                         free_split(tokens, tokens_len);
72                         tokens = NULL;
73                 }
74         }
75
76         fprintf(h_fp, "} %s;\n\n", msg);
77         msg = NULL;
78
79         // Create (de)serialization functions
80         for (size_t i = 0; i < msgs_len; ++i) {
81                 if (msgs[i][0] != '\t') {
82                         if (msg != NULL)
83                                 fprintf(c_fp, "}\n\n");
84
85                         msg = msgs[i];
86                         fprintf(c_fp, "void dragonnet_send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg);
87                 } else {
88                         char **tokens;
89                         size_t tokens_len = split(&tokens, msgs[i], " ");
90
91                         if (i >= msgs_len-1 || msgs[1+i][0] != '\t')
92                                 fprintf(c_fp, "\tsend_%s(p, true, type.%s);\n", &tokens[0][1], tokens[1]);
93                         else
94                                 fprintf(c_fp, "\tsend_%s(p, false, type.%s);\n", &tokens[0][1], tokens[1]);
95
96                         free_split(tokens, tokens_len);
97                         tokens = NULL;
98                 }
99         }
100
101         fprintf(c_fp, "}\n\n");
102         msg = NULL;
103
104         for (size_t i = 0; i < msgs_len; ++i) {
105                 if (msgs[i][0] != '\t') {
106                         if (msg != NULL) {
107                                 fprintf(c_fp, "\treturn type;\n");
108                                 fprintf(c_fp, "}\n\n");
109                         }
110
111                         msg = msgs[i];
112                         fprintf(c_fp, "%s dragonnet_recv_%s(DragonnetPeer *p)\n{\n", msg, msg);
113                         fprintf(c_fp, "\t%s type = {0};\n", msg);
114                 } else {
115                         char **tokens;
116                         size_t tokens_len = split(&tokens, msgs[i], " ");
117
118                         fprintf(c_fp, "\ttype.%s = recv_%s(p);\n", tokens[1], &tokens[0][1]);
119                         free_split(tokens, tokens_len);
120                         tokens = NULL;
121                 }
122         }
123
124         fprintf(c_fp, "\treturn type;\n");
125         fprintf(c_fp, "}\n");
126         msg = NULL;
127
128         // Create type enum
129         size_t last_msg = 0;
130         for (size_t i = 0; i < msgs_len; ++i)
131                 if (msgs[i][0] != '\t')
132                         last_msg = i;
133
134         fprintf(h_fp, "typedef enum {\n");
135         for (size_t i = 0; i < msgs_len; ++i) {
136                 if (msgs[i][0] == '\t')
137                         continue;
138
139                 char upper[1 + strlen(msgs[i])];
140                 char *ptr = upper;
141                 strcpy(upper, msgs[i]);
142
143                 while ((*ptr = *ptr ? toupper(*ptr) : '\0'))
144                         ++ptr;
145
146                 if (i == last_msg)
147                         fprintf(h_fp, "\tDRAGONNET_TYPE_%s\n", upper);
148                 else
149                         fprintf(h_fp, "\tDRAGONNET_TYPE_%s,\n", upper);
150         }
151
152         fprintf(h_fp, "} DragonnetType;\n");
153
154         free_split(msgs, msgs_len);
155         msgs = NULL;
156
157         fclose(c_fp);
158         fclose(h_fp);
159         c_fp = NULL;
160         h_fp = NULL;
161 }