1
2
3
4
5
6
7
8
9#include <unistd.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <errno.h>
14#include <ctype.h>
15
16struct flag {
17 struct flag *next;
18 char *command;
19 struct flag *lopt;
20};
21
22int chrtype(char c)
23{
24
25 if (strchr("^-:#|@*; %.", c)) return 1;
26
27
28 if (strchr("=<>", c)) return 2;
29
30 if (strchr("?&0", c)) return 3;
31
32 return 0;
33}
34
35
36
37
38char *mark_gaps(char *flags, char *all)
39{
40 char *n, *new, c;
41 int bare = 2;
42
43
44 while (isspace(*flags)) flags++;
45 while (isspace(*all)) all++;
46
47 n = new = strdup(all);
48 while (*all) {
49
50 if (*all == '(') {
51 int len = 0;
52
53 if (bare) bare = 1;
54 while (all[len]) if (all[len++] == ')') break;
55 if (strncmp(flags, all, len)) {
56
57 if (bare) *(new++) = 1;
58 } else {
59 memcpy(new, all, len);
60 new += len;
61 flags += len;
62 }
63 all += len;
64 continue;
65 }
66 c = *(all++);
67 if (bare && !chrtype(c)) bare = 0;
68 if (*flags == c) {
69 *(new++) = c;
70 flags++;
71 continue;
72 }
73
74 c = chrtype(c);
75 if (!c || (!bare && c==3)) *(new++) = 1;
76 else if (c==2) while (isdigit(*all)) all++;
77 }
78 *new = 0;
79
80 return n;
81}
82
83
84
85struct flag *digest(char *string)
86{
87 struct flag *list = 0;
88 char *err = string, c;
89
90 while (*string) {
91
92 if (*string == '[') break;
93
94
95 if (*string == '(') {
96 struct flag *new = calloc(sizeof(struct flag), 1);
97
98 new->command = ++string;
99
100
101 if (list && list->command) {
102 new->next = list->lopt;
103 list->lopt = new;
104 } else {
105 struct flag *blank = calloc(sizeof(struct flag), 1);
106
107 blank->next = list;
108 blank->lopt = new;
109 list = blank;
110 }
111
112 while (*++string != ')') if (*string == '-') *string = '_';
113 *(string++) = 0;
114 continue;
115 }
116
117 c = chrtype(*string);
118 if (c == 1 || (c == 3 && !list)) string++;
119 else if (c == 2) {
120 if (string[1]=='-') string++;
121 if (!isdigit(string[1])) {
122 fprintf(stderr, "%c without number in '%s'", *string, err);
123 exit(1);
124 }
125 while (isdigit(*++string)) {
126 if (!list) {
127 string++;
128 break;
129 }
130 }
131 } else {
132 struct flag *new = calloc(sizeof(struct flag), 1);
133
134 new->command = string++;
135 new->next = list;
136 list = new;
137 }
138 }
139
140 return list;
141}
142
143
144void octane(char *from)
145{
146 unsigned char *to = (void *)from;
147
148 while (*from) {
149 if (*from == '\\') {
150 *to = 0;
151 while (isdigit(*++from)) *to = (8**to)+*from-'0';
152 to++;
153 } else *to++ = *from++;
154 }
155 *to = 0;
156}
157
158int main(int argc, char *argv[])
159{
160 char command[256], flags[1024], allflags[1024];
161 char *out, *outbuf = malloc(1024*1024);
162
163
164
165 if (!(out = outbuf)) return 1;
166
167 printf("#undef FORCED_FLAG\n#undef FORCED_FLAGLL\n"
168 "#ifdef FORCE_FLAGS\n#define FORCED_FLAG 1\n#define FORCED_FLAGLL 1ULL\n"
169 "#else\n#define FORCED_FLAG 0\n#define FORCED_FLAGLL 0\n#endif\n\n");
170
171 for (;;) {
172 struct flag *flist, *aflist, *offlist;
173 char *mgaps = 0;
174 unsigned bit;
175
176 *command = *flags = *allflags = 0;
177 bit = fscanf(stdin, "%255s \"%1023[^\"]\" \"%1023[^\"]\"\n",
178 command, flags, allflags);
179 octane(flags);
180 octane(allflags);
181
182 if (getenv("DEBUG"))
183 fprintf(stderr, "command=%s, flags=%s, allflags=%s\n",
184 command, flags, allflags);
185
186 if (!*command) break;
187 if (bit != 3) {
188 fprintf(stderr, "\nError in %s (see generated/flags.raw)\n", command);
189 exit(1);
190 }
191
192 bit = 0;
193 printf("// %s %s %s\n", command, flags, allflags);
194 if (*flags != ' ') mgaps = mark_gaps(flags, allflags);
195 else if (*allflags != ' ') mgaps = allflags;
196
197 printf("#undef OPTSTR_%s\n#define OPTSTR_%s ", command, command);
198 if (mgaps) printf("\"%s\"\n", mgaps);
199 else printf("0\n");
200 if (mgaps != allflags) free(mgaps);
201
202 flist = digest(flags);
203 offlist = aflist = digest(allflags);
204
205 printf("#ifdef CLEANUP_%s\n#undef CLEANUP_%s\n#undef FOR_%s\n",
206 command, command, command);
207
208 while (offlist) {
209 char *s = (char []){0, 0, 0, 0};
210
211 if (!offlist->command) s = offlist->lopt->command;
212 else {
213 *s = *offlist->command;
214 if (127 < (unsigned char)*s) sprintf(s, "X%02X", 127&*s);
215 }
216 printf("#undef FLAG_%s\n", s);
217 offlist = offlist->next;
218 }
219 printf("#endif\n\n");
220
221 sprintf(out, "#ifdef FOR_%s\n#ifndef TT\n#define TT this.%s\n#endif\n",
222 command, command);
223 out += strlen(out);
224
225 while (aflist) {
226 char *llstr = bit>30 ? "LL" : "", *s = (char []){0, 0, 0, 0};
227 int enabled = 0;
228
229
230 if (!aflist->command) {
231 s = aflist->lopt->command;
232 if (flist && flist->lopt &&
233 !strcmp(flist->lopt->command, aflist->lopt->command)) enabled++;
234
235 } else {
236 *s = *aflist->command;
237 if (127 < (unsigned char)*s) sprintf(s, "X%02X", 127&*s);
238 if (flist && flist->command && *aflist->command == *flist->command)
239 enabled++;
240 }
241 out += sprintf(out, "#define FLAG_%s (%s%s<<%d)\n",
242 s, enabled ? "1" : "FORCED_FLAG", llstr, bit++);
243 aflist = aflist->next;
244 if (enabled) flist = flist->next;
245 }
246 out = stpcpy(out, "#endif\n\n");
247 }
248
249 if (fflush(0) && ferror(stdout)) return 1;
250
251 out = outbuf;
252 while (*out) {
253 int i = write(1, outbuf, strlen(outbuf));
254
255 if (i<0) return 1;
256 out += i;
257 }
258
259 return 0;
260}
261