1
2
3
4
5
6
7
8#include <ctype.h>
9#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <unistd.h>
15#include <regex.h>
16#include <inttypes.h>
17#include <termios.h>
18#include <poll.h>
19#include <sys/socket.h>
20
21struct statvfs {int i;};
22#include "lib/portability.h"
23#include "lib/lib.h"
24
25
26char toys[4096], libbuf[4096], toybuf[4096];
27void show_help(FILE *out) {;}
28void toy_exec(char *argv[]) {;}
29void toy_init(void *which, char *argv[]) {;}
30
31
32
33struct symbol {
34 struct symbol *next;
35 int enabled, help_indent;
36 char *name, *depends;
37 struct double_list *help;
38} *sym;
39
40
41char *skip_spaces(char *s)
42{
43 while (isspace(*s)) s++;
44
45 return s;
46}
47
48
49char *keyword(char *name, char *line)
50{
51 int len = strlen(name);
52
53 line = skip_spaces(line);
54 if (strncmp(name, line, len)) return 0;
55 line += len;
56 if (*line && !isspace(*line)) return 0;
57 line = skip_spaces(line);
58
59 return line;
60}
61
62
63char *dlist_zap(struct double_list **help)
64{
65 struct double_list *dd = dlist_pop(help);
66 char *s = dd->data;
67
68 free(dd);
69
70 return s;
71}
72
73int zap_blank_lines(struct double_list **help)
74{
75 int got = 0;
76
77 while (*help) {
78 char *s;
79
80 s = skip_spaces((*help)->data);
81
82 if (*s) break;
83 got++;
84 free(dlist_zap(help));
85 }
86
87 return got;
88}
89
90
91
92
93
94
95
96
97
98
99
100char **grab_dashlines(struct double_list **help, struct double_list **from,
101 int *len)
102{
103 struct double_list *dd;
104 char *s, **list;
105 int count = 0;
106
107 *len = 0;
108 zap_blank_lines(help);
109 *from = *help;
110
111
112 for (;;) {
113 s = skip_spaces((*from)->data);
114 if (*s == '-' && s[1] != '-' && !count) break;
115
116 if (!*s) count = 0;
117 else count++;
118
119 *from = (*from)->next;
120 if (*from == *help) return 0;
121 }
122
123
124
125
126 while (!*skip_spaces((*from)->prev->data)) {
127 *from = (*from)->prev;
128 free(dlist_zap(from));
129 }
130
131
132
133 count = 0;
134 dd = *from;
135 if (*help == *from) *help = 0;
136 for (;;) {
137 if (*skip_spaces(dd->data) != '-') break;
138 count++;
139 if (*from == (dd = dd->next)) break;
140 }
141
142 list = xmalloc(sizeof(char *)*count);
143 *len = count;
144 while (count) list[--count] = dlist_zap(from);
145
146 return list;
147}
148
149
150void parse(char *filename)
151{
152 FILE *fp = xfopen(filename, "r");
153 struct symbol *new = 0;
154
155 for (;;) {
156 char *s, *line = NULL;
157 size_t len;
158
159
160 if (getline(&line, &len, fp) < 1) break;
161 s = line+strlen(line);
162 while (--s >= line) {
163 if (!isspace(*s)) break;
164 *s = 0;
165 }
166
167
168 if (*line && !isspace(*line)) {
169 if ((s = keyword("config", line))) {
170 new = xzalloc(sizeof(struct symbol));
171 new->next = sym;
172 new->name = s;
173 sym = new;
174 } else if ((s = keyword("source", line))) parse(s);
175
176 continue;
177 }
178 if (!new) continue;
179
180 if (sym && sym->help_indent) {
181 dlist_add(&(new->help), line);
182 if (sym->help_indent < 0) {
183 sym->help_indent = 0;
184 while (isspace(line[sym->help_indent])) sym->help_indent++;
185 }
186 }
187 else if ((s = keyword("depends", line)) && (s = keyword("on", s)))
188 new->depends = s;
189 else if (keyword("help", line)) sym->help_indent = -1;
190 }
191
192 fclose(fp);
193}
194
195int charsort(void *a, void *b)
196{
197 char *aa = a, *bb = b;
198
199 if (*aa < *bb) return -1;
200 if (*aa > *bb) return 1;
201 return 0;
202}
203
204int dashsort(char **a, char **b)
205{
206 char *aa = *a, *bb = *b;
207
208 if (aa[1] < bb[1]) return -1;
209 if (aa[1] > bb[1]) return 1;
210 return 0;
211}
212
213int dashlinesort(char **a, char **b)
214{
215 return strcmp(*a, *b);
216}
217
218
219
220int main(int argc, char *argv[])
221{
222 FILE *fp;
223
224 if (argc != 3) {
225 fprintf(stderr, "usage: config2help Config.in .config\n");
226 exit(1);
227 }
228
229
230
231
232
233 parse(argv[1]);
234
235
236 fp = xfopen(argv[2], "r");
237 for (;;) {
238 char *line = NULL;
239 size_t len;
240
241 if (getline(&line, &len, fp) < 1) break;
242 if (!strncmp("CONFIG_", line, 7)) {
243 struct symbol *try;
244 char *s = line+7;
245
246 for (try=sym; try; try=try->next) {
247 len = strlen(try->name);
248 if (!strncmp(try->name, s, len) && s[len]=='=' && s[len+1]=='y') {
249 try->enabled++;
250 break;
251 }
252 }
253 }
254 }
255
256
257
258
259
260
261
262
263 for (;;) {
264 struct symbol *throw = 0, *catch;
265 char *this, *that, *cusage, *tusage, *name = 0;
266 int len;
267
268
269 for (catch = sym; catch; catch = catch->next) {
270 if (catch->enabled != 1) continue;
271 if (catch->help && (that = keyword("usage:", catch->help->data))) {
272 struct double_list *cfrom, *tfrom, *anchor;
273 char *try, **cdashlines, **tdashlines, *usage;
274 int clen, tlen;
275
276
277
278 if (!throw) usage = that;
279 else if (strncmp(name, that, len) || !isspace(that[len])) continue;
280 catch->enabled++;
281 while (!isspace(*that) && *that) that++;
282 if (!throw) len = that-usage;
283 free(name);
284 name = strndup(usage, len);
285 that = skip_spaces(that);
286 if (!throw) {
287 throw = catch;
288 this = that;
289
290 continue;
291 }
292
293
294 tusage = dlist_zap(&throw->help);
295 tdashlines = grab_dashlines(&throw->help, &tfrom, &tlen);
296 cusage = dlist_zap(&catch->help);
297 cdashlines = grab_dashlines(&catch->help, &cfrom, &clen);
298 anchor = catch->help;
299
300
301 if (cdashlines && tdashlines) {
302 char **new = xmalloc(sizeof(char *)*(clen+tlen));
303
304 memcpy(new, cdashlines, sizeof(char *)*clen);
305 memcpy(new+clen, tdashlines, sizeof(char *)*tlen);
306 free(cdashlines);
307 free(tdashlines);
308 qsort(new, clen+tlen, sizeof(char *), (void *)dashlinesort);
309 cdashlines = new;
310
311
312 } else if (tdashlines) cdashlines = tdashlines;
313
314
315
316 if (tfrom && tfrom != throw->help) {
317 if (throw->help || catch->help) dlist_add(&cfrom, strdup(""));
318 else {
319 dlist_add(&cfrom, 0);
320 anchor = cfrom->prev;
321 }
322 while (throw->help && throw->help != tfrom)
323 dlist_add(&cfrom, dlist_zap(&throw->help));
324 if (cfrom && cfrom->prev->data && *skip_spaces(cfrom->prev->data))
325 dlist_add(&cfrom, strdup(""));
326 }
327 if (!anchor) {
328 dlist_add(&cfrom, 0);
329 anchor = cfrom->prev;
330 }
331
332
333 if (cdashlines) {
334 tlen += clen;
335
336 for (clen = 0; clen < tlen; clen++)
337 dlist_add(&cfrom, cdashlines[clen]);
338 }
339
340
341
342 if (!anchor->data) dlist_zap(&anchor);
343
344
345 while (!*skip_spaces(anchor->prev->data)) {
346 anchor = anchor->prev;
347 free(dlist_zap(&anchor));
348 }
349
350
351 while (tfrom) dlist_add(&anchor, dlist_zap(&tfrom));
352
353
354 try = 0;
355 if (*this == '[' && this[1] == '-' && this[2] != '-' &&
356 *that == '[' && that[1] == '-' && that[2] != '-')
357 {
358 char *from = this+2, *to = that+2;
359 int ff = strcspn(from, " ]"), tt = strcspn(to, " ]");
360
361 if (from[ff] == ']' && to[tt] == ']') {
362 try = xmprintf("[-%.*s%.*s] ", ff, from, tt, to);
363 qsort(try+2, ff+tt, 1, (void *)charsort);
364 this = skip_spaces(this+ff+3);
365 that = skip_spaces(that+tt+3);
366 }
367 }
368
369
370 if (!anchor->data) dlist_zap(&anchor);
371
372
373 dlist_add(&anchor, xmprintf("%*cusage: %.*s %s%s%s%s",
374 catch->help_indent, ' ', len, name, try ? try : "",
375 this, *this ? " " : "", that));
376 free(try);
377 dlist_add(&anchor, strdup(""));
378 free(cusage);
379 free(tusage);
380 throw->enabled = 0;
381 throw = catch;
382 throw->help = anchor->prev->prev;
383
384 throw = catch;
385 this = throw->help->data + throw->help_indent + 8 + len;
386 }
387 }
388
389
390
391 if (!throw) break;
392 }
393
394
395
396
397 while (sym) {
398 struct double_list *dd;
399
400 if (sym->help) {
401 int i;
402 char *s = xstrdup(sym->name);
403
404 for (i = 0; s[i]; i++) s[i] = tolower(s[i]);
405 printf("#define HELP_%s \"", s);
406 free(s);
407
408 dd = sym->help;
409 for (;;) {
410 i = sym->help_indent;
411
412
413 s = dd->data;
414 while (isspace(*s) && i) {
415 s++;
416 i--;
417 }
418 for (i=0; s[i]; i++) {
419 if (s[i] == '"' || s[i] == '\\') putchar('\\');
420 putchar(s[i]);
421 }
422 putchar('\\');
423 putchar('n');
424 dd = dd->next;
425 if (dd == sym->help) break;
426 }
427 printf("\"\n\n");
428 }
429 sym = sym->next;
430 }
431
432 return 0;
433}
434