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