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