1*cf5a6c84SAndroid Build Coastguard Worker /* config2.help.c - config2hep Config.in .config > help.h
2*cf5a6c84SAndroid Build Coastguard Worker
3*cf5a6c84SAndroid Build Coastguard Worker function parse() reads Config.in data into *sym list, then
4*cf5a6c84SAndroid Build Coastguard Worker we read .config and set sym->try on each enabled symbol.
5*cf5a6c84SAndroid Build Coastguard Worker
6*cf5a6c84SAndroid Build Coastguard Worker */
7*cf5a6c84SAndroid Build Coastguard Worker
8*cf5a6c84SAndroid Build Coastguard Worker #include <ctype.h>
9*cf5a6c84SAndroid Build Coastguard Worker #include <stdio.h>
10*cf5a6c84SAndroid Build Coastguard Worker #include <string.h>
11*cf5a6c84SAndroid Build Coastguard Worker #include <stdarg.h>
12*cf5a6c84SAndroid Build Coastguard Worker #include <stdlib.h>
13*cf5a6c84SAndroid Build Coastguard Worker #include <sys/types.h>
14*cf5a6c84SAndroid Build Coastguard Worker #include <sys/stat.h>
15*cf5a6c84SAndroid Build Coastguard Worker #include <unistd.h>
16*cf5a6c84SAndroid Build Coastguard Worker #include <regex.h>
17*cf5a6c84SAndroid Build Coastguard Worker #include <inttypes.h>
18*cf5a6c84SAndroid Build Coastguard Worker #include <termios.h>
19*cf5a6c84SAndroid Build Coastguard Worker #include <poll.h>
20*cf5a6c84SAndroid Build Coastguard Worker #include <sys/socket.h>
21*cf5a6c84SAndroid Build Coastguard Worker
22*cf5a6c84SAndroid Build Coastguard Worker //****************** functions copied from lib/*.c ********************
23*cf5a6c84SAndroid Build Coastguard Worker
24*cf5a6c84SAndroid Build Coastguard Worker struct double_list {
25*cf5a6c84SAndroid Build Coastguard Worker struct double_list *next, *prev;
26*cf5a6c84SAndroid Build Coastguard Worker char *data;
27*cf5a6c84SAndroid Build Coastguard Worker };
28*cf5a6c84SAndroid Build Coastguard Worker
29*cf5a6c84SAndroid Build Coastguard Worker // Die unless we can allocate memory.
xmalloc(size_t size)30*cf5a6c84SAndroid Build Coastguard Worker void *xmalloc(size_t size)
31*cf5a6c84SAndroid Build Coastguard Worker {
32*cf5a6c84SAndroid Build Coastguard Worker void *ret = malloc(size);
33*cf5a6c84SAndroid Build Coastguard Worker if (!ret) {
34*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, "xmalloc(%ld)", (long)size);
35*cf5a6c84SAndroid Build Coastguard Worker exit(1);
36*cf5a6c84SAndroid Build Coastguard Worker }
37*cf5a6c84SAndroid Build Coastguard Worker
38*cf5a6c84SAndroid Build Coastguard Worker return ret;
39*cf5a6c84SAndroid Build Coastguard Worker }
40*cf5a6c84SAndroid Build Coastguard Worker
41*cf5a6c84SAndroid Build Coastguard Worker // Die unless we can allocate enough space to sprintf() into.
xmprintf(char * format,...)42*cf5a6c84SAndroid Build Coastguard Worker char *xmprintf(char *format, ...)
43*cf5a6c84SAndroid Build Coastguard Worker {
44*cf5a6c84SAndroid Build Coastguard Worker va_list va, va2;
45*cf5a6c84SAndroid Build Coastguard Worker int len;
46*cf5a6c84SAndroid Build Coastguard Worker char *ret;
47*cf5a6c84SAndroid Build Coastguard Worker
48*cf5a6c84SAndroid Build Coastguard Worker va_start(va, format);
49*cf5a6c84SAndroid Build Coastguard Worker va_copy(va2, va);
50*cf5a6c84SAndroid Build Coastguard Worker
51*cf5a6c84SAndroid Build Coastguard Worker // How long is it?
52*cf5a6c84SAndroid Build Coastguard Worker len = vsnprintf(0, 0, format, va);
53*cf5a6c84SAndroid Build Coastguard Worker len++;
54*cf5a6c84SAndroid Build Coastguard Worker va_end(va);
55*cf5a6c84SAndroid Build Coastguard Worker
56*cf5a6c84SAndroid Build Coastguard Worker // Allocate and do the sprintf()
57*cf5a6c84SAndroid Build Coastguard Worker ret = xmalloc(len);
58*cf5a6c84SAndroid Build Coastguard Worker vsnprintf(ret, len, format, va2);
59*cf5a6c84SAndroid Build Coastguard Worker va_end(va2);
60*cf5a6c84SAndroid Build Coastguard Worker
61*cf5a6c84SAndroid Build Coastguard Worker return ret;
62*cf5a6c84SAndroid Build Coastguard Worker }
63*cf5a6c84SAndroid Build Coastguard Worker
64*cf5a6c84SAndroid Build Coastguard Worker // Die unless we can open/create a file, returning FILE *.
xfopen(char * path,char * mode)65*cf5a6c84SAndroid Build Coastguard Worker FILE *xfopen(char *path, char *mode)
66*cf5a6c84SAndroid Build Coastguard Worker {
67*cf5a6c84SAndroid Build Coastguard Worker FILE *f = fopen(path, mode);
68*cf5a6c84SAndroid Build Coastguard Worker if (!f) {
69*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, "No file %s", path);
70*cf5a6c84SAndroid Build Coastguard Worker exit(1);
71*cf5a6c84SAndroid Build Coastguard Worker }
72*cf5a6c84SAndroid Build Coastguard Worker return f;
73*cf5a6c84SAndroid Build Coastguard Worker }
74*cf5a6c84SAndroid Build Coastguard Worker
dlist_pop(void * list)75*cf5a6c84SAndroid Build Coastguard Worker void *dlist_pop(void *list)
76*cf5a6c84SAndroid Build Coastguard Worker {
77*cf5a6c84SAndroid Build Coastguard Worker struct double_list **pdlist = (struct double_list **)list, *dlist = *pdlist;
78*cf5a6c84SAndroid Build Coastguard Worker
79*cf5a6c84SAndroid Build Coastguard Worker if (dlist->next == dlist) *pdlist = 0;
80*cf5a6c84SAndroid Build Coastguard Worker else {
81*cf5a6c84SAndroid Build Coastguard Worker dlist->next->prev = dlist->prev;
82*cf5a6c84SAndroid Build Coastguard Worker dlist->prev->next = *pdlist = dlist->next;
83*cf5a6c84SAndroid Build Coastguard Worker }
84*cf5a6c84SAndroid Build Coastguard Worker
85*cf5a6c84SAndroid Build Coastguard Worker return dlist;
86*cf5a6c84SAndroid Build Coastguard Worker }
87*cf5a6c84SAndroid Build Coastguard Worker
dlist_add_nomalloc(struct double_list ** list,struct double_list * new)88*cf5a6c84SAndroid Build Coastguard Worker void dlist_add_nomalloc(struct double_list **list, struct double_list *new)
89*cf5a6c84SAndroid Build Coastguard Worker {
90*cf5a6c84SAndroid Build Coastguard Worker if (*list) {
91*cf5a6c84SAndroid Build Coastguard Worker new->next = *list;
92*cf5a6c84SAndroid Build Coastguard Worker new->prev = (*list)->prev;
93*cf5a6c84SAndroid Build Coastguard Worker (*list)->prev->next = new;
94*cf5a6c84SAndroid Build Coastguard Worker (*list)->prev = new;
95*cf5a6c84SAndroid Build Coastguard Worker } else *list = new->next = new->prev = new;
96*cf5a6c84SAndroid Build Coastguard Worker }
97*cf5a6c84SAndroid Build Coastguard Worker
98*cf5a6c84SAndroid Build Coastguard Worker
99*cf5a6c84SAndroid Build Coastguard Worker // Add an entry to the end of a doubly linked list
dlist_add(struct double_list ** list,char * data)100*cf5a6c84SAndroid Build Coastguard Worker struct double_list *dlist_add(struct double_list **list, char *data)
101*cf5a6c84SAndroid Build Coastguard Worker {
102*cf5a6c84SAndroid Build Coastguard Worker struct double_list *new = xmalloc(sizeof(struct double_list));
103*cf5a6c84SAndroid Build Coastguard Worker
104*cf5a6c84SAndroid Build Coastguard Worker new->data = data;
105*cf5a6c84SAndroid Build Coastguard Worker dlist_add_nomalloc(list, new);
106*cf5a6c84SAndroid Build Coastguard Worker
107*cf5a6c84SAndroid Build Coastguard Worker return new;
108*cf5a6c84SAndroid Build Coastguard Worker }
109*cf5a6c84SAndroid Build Coastguard Worker
110*cf5a6c84SAndroid Build Coastguard Worker //****************** end copies of lib/*.c *************
111*cf5a6c84SAndroid Build Coastguard Worker
112*cf5a6c84SAndroid Build Coastguard Worker // Parse config files into data structures.
113*cf5a6c84SAndroid Build Coastguard Worker
114*cf5a6c84SAndroid Build Coastguard Worker struct symbol {
115*cf5a6c84SAndroid Build Coastguard Worker struct symbol *next;
116*cf5a6c84SAndroid Build Coastguard Worker int enabled, help_indent;
117*cf5a6c84SAndroid Build Coastguard Worker char *name, *depends;
118*cf5a6c84SAndroid Build Coastguard Worker struct double_list *help;
119*cf5a6c84SAndroid Build Coastguard Worker } *sym;
120*cf5a6c84SAndroid Build Coastguard Worker
121*cf5a6c84SAndroid Build Coastguard Worker // remove leading spaces
skip_spaces(char * s)122*cf5a6c84SAndroid Build Coastguard Worker char *skip_spaces(char *s)
123*cf5a6c84SAndroid Build Coastguard Worker {
124*cf5a6c84SAndroid Build Coastguard Worker while (isspace(*s)) s++;
125*cf5a6c84SAndroid Build Coastguard Worker
126*cf5a6c84SAndroid Build Coastguard Worker return s;
127*cf5a6c84SAndroid Build Coastguard Worker }
128*cf5a6c84SAndroid Build Coastguard Worker
129*cf5a6c84SAndroid Build Coastguard Worker // if line starts with name (as whole word) return pointer after it, else NULL
keyword(char * name,char * line)130*cf5a6c84SAndroid Build Coastguard Worker char *keyword(char *name, char *line)
131*cf5a6c84SAndroid Build Coastguard Worker {
132*cf5a6c84SAndroid Build Coastguard Worker int len = strlen(name);
133*cf5a6c84SAndroid Build Coastguard Worker
134*cf5a6c84SAndroid Build Coastguard Worker line = skip_spaces(line);
135*cf5a6c84SAndroid Build Coastguard Worker if (strncmp(name, line, len)) return 0;
136*cf5a6c84SAndroid Build Coastguard Worker line += len;
137*cf5a6c84SAndroid Build Coastguard Worker if (*line && !isspace(*line)) return 0;
138*cf5a6c84SAndroid Build Coastguard Worker line = skip_spaces(line);
139*cf5a6c84SAndroid Build Coastguard Worker
140*cf5a6c84SAndroid Build Coastguard Worker return line;
141*cf5a6c84SAndroid Build Coastguard Worker }
142*cf5a6c84SAndroid Build Coastguard Worker
143*cf5a6c84SAndroid Build Coastguard Worker // dlist_pop() freeing wrapper structure for you.
dlist_zap(struct double_list ** help)144*cf5a6c84SAndroid Build Coastguard Worker char *dlist_zap(struct double_list **help)
145*cf5a6c84SAndroid Build Coastguard Worker {
146*cf5a6c84SAndroid Build Coastguard Worker struct double_list *dd = dlist_pop(help);
147*cf5a6c84SAndroid Build Coastguard Worker char *s = dd->data;
148*cf5a6c84SAndroid Build Coastguard Worker
149*cf5a6c84SAndroid Build Coastguard Worker free(dd);
150*cf5a6c84SAndroid Build Coastguard Worker
151*cf5a6c84SAndroid Build Coastguard Worker return s;
152*cf5a6c84SAndroid Build Coastguard Worker }
153*cf5a6c84SAndroid Build Coastguard Worker
zap_blank_lines(struct double_list ** help)154*cf5a6c84SAndroid Build Coastguard Worker int zap_blank_lines(struct double_list **help)
155*cf5a6c84SAndroid Build Coastguard Worker {
156*cf5a6c84SAndroid Build Coastguard Worker int got = 0;
157*cf5a6c84SAndroid Build Coastguard Worker
158*cf5a6c84SAndroid Build Coastguard Worker while (*help) {
159*cf5a6c84SAndroid Build Coastguard Worker char *s;
160*cf5a6c84SAndroid Build Coastguard Worker
161*cf5a6c84SAndroid Build Coastguard Worker s = skip_spaces((*help)->data);
162*cf5a6c84SAndroid Build Coastguard Worker
163*cf5a6c84SAndroid Build Coastguard Worker if (*s) break;
164*cf5a6c84SAndroid Build Coastguard Worker got++;
165*cf5a6c84SAndroid Build Coastguard Worker free(dlist_zap(help));
166*cf5a6c84SAndroid Build Coastguard Worker }
167*cf5a6c84SAndroid Build Coastguard Worker
168*cf5a6c84SAndroid Build Coastguard Worker return got;
169*cf5a6c84SAndroid Build Coastguard Worker }
170*cf5a6c84SAndroid Build Coastguard Worker
171*cf5a6c84SAndroid Build Coastguard Worker // Collect "-a blah" description lines following a blank line (or start).
172*cf5a6c84SAndroid Build Coastguard Worker // Returns array of removed lines with *len entries (0 for none).
173*cf5a6c84SAndroid Build Coastguard Worker
174*cf5a6c84SAndroid Build Coastguard Worker // Moves *help to new start of text (in case dash lines were at beginning).
175*cf5a6c84SAndroid Build Coastguard Worker // Sets *from to where dash lines removed from (in case they weren't).
176*cf5a6c84SAndroid Build Coastguard Worker // Discards blank lines before and after dashlines.
177*cf5a6c84SAndroid Build Coastguard Worker
178*cf5a6c84SAndroid Build Coastguard Worker // If no prefix, *help NULL. If no postfix, *from == *help
179*cf5a6c84SAndroid Build Coastguard Worker // if no dashlines returned *from == *help.
180*cf5a6c84SAndroid Build Coastguard Worker
grab_dashlines(struct double_list ** help,struct double_list ** from,int * len)181*cf5a6c84SAndroid Build Coastguard Worker char **grab_dashlines(struct double_list **help, struct double_list **from,
182*cf5a6c84SAndroid Build Coastguard Worker int *len)
183*cf5a6c84SAndroid Build Coastguard Worker {
184*cf5a6c84SAndroid Build Coastguard Worker struct double_list *dd;
185*cf5a6c84SAndroid Build Coastguard Worker char *s, **list;
186*cf5a6c84SAndroid Build Coastguard Worker int count = 0;
187*cf5a6c84SAndroid Build Coastguard Worker
188*cf5a6c84SAndroid Build Coastguard Worker *len = 0;
189*cf5a6c84SAndroid Build Coastguard Worker zap_blank_lines(help);
190*cf5a6c84SAndroid Build Coastguard Worker *from = *help;
191*cf5a6c84SAndroid Build Coastguard Worker
192*cf5a6c84SAndroid Build Coastguard Worker // Find start of dash block. Must be at start or after blank line.
193*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
194*cf5a6c84SAndroid Build Coastguard Worker s = skip_spaces((*from)->data);
195*cf5a6c84SAndroid Build Coastguard Worker if (*s == '-' && s[1] != '-' && !count) break;
196*cf5a6c84SAndroid Build Coastguard Worker
197*cf5a6c84SAndroid Build Coastguard Worker if (!*s) count = 0;
198*cf5a6c84SAndroid Build Coastguard Worker else count++;
199*cf5a6c84SAndroid Build Coastguard Worker
200*cf5a6c84SAndroid Build Coastguard Worker *from = (*from)->next;
201*cf5a6c84SAndroid Build Coastguard Worker if (*from == *help) return 0;
202*cf5a6c84SAndroid Build Coastguard Worker }
203*cf5a6c84SAndroid Build Coastguard Worker
204*cf5a6c84SAndroid Build Coastguard Worker // If there was whitespace before this, zap it. This can't take out *help
205*cf5a6c84SAndroid Build Coastguard Worker // because zap_blank_lines skipped blank lines, and we had to have at least
206*cf5a6c84SAndroid Build Coastguard Worker // one non-blank line (a dash line) to get this far.
207*cf5a6c84SAndroid Build Coastguard Worker while (!*skip_spaces((*from)->prev->data)) {
208*cf5a6c84SAndroid Build Coastguard Worker *from = (*from)->prev;
209*cf5a6c84SAndroid Build Coastguard Worker free(dlist_zap(from));
210*cf5a6c84SAndroid Build Coastguard Worker }
211*cf5a6c84SAndroid Build Coastguard Worker
212*cf5a6c84SAndroid Build Coastguard Worker // Count number of dashlines, copy out to array, zap trailing whitespace
213*cf5a6c84SAndroid Build Coastguard Worker // If *help was at start of dashblock, move it with *from
214*cf5a6c84SAndroid Build Coastguard Worker count = 0;
215*cf5a6c84SAndroid Build Coastguard Worker dd = *from;
216*cf5a6c84SAndroid Build Coastguard Worker if (*help == *from) *help = 0;
217*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
218*cf5a6c84SAndroid Build Coastguard Worker if (*skip_spaces(dd->data) != '-') break;
219*cf5a6c84SAndroid Build Coastguard Worker count++;
220*cf5a6c84SAndroid Build Coastguard Worker if (*from == (dd = dd->next)) break;
221*cf5a6c84SAndroid Build Coastguard Worker }
222*cf5a6c84SAndroid Build Coastguard Worker
223*cf5a6c84SAndroid Build Coastguard Worker list = xmalloc(sizeof(char *)*count);
224*cf5a6c84SAndroid Build Coastguard Worker *len = count;
225*cf5a6c84SAndroid Build Coastguard Worker while (count) list[--count] = dlist_zap(from);
226*cf5a6c84SAndroid Build Coastguard Worker
227*cf5a6c84SAndroid Build Coastguard Worker return list;
228*cf5a6c84SAndroid Build Coastguard Worker }
229*cf5a6c84SAndroid Build Coastguard Worker
230*cf5a6c84SAndroid Build Coastguard Worker // Read Config.in (and includes) to populate global struct symbol *sym list.
parse(char * filename)231*cf5a6c84SAndroid Build Coastguard Worker void parse(char *filename)
232*cf5a6c84SAndroid Build Coastguard Worker {
233*cf5a6c84SAndroid Build Coastguard Worker FILE *fp = xfopen(filename, "r");
234*cf5a6c84SAndroid Build Coastguard Worker struct symbol *new = 0;
235*cf5a6c84SAndroid Build Coastguard Worker
236*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
237*cf5a6c84SAndroid Build Coastguard Worker char *s, *line = NULL;
238*cf5a6c84SAndroid Build Coastguard Worker size_t len;
239*cf5a6c84SAndroid Build Coastguard Worker
240*cf5a6c84SAndroid Build Coastguard Worker // Read line, trim whitespace at right edge.
241*cf5a6c84SAndroid Build Coastguard Worker if (getline(&line, &len, fp) < 1) break;
242*cf5a6c84SAndroid Build Coastguard Worker s = line+strlen(line);
243*cf5a6c84SAndroid Build Coastguard Worker while (--s >= line) {
244*cf5a6c84SAndroid Build Coastguard Worker if (!isspace(*s)) break;
245*cf5a6c84SAndroid Build Coastguard Worker *s = 0;
246*cf5a6c84SAndroid Build Coastguard Worker }
247*cf5a6c84SAndroid Build Coastguard Worker
248*cf5a6c84SAndroid Build Coastguard Worker // source or config keyword at left edge?
249*cf5a6c84SAndroid Build Coastguard Worker if (*line && !isspace(*line)) {
250*cf5a6c84SAndroid Build Coastguard Worker if ((s = keyword("config", line))) {
251*cf5a6c84SAndroid Build Coastguard Worker memset(new = xmalloc(sizeof(struct symbol)), 0, sizeof(struct symbol));
252*cf5a6c84SAndroid Build Coastguard Worker new->next = sym;
253*cf5a6c84SAndroid Build Coastguard Worker new->name = s;
254*cf5a6c84SAndroid Build Coastguard Worker sym = new;
255*cf5a6c84SAndroid Build Coastguard Worker } else if ((s = keyword("source", line))) parse(s);
256*cf5a6c84SAndroid Build Coastguard Worker
257*cf5a6c84SAndroid Build Coastguard Worker continue;
258*cf5a6c84SAndroid Build Coastguard Worker }
259*cf5a6c84SAndroid Build Coastguard Worker if (!new) continue;
260*cf5a6c84SAndroid Build Coastguard Worker
261*cf5a6c84SAndroid Build Coastguard Worker if (sym && sym->help_indent) {
262*cf5a6c84SAndroid Build Coastguard Worker dlist_add(&(new->help), line);
263*cf5a6c84SAndroid Build Coastguard Worker if (sym->help_indent < 0) {
264*cf5a6c84SAndroid Build Coastguard Worker sym->help_indent = 0;
265*cf5a6c84SAndroid Build Coastguard Worker while (isspace(line[sym->help_indent])) sym->help_indent++;
266*cf5a6c84SAndroid Build Coastguard Worker }
267*cf5a6c84SAndroid Build Coastguard Worker }
268*cf5a6c84SAndroid Build Coastguard Worker else if ((s = keyword("depends", line)) && (s = keyword("on", s)))
269*cf5a6c84SAndroid Build Coastguard Worker new->depends = s;
270*cf5a6c84SAndroid Build Coastguard Worker else if (keyword("help", line)) sym->help_indent = -1;
271*cf5a6c84SAndroid Build Coastguard Worker }
272*cf5a6c84SAndroid Build Coastguard Worker
273*cf5a6c84SAndroid Build Coastguard Worker fclose(fp);
274*cf5a6c84SAndroid Build Coastguard Worker }
275*cf5a6c84SAndroid Build Coastguard Worker
charsort(void * a,void * b)276*cf5a6c84SAndroid Build Coastguard Worker int charsort(void *a, void *b)
277*cf5a6c84SAndroid Build Coastguard Worker {
278*cf5a6c84SAndroid Build Coastguard Worker char *aa = a, *bb = b;
279*cf5a6c84SAndroid Build Coastguard Worker
280*cf5a6c84SAndroid Build Coastguard Worker if (*aa < *bb) return -1;
281*cf5a6c84SAndroid Build Coastguard Worker if (*aa > *bb) return 1;
282*cf5a6c84SAndroid Build Coastguard Worker return 0;
283*cf5a6c84SAndroid Build Coastguard Worker }
284*cf5a6c84SAndroid Build Coastguard Worker
dashsort(char ** a,char ** b)285*cf5a6c84SAndroid Build Coastguard Worker int dashsort(char **a, char **b)
286*cf5a6c84SAndroid Build Coastguard Worker {
287*cf5a6c84SAndroid Build Coastguard Worker char *aa = *a, *bb = *b;
288*cf5a6c84SAndroid Build Coastguard Worker
289*cf5a6c84SAndroid Build Coastguard Worker if (aa[1] < bb[1]) return -1;
290*cf5a6c84SAndroid Build Coastguard Worker if (aa[1] > bb[1]) return 1;
291*cf5a6c84SAndroid Build Coastguard Worker return 0;
292*cf5a6c84SAndroid Build Coastguard Worker }
293*cf5a6c84SAndroid Build Coastguard Worker
dashlinesort(char ** a,char ** b)294*cf5a6c84SAndroid Build Coastguard Worker int dashlinesort(char **a, char **b)
295*cf5a6c84SAndroid Build Coastguard Worker {
296*cf5a6c84SAndroid Build Coastguard Worker return strcmp(*a, *b);
297*cf5a6c84SAndroid Build Coastguard Worker }
298*cf5a6c84SAndroid Build Coastguard Worker
299*cf5a6c84SAndroid Build Coastguard Worker // Three stages: read data, collate entries, output results.
300*cf5a6c84SAndroid Build Coastguard Worker
main(int argc,char * argv[])301*cf5a6c84SAndroid Build Coastguard Worker int main(int argc, char *argv[])
302*cf5a6c84SAndroid Build Coastguard Worker {
303*cf5a6c84SAndroid Build Coastguard Worker FILE *fp;
304*cf5a6c84SAndroid Build Coastguard Worker
305*cf5a6c84SAndroid Build Coastguard Worker if (argc != 3) {
306*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, "usage: config2help Config.in .config\n");
307*cf5a6c84SAndroid Build Coastguard Worker exit(1);
308*cf5a6c84SAndroid Build Coastguard Worker }
309*cf5a6c84SAndroid Build Coastguard Worker
310*cf5a6c84SAndroid Build Coastguard Worker // Stage 1: read data. Read Config.in to global 'struct symbol *sym' list,
311*cf5a6c84SAndroid Build Coastguard Worker // then read .config to set "enabled" member of each enabled symbol.
312*cf5a6c84SAndroid Build Coastguard Worker
313*cf5a6c84SAndroid Build Coastguard Worker // Read Config.in
314*cf5a6c84SAndroid Build Coastguard Worker parse(argv[1]);
315*cf5a6c84SAndroid Build Coastguard Worker
316*cf5a6c84SAndroid Build Coastguard Worker // read .config
317*cf5a6c84SAndroid Build Coastguard Worker fp = xfopen(argv[2], "r");
318*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
319*cf5a6c84SAndroid Build Coastguard Worker char *line = NULL;
320*cf5a6c84SAndroid Build Coastguard Worker size_t len;
321*cf5a6c84SAndroid Build Coastguard Worker
322*cf5a6c84SAndroid Build Coastguard Worker if (getline(&line, &len, fp) < 1) break;
323*cf5a6c84SAndroid Build Coastguard Worker if (!strncmp("CONFIG_", line, 7)) {
324*cf5a6c84SAndroid Build Coastguard Worker struct symbol *try;
325*cf5a6c84SAndroid Build Coastguard Worker char *s = line+7;
326*cf5a6c84SAndroid Build Coastguard Worker
327*cf5a6c84SAndroid Build Coastguard Worker for (try=sym; try; try=try->next) {
328*cf5a6c84SAndroid Build Coastguard Worker len = strlen(try->name);
329*cf5a6c84SAndroid Build Coastguard Worker if (!strncmp(try->name, s, len) && s[len]=='=' && s[len+1]=='y') {
330*cf5a6c84SAndroid Build Coastguard Worker try->enabled++;
331*cf5a6c84SAndroid Build Coastguard Worker break;
332*cf5a6c84SAndroid Build Coastguard Worker }
333*cf5a6c84SAndroid Build Coastguard Worker }
334*cf5a6c84SAndroid Build Coastguard Worker }
335*cf5a6c84SAndroid Build Coastguard Worker }
336*cf5a6c84SAndroid Build Coastguard Worker
337*cf5a6c84SAndroid Build Coastguard Worker // Stage 2: process data.
338*cf5a6c84SAndroid Build Coastguard Worker
339*cf5a6c84SAndroid Build Coastguard Worker // Collate help according to usage, depends, and .config
340*cf5a6c84SAndroid Build Coastguard Worker
341*cf5a6c84SAndroid Build Coastguard Worker // Loop through each entry, finding duplicate enabled "usage:" names
342*cf5a6c84SAndroid Build Coastguard Worker // This is in reverse order, so last entry gets collated with previous
343*cf5a6c84SAndroid Build Coastguard Worker // entry until we run out of matching pairs.
344*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
345*cf5a6c84SAndroid Build Coastguard Worker struct symbol *throw = 0, *catch;
346*cf5a6c84SAndroid Build Coastguard Worker char *this, *that, *cusage, *tusage, *name = 0;
347*cf5a6c84SAndroid Build Coastguard Worker int len;
348*cf5a6c84SAndroid Build Coastguard Worker
349*cf5a6c84SAndroid Build Coastguard Worker // find a usage: name and collate all enabled entries with that name
350*cf5a6c84SAndroid Build Coastguard Worker for (catch = sym; catch; catch = catch->next) {
351*cf5a6c84SAndroid Build Coastguard Worker if (catch->enabled != 1) continue;
352*cf5a6c84SAndroid Build Coastguard Worker if (catch->help && (that = keyword("usage:", catch->help->data))) {
353*cf5a6c84SAndroid Build Coastguard Worker struct double_list *cfrom, *tfrom, *anchor;
354*cf5a6c84SAndroid Build Coastguard Worker char *try, **cdashlines, **tdashlines, *usage;
355*cf5a6c84SAndroid Build Coastguard Worker int clen, tlen;
356*cf5a6c84SAndroid Build Coastguard Worker
357*cf5a6c84SAndroid Build Coastguard Worker // Align usage: lines, finding a matching pair so we can suck help
358*cf5a6c84SAndroid Build Coastguard Worker // text out of throw into catch, copying from this to that
359*cf5a6c84SAndroid Build Coastguard Worker if (!throw) usage = that;
360*cf5a6c84SAndroid Build Coastguard Worker else if (strncmp(name, that, len) || !isspace(that[len])) continue;
361*cf5a6c84SAndroid Build Coastguard Worker catch->enabled++;
362*cf5a6c84SAndroid Build Coastguard Worker while (!isspace(*that) && *that) that++;
363*cf5a6c84SAndroid Build Coastguard Worker if (!throw) len = that-usage;
364*cf5a6c84SAndroid Build Coastguard Worker free(name);
365*cf5a6c84SAndroid Build Coastguard Worker name = strndup(usage, len);
366*cf5a6c84SAndroid Build Coastguard Worker that = skip_spaces(that);
367*cf5a6c84SAndroid Build Coastguard Worker if (!throw) {
368*cf5a6c84SAndroid Build Coastguard Worker throw = catch;
369*cf5a6c84SAndroid Build Coastguard Worker this = that;
370*cf5a6c84SAndroid Build Coastguard Worker
371*cf5a6c84SAndroid Build Coastguard Worker continue;
372*cf5a6c84SAndroid Build Coastguard Worker }
373*cf5a6c84SAndroid Build Coastguard Worker
374*cf5a6c84SAndroid Build Coastguard Worker // Grab option description lines to collate from catch and throw
375*cf5a6c84SAndroid Build Coastguard Worker tusage = dlist_zap(&throw->help);
376*cf5a6c84SAndroid Build Coastguard Worker tdashlines = grab_dashlines(&throw->help, &tfrom, &tlen);
377*cf5a6c84SAndroid Build Coastguard Worker cusage = dlist_zap(&catch->help);
378*cf5a6c84SAndroid Build Coastguard Worker cdashlines = grab_dashlines(&catch->help, &cfrom, &clen);
379*cf5a6c84SAndroid Build Coastguard Worker anchor = catch->help;
380*cf5a6c84SAndroid Build Coastguard Worker
381*cf5a6c84SAndroid Build Coastguard Worker // If we've got both, collate and alphebetize
382*cf5a6c84SAndroid Build Coastguard Worker if (cdashlines && tdashlines) {
383*cf5a6c84SAndroid Build Coastguard Worker char **new = xmalloc(sizeof(char *)*(clen+tlen));
384*cf5a6c84SAndroid Build Coastguard Worker
385*cf5a6c84SAndroid Build Coastguard Worker memcpy(new, cdashlines, sizeof(char *)*clen);
386*cf5a6c84SAndroid Build Coastguard Worker memcpy(new+clen, tdashlines, sizeof(char *)*tlen);
387*cf5a6c84SAndroid Build Coastguard Worker free(cdashlines);
388*cf5a6c84SAndroid Build Coastguard Worker free(tdashlines);
389*cf5a6c84SAndroid Build Coastguard Worker qsort(new, clen+tlen, sizeof(char *), (void *)dashlinesort);
390*cf5a6c84SAndroid Build Coastguard Worker cdashlines = new;
391*cf5a6c84SAndroid Build Coastguard Worker
392*cf5a6c84SAndroid Build Coastguard Worker // If just one, make sure it's in catch.
393*cf5a6c84SAndroid Build Coastguard Worker } else if (tdashlines) cdashlines = tdashlines;
394*cf5a6c84SAndroid Build Coastguard Worker
395*cf5a6c84SAndroid Build Coastguard Worker // If throw had a prefix, insert it before dashlines, with a
396*cf5a6c84SAndroid Build Coastguard Worker // blank line if catch had a prefix.
397*cf5a6c84SAndroid Build Coastguard Worker if (tfrom && tfrom != throw->help) {
398*cf5a6c84SAndroid Build Coastguard Worker if (throw->help || catch->help) dlist_add(&cfrom, strdup(""));
399*cf5a6c84SAndroid Build Coastguard Worker else {
400*cf5a6c84SAndroid Build Coastguard Worker dlist_add(&cfrom, 0);
401*cf5a6c84SAndroid Build Coastguard Worker anchor = cfrom->prev;
402*cf5a6c84SAndroid Build Coastguard Worker }
403*cf5a6c84SAndroid Build Coastguard Worker while (throw->help && throw->help != tfrom)
404*cf5a6c84SAndroid Build Coastguard Worker dlist_add(&cfrom, dlist_zap(&throw->help));
405*cf5a6c84SAndroid Build Coastguard Worker if (cfrom && cfrom->prev->data && *skip_spaces(cfrom->prev->data))
406*cf5a6c84SAndroid Build Coastguard Worker dlist_add(&cfrom, strdup(""));
407*cf5a6c84SAndroid Build Coastguard Worker }
408*cf5a6c84SAndroid Build Coastguard Worker if (!anchor) {
409*cf5a6c84SAndroid Build Coastguard Worker dlist_add(&cfrom, 0);
410*cf5a6c84SAndroid Build Coastguard Worker anchor = cfrom->prev;
411*cf5a6c84SAndroid Build Coastguard Worker }
412*cf5a6c84SAndroid Build Coastguard Worker
413*cf5a6c84SAndroid Build Coastguard Worker // Splice sorted lines back in place
414*cf5a6c84SAndroid Build Coastguard Worker if (cdashlines) {
415*cf5a6c84SAndroid Build Coastguard Worker tlen += clen;
416*cf5a6c84SAndroid Build Coastguard Worker
417*cf5a6c84SAndroid Build Coastguard Worker for (clen = 0; clen < tlen; clen++)
418*cf5a6c84SAndroid Build Coastguard Worker dlist_add(&cfrom, cdashlines[clen]);
419*cf5a6c84SAndroid Build Coastguard Worker }
420*cf5a6c84SAndroid Build Coastguard Worker
421*cf5a6c84SAndroid Build Coastguard Worker // If there were no dashlines, text would be considered prefix, so
422*cf5a6c84SAndroid Build Coastguard Worker // the list is definitely no longer empty, so discard placeholder.
423*cf5a6c84SAndroid Build Coastguard Worker if (!anchor->data) dlist_zap(&anchor);
424*cf5a6c84SAndroid Build Coastguard Worker
425*cf5a6c84SAndroid Build Coastguard Worker // zap whitespace at end of catch help text
426*cf5a6c84SAndroid Build Coastguard Worker while (!*skip_spaces(anchor->prev->data)) {
427*cf5a6c84SAndroid Build Coastguard Worker anchor = anchor->prev;
428*cf5a6c84SAndroid Build Coastguard Worker free(dlist_zap(&anchor));
429*cf5a6c84SAndroid Build Coastguard Worker }
430*cf5a6c84SAndroid Build Coastguard Worker
431*cf5a6c84SAndroid Build Coastguard Worker // Append trailing lines.
432*cf5a6c84SAndroid Build Coastguard Worker while (tfrom) dlist_add(&anchor, dlist_zap(&tfrom));
433*cf5a6c84SAndroid Build Coastguard Worker
434*cf5a6c84SAndroid Build Coastguard Worker // Collate first [-abc] option block in usage: lines
435*cf5a6c84SAndroid Build Coastguard Worker try = 0;
436*cf5a6c84SAndroid Build Coastguard Worker if (*this == '[' && this[1] == '-' && this[2] != '-' &&
437*cf5a6c84SAndroid Build Coastguard Worker *that == '[' && that[1] == '-' && that[2] != '-')
438*cf5a6c84SAndroid Build Coastguard Worker {
439*cf5a6c84SAndroid Build Coastguard Worker char *from = this+2, *to = that+2;
440*cf5a6c84SAndroid Build Coastguard Worker int ff = strcspn(from, " ]"), tt = strcspn(to, " ]");
441*cf5a6c84SAndroid Build Coastguard Worker
442*cf5a6c84SAndroid Build Coastguard Worker if (from[ff] == ']' && to[tt] == ']') {
443*cf5a6c84SAndroid Build Coastguard Worker try = xmprintf("[-%.*s%.*s] ", ff, from, tt, to);
444*cf5a6c84SAndroid Build Coastguard Worker qsort(try+2, ff+tt, 1, (void *)charsort);
445*cf5a6c84SAndroid Build Coastguard Worker this = skip_spaces(this+ff+3);
446*cf5a6c84SAndroid Build Coastguard Worker that = skip_spaces(that+tt+3);
447*cf5a6c84SAndroid Build Coastguard Worker }
448*cf5a6c84SAndroid Build Coastguard Worker }
449*cf5a6c84SAndroid Build Coastguard Worker
450*cf5a6c84SAndroid Build Coastguard Worker // The list is definitely no longer empty, so discard placeholder.
451*cf5a6c84SAndroid Build Coastguard Worker if (!anchor->data) dlist_zap(&anchor);
452*cf5a6c84SAndroid Build Coastguard Worker
453*cf5a6c84SAndroid Build Coastguard Worker // Add new collated line (and whitespace).
454*cf5a6c84SAndroid Build Coastguard Worker dlist_add(&anchor, xmprintf("%*cusage: %.*s %s%s%s%s",
455*cf5a6c84SAndroid Build Coastguard Worker catch->help_indent, ' ', len, name, try ? try : "",
456*cf5a6c84SAndroid Build Coastguard Worker this, *this ? " " : "", that));
457*cf5a6c84SAndroid Build Coastguard Worker free(try);
458*cf5a6c84SAndroid Build Coastguard Worker dlist_add(&anchor, strdup(""));
459*cf5a6c84SAndroid Build Coastguard Worker free(cusage);
460*cf5a6c84SAndroid Build Coastguard Worker free(tusage);
461*cf5a6c84SAndroid Build Coastguard Worker throw->enabled = 0;
462*cf5a6c84SAndroid Build Coastguard Worker throw = catch;
463*cf5a6c84SAndroid Build Coastguard Worker throw->help = anchor->prev->prev;
464*cf5a6c84SAndroid Build Coastguard Worker
465*cf5a6c84SAndroid Build Coastguard Worker throw = catch;
466*cf5a6c84SAndroid Build Coastguard Worker this = throw->help->data + throw->help_indent + 8 + len;
467*cf5a6c84SAndroid Build Coastguard Worker }
468*cf5a6c84SAndroid Build Coastguard Worker }
469*cf5a6c84SAndroid Build Coastguard Worker
470*cf5a6c84SAndroid Build Coastguard Worker // Did we find one?
471*cf5a6c84SAndroid Build Coastguard Worker
472*cf5a6c84SAndroid Build Coastguard Worker if (!throw) break;
473*cf5a6c84SAndroid Build Coastguard Worker }
474*cf5a6c84SAndroid Build Coastguard Worker
475*cf5a6c84SAndroid Build Coastguard Worker // Stage 3: output results to stdout.
476*cf5a6c84SAndroid Build Coastguard Worker
477*cf5a6c84SAndroid Build Coastguard Worker // Print out help #defines
478*cf5a6c84SAndroid Build Coastguard Worker while (sym) {
479*cf5a6c84SAndroid Build Coastguard Worker struct double_list *dd;
480*cf5a6c84SAndroid Build Coastguard Worker
481*cf5a6c84SAndroid Build Coastguard Worker if (sym->help) {
482*cf5a6c84SAndroid Build Coastguard Worker int i, blank;
483*cf5a6c84SAndroid Build Coastguard Worker char *s;
484*cf5a6c84SAndroid Build Coastguard Worker
485*cf5a6c84SAndroid Build Coastguard Worker strcpy(s = xmalloc(strlen(sym->name)+1), sym->name);
486*cf5a6c84SAndroid Build Coastguard Worker
487*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; s[i]; i++) s[i] = tolower(s[i]);
488*cf5a6c84SAndroid Build Coastguard Worker printf("#define HELP_%s \"", s);
489*cf5a6c84SAndroid Build Coastguard Worker free(s);
490*cf5a6c84SAndroid Build Coastguard Worker
491*cf5a6c84SAndroid Build Coastguard Worker dd = sym->help;
492*cf5a6c84SAndroid Build Coastguard Worker blank = 0;
493*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
494*cf5a6c84SAndroid Build Coastguard Worker
495*cf5a6c84SAndroid Build Coastguard Worker // Trim leading whitespace
496*cf5a6c84SAndroid Build Coastguard Worker s = dd->data;
497*cf5a6c84SAndroid Build Coastguard Worker i = sym->help_indent;
498*cf5a6c84SAndroid Build Coastguard Worker while (isspace(*s) && i--) s++;
499*cf5a6c84SAndroid Build Coastguard Worker
500*cf5a6c84SAndroid Build Coastguard Worker // Only one blank line between nonblank lines, not at start or end.
501*cf5a6c84SAndroid Build Coastguard Worker if (!*s) blank = 2;
502*cf5a6c84SAndroid Build Coastguard Worker else {
503*cf5a6c84SAndroid Build Coastguard Worker while (blank--) {
504*cf5a6c84SAndroid Build Coastguard Worker putchar('\\');
505*cf5a6c84SAndroid Build Coastguard Worker putchar('n');
506*cf5a6c84SAndroid Build Coastguard Worker }
507*cf5a6c84SAndroid Build Coastguard Worker blank = 1;
508*cf5a6c84SAndroid Build Coastguard Worker }
509*cf5a6c84SAndroid Build Coastguard Worker
510*cf5a6c84SAndroid Build Coastguard Worker for (i=0; s[i]; i++) {
511*cf5a6c84SAndroid Build Coastguard Worker if (s[i] == '"' || s[i] == '\\') putchar('\\');
512*cf5a6c84SAndroid Build Coastguard Worker putchar(s[i]);
513*cf5a6c84SAndroid Build Coastguard Worker }
514*cf5a6c84SAndroid Build Coastguard Worker dd = dd->next;
515*cf5a6c84SAndroid Build Coastguard Worker if (dd == sym->help) break;
516*cf5a6c84SAndroid Build Coastguard Worker }
517*cf5a6c84SAndroid Build Coastguard Worker printf("\"\n\n");
518*cf5a6c84SAndroid Build Coastguard Worker }
519*cf5a6c84SAndroid Build Coastguard Worker sym = sym->next;
520*cf5a6c84SAndroid Build Coastguard Worker }
521*cf5a6c84SAndroid Build Coastguard Worker
522*cf5a6c84SAndroid Build Coastguard Worker return 0;
523*cf5a6c84SAndroid Build Coastguard Worker }
524