Mercurial > hg > toybox
comparison kconfig/conf.c @ 10:4d21d59f3206
Add menuconfig, plus some basic Config info, lots of which is just future
plans for toysh. Nothing's currently _using_ this config info, but at least
it's being generated now.
author | landley@driftwood |
---|---|
date | Tue, 31 Oct 2006 23:30:06 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 10:4d21d59f3206 |
---|---|
1 /* | |
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | |
3 * Released under the terms of the GNU GPL v2.0. | |
4 */ | |
5 | |
6 #include <ctype.h> | |
7 #include <stdlib.h> | |
8 #include <stdio.h> | |
9 #include <string.h> | |
10 #include <unistd.h> | |
11 #include <time.h> | |
12 #include <sys/stat.h> | |
13 | |
14 #define LKC_DIRECT_LINK | |
15 #include "lkc.h" | |
16 | |
17 static void conf(struct menu *menu); | |
18 static void check_conf(struct menu *menu); | |
19 | |
20 enum { | |
21 ask_all, | |
22 ask_new, | |
23 ask_silent, | |
24 set_default, | |
25 set_yes, | |
26 set_mod, | |
27 set_no, | |
28 set_random | |
29 } input_mode = ask_all; | |
30 char *defconfig_file; | |
31 | |
32 static int indent = 1; | |
33 static int valid_stdin = 1; | |
34 static int conf_cnt; | |
35 static char line[128]; | |
36 static struct menu *rootEntry; | |
37 | |
38 static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n"); | |
39 | |
40 static void strip(char *str) | |
41 { | |
42 char *p = str; | |
43 int l; | |
44 | |
45 while ((isspace(*p))) | |
46 p++; | |
47 l = strlen(p); | |
48 if (p != str) | |
49 memmove(str, p, l + 1); | |
50 if (!l) | |
51 return; | |
52 p = str + l - 1; | |
53 while ((isspace(*p))) | |
54 *p-- = 0; | |
55 } | |
56 | |
57 static void check_stdin(void) | |
58 { | |
59 if (!valid_stdin && input_mode == ask_silent) { | |
60 printf(_("aborted!\n\n")); | |
61 printf(_("Console input/output is redirected. ")); | |
62 printf(_("Run 'make oldconfig' to update configuration.\n\n")); | |
63 exit(1); | |
64 } | |
65 } | |
66 | |
67 static void conf_askvalue(struct symbol *sym, const char *def) | |
68 { | |
69 enum symbol_type type = sym_get_type(sym); | |
70 tristate val; | |
71 | |
72 if (!sym_has_value(sym)) | |
73 printf("(NEW) "); | |
74 | |
75 line[0] = '\n'; | |
76 line[1] = 0; | |
77 | |
78 if (!sym_is_changable(sym)) { | |
79 printf("%s\n", def); | |
80 line[0] = '\n'; | |
81 line[1] = 0; | |
82 return; | |
83 } | |
84 | |
85 switch (input_mode) { | |
86 case set_no: | |
87 case set_mod: | |
88 case set_yes: | |
89 case set_random: | |
90 if (sym_has_value(sym)) { | |
91 printf("%s\n", def); | |
92 return; | |
93 } | |
94 break; | |
95 case ask_new: | |
96 case ask_silent: | |
97 if (sym_has_value(sym)) { | |
98 printf("%s\n", def); | |
99 return; | |
100 } | |
101 check_stdin(); | |
102 case ask_all: | |
103 fflush(stdout); | |
104 fgets(line, 128, stdin); | |
105 return; | |
106 case set_default: | |
107 printf("%s\n", def); | |
108 return; | |
109 default: | |
110 break; | |
111 } | |
112 | |
113 switch (type) { | |
114 case S_INT: | |
115 case S_HEX: | |
116 case S_STRING: | |
117 printf("%s\n", def); | |
118 return; | |
119 default: | |
120 ; | |
121 } | |
122 switch (input_mode) { | |
123 case set_yes: | |
124 if (sym_tristate_within_range(sym, yes)) { | |
125 line[0] = 'y'; | |
126 line[1] = '\n'; | |
127 line[2] = 0; | |
128 break; | |
129 } | |
130 case set_mod: | |
131 if (type == S_TRISTATE) { | |
132 if (sym_tristate_within_range(sym, mod)) { | |
133 line[0] = 'm'; | |
134 line[1] = '\n'; | |
135 line[2] = 0; | |
136 break; | |
137 } | |
138 } else { | |
139 if (sym_tristate_within_range(sym, yes)) { | |
140 line[0] = 'y'; | |
141 line[1] = '\n'; | |
142 line[2] = 0; | |
143 break; | |
144 } | |
145 } | |
146 case set_no: | |
147 if (sym_tristate_within_range(sym, no)) { | |
148 line[0] = 'n'; | |
149 line[1] = '\n'; | |
150 line[2] = 0; | |
151 break; | |
152 } | |
153 case set_random: | |
154 do { | |
155 val = (tristate)(random() % 3); | |
156 } while (!sym_tristate_within_range(sym, val)); | |
157 switch (val) { | |
158 case no: line[0] = 'n'; break; | |
159 case mod: line[0] = 'm'; break; | |
160 case yes: line[0] = 'y'; break; | |
161 } | |
162 line[1] = '\n'; | |
163 line[2] = 0; | |
164 break; | |
165 default: | |
166 break; | |
167 } | |
168 printf("%s", line); | |
169 } | |
170 | |
171 int conf_string(struct menu *menu) | |
172 { | |
173 struct symbol *sym = menu->sym; | |
174 const char *def, *help; | |
175 | |
176 while (1) { | |
177 printf("%*s%s ", indent - 1, "", menu->prompt->text); | |
178 printf("(%s) ", sym->name); | |
179 def = sym_get_string_value(sym); | |
180 if (sym_get_string_value(sym)) | |
181 printf("[%s] ", def); | |
182 conf_askvalue(sym, def); | |
183 switch (line[0]) { | |
184 case '\n': | |
185 break; | |
186 case '?': | |
187 /* print help */ | |
188 if (line[1] == '\n') { | |
189 help = nohelp_text; | |
190 if (menu->sym->help) | |
191 help = menu->sym->help; | |
192 printf("\n%s\n", menu->sym->help); | |
193 def = NULL; | |
194 break; | |
195 } | |
196 default: | |
197 line[strlen(line)-1] = 0; | |
198 def = line; | |
199 } | |
200 if (def && sym_set_string_value(sym, def)) | |
201 return 0; | |
202 } | |
203 } | |
204 | |
205 static int conf_sym(struct menu *menu) | |
206 { | |
207 struct symbol *sym = menu->sym; | |
208 int type; | |
209 tristate oldval, newval; | |
210 const char *help; | |
211 | |
212 while (1) { | |
213 printf("%*s%s ", indent - 1, "", menu->prompt->text); | |
214 if (sym->name) | |
215 printf("(%s) ", sym->name); | |
216 type = sym_get_type(sym); | |
217 putchar('['); | |
218 oldval = sym_get_tristate_value(sym); | |
219 switch (oldval) { | |
220 case no: | |
221 putchar('N'); | |
222 break; | |
223 case mod: | |
224 putchar('M'); | |
225 break; | |
226 case yes: | |
227 putchar('Y'); | |
228 break; | |
229 } | |
230 if (oldval != no && sym_tristate_within_range(sym, no)) | |
231 printf("/n"); | |
232 if (oldval != mod && sym_tristate_within_range(sym, mod)) | |
233 printf("/m"); | |
234 if (oldval != yes && sym_tristate_within_range(sym, yes)) | |
235 printf("/y"); | |
236 if (sym->help) | |
237 printf("/?"); | |
238 printf("] "); | |
239 conf_askvalue(sym, sym_get_string_value(sym)); | |
240 strip(line); | |
241 | |
242 switch (line[0]) { | |
243 case 'n': | |
244 case 'N': | |
245 newval = no; | |
246 if (!line[1] || !strcmp(&line[1], "o")) | |
247 break; | |
248 continue; | |
249 case 'm': | |
250 case 'M': | |
251 newval = mod; | |
252 if (!line[1]) | |
253 break; | |
254 continue; | |
255 case 'y': | |
256 case 'Y': | |
257 newval = yes; | |
258 if (!line[1] || !strcmp(&line[1], "es")) | |
259 break; | |
260 continue; | |
261 case 0: | |
262 newval = oldval; | |
263 break; | |
264 case '?': | |
265 goto help; | |
266 default: | |
267 continue; | |
268 } | |
269 if (sym_set_tristate_value(sym, newval)) | |
270 return 0; | |
271 help: | |
272 help = nohelp_text; | |
273 if (sym->help) | |
274 help = sym->help; | |
275 printf("\n%s\n", help); | |
276 } | |
277 } | |
278 | |
279 static int conf_choice(struct menu *menu) | |
280 { | |
281 struct symbol *sym, *def_sym; | |
282 struct menu *child; | |
283 int type; | |
284 bool is_new; | |
285 | |
286 sym = menu->sym; | |
287 type = sym_get_type(sym); | |
288 is_new = !sym_has_value(sym); | |
289 if (sym_is_changable(sym)) { | |
290 conf_sym(menu); | |
291 sym_calc_value(sym); | |
292 switch (sym_get_tristate_value(sym)) { | |
293 case no: | |
294 return 1; | |
295 case mod: | |
296 return 0; | |
297 case yes: | |
298 break; | |
299 } | |
300 } else { | |
301 switch (sym_get_tristate_value(sym)) { | |
302 case no: | |
303 return 1; | |
304 case mod: | |
305 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); | |
306 return 0; | |
307 case yes: | |
308 break; | |
309 } | |
310 } | |
311 | |
312 while (1) { | |
313 int cnt, def; | |
314 | |
315 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); | |
316 def_sym = sym_get_choice_value(sym); | |
317 cnt = def = 0; | |
318 line[0] = 0; | |
319 for (child = menu->list; child; child = child->next) { | |
320 if (!menu_is_visible(child)) | |
321 continue; | |
322 if (!child->sym) { | |
323 printf("%*c %s\n", indent, '*', menu_get_prompt(child)); | |
324 continue; | |
325 } | |
326 cnt++; | |
327 if (child->sym == def_sym) { | |
328 def = cnt; | |
329 printf("%*c", indent, '>'); | |
330 } else | |
331 printf("%*c", indent, ' '); | |
332 printf(" %d. %s", cnt, menu_get_prompt(child)); | |
333 if (child->sym->name) | |
334 printf(" (%s)", child->sym->name); | |
335 if (!sym_has_value(child->sym)) | |
336 printf(" (NEW)"); | |
337 printf("\n"); | |
338 } | |
339 printf("%*schoice", indent - 1, ""); | |
340 if (cnt == 1) { | |
341 printf("[1]: 1\n"); | |
342 goto conf_childs; | |
343 } | |
344 printf("[1-%d", cnt); | |
345 if (sym->help) | |
346 printf("?"); | |
347 printf("]: "); | |
348 switch (input_mode) { | |
349 case ask_new: | |
350 case ask_silent: | |
351 if (!is_new) { | |
352 cnt = def; | |
353 printf("%d\n", cnt); | |
354 break; | |
355 } | |
356 check_stdin(); | |
357 case ask_all: | |
358 fflush(stdout); | |
359 fgets(line, 128, stdin); | |
360 strip(line); | |
361 if (line[0] == '?') { | |
362 printf("\n%s\n", menu->sym->help ? | |
363 menu->sym->help : nohelp_text); | |
364 continue; | |
365 } | |
366 if (!line[0]) | |
367 cnt = def; | |
368 else if (isdigit(line[0])) | |
369 cnt = atoi(line); | |
370 else | |
371 continue; | |
372 break; | |
373 case set_random: | |
374 def = (random() % cnt) + 1; | |
375 case set_default: | |
376 case set_yes: | |
377 case set_mod: | |
378 case set_no: | |
379 cnt = def; | |
380 printf("%d\n", cnt); | |
381 break; | |
382 } | |
383 | |
384 conf_childs: | |
385 for (child = menu->list; child; child = child->next) { | |
386 if (!child->sym || !menu_is_visible(child)) | |
387 continue; | |
388 if (!--cnt) | |
389 break; | |
390 } | |
391 if (!child) | |
392 continue; | |
393 if (line[strlen(line) - 1] == '?') { | |
394 printf("\n%s\n", child->sym->help ? | |
395 child->sym->help : nohelp_text); | |
396 continue; | |
397 } | |
398 sym_set_choice_value(sym, child->sym); | |
399 if (child->list) { | |
400 indent += 2; | |
401 conf(child->list); | |
402 indent -= 2; | |
403 } | |
404 return 1; | |
405 } | |
406 } | |
407 | |
408 static void conf(struct menu *menu) | |
409 { | |
410 struct symbol *sym; | |
411 struct property *prop; | |
412 struct menu *child; | |
413 | |
414 if (!menu_is_visible(menu)) | |
415 return; | |
416 | |
417 sym = menu->sym; | |
418 prop = menu->prompt; | |
419 if (prop) { | |
420 const char *prompt; | |
421 | |
422 switch (prop->type) { | |
423 case P_MENU: | |
424 if (input_mode == ask_silent && rootEntry != menu) { | |
425 check_conf(menu); | |
426 return; | |
427 } | |
428 case P_COMMENT: | |
429 prompt = menu_get_prompt(menu); | |
430 if (prompt) | |
431 printf("%*c\n%*c %s\n%*c\n", | |
432 indent, '*', | |
433 indent, '*', prompt, | |
434 indent, '*'); | |
435 default: | |
436 ; | |
437 } | |
438 } | |
439 | |
440 if (!sym) | |
441 goto conf_childs; | |
442 | |
443 if (sym_is_choice(sym)) { | |
444 conf_choice(menu); | |
445 if (sym->curr.tri != mod) | |
446 return; | |
447 goto conf_childs; | |
448 } | |
449 | |
450 switch (sym->type) { | |
451 case S_INT: | |
452 case S_HEX: | |
453 case S_STRING: | |
454 conf_string(menu); | |
455 break; | |
456 default: | |
457 conf_sym(menu); | |
458 break; | |
459 } | |
460 | |
461 conf_childs: | |
462 if (sym) | |
463 indent += 2; | |
464 for (child = menu->list; child; child = child->next) | |
465 conf(child); | |
466 if (sym) | |
467 indent -= 2; | |
468 } | |
469 | |
470 static void check_conf(struct menu *menu) | |
471 { | |
472 struct symbol *sym; | |
473 struct menu *child; | |
474 | |
475 if (!menu_is_visible(menu)) | |
476 return; | |
477 | |
478 sym = menu->sym; | |
479 if (sym && !sym_has_value(sym)) { | |
480 if (sym_is_changable(sym) || | |
481 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { | |
482 if (!conf_cnt++) | |
483 printf(_("*\n* Restart config...\n*\n")); | |
484 rootEntry = menu_get_parent_menu(menu); | |
485 conf(rootEntry); | |
486 } | |
487 } | |
488 | |
489 for (child = menu->list; child; child = child->next) | |
490 check_conf(child); | |
491 } | |
492 | |
493 int main(int ac, char **av) | |
494 { | |
495 int i = 1; | |
496 const char *name; | |
497 struct stat tmpstat; | |
498 | |
499 if (ac > i && av[i][0] == '-') { | |
500 switch (av[i++][1]) { | |
501 case 'o': | |
502 input_mode = ask_new; | |
503 break; | |
504 case 's': | |
505 input_mode = ask_silent; | |
506 valid_stdin = isatty(0) && isatty(1) && isatty(2); | |
507 break; | |
508 case 'd': | |
509 input_mode = set_default; | |
510 break; | |
511 case 'D': | |
512 input_mode = set_default; | |
513 defconfig_file = av[i++]; | |
514 if (!defconfig_file) { | |
515 printf(_("%s: No default config file specified\n"), | |
516 av[0]); | |
517 exit(1); | |
518 } | |
519 break; | |
520 case 'n': | |
521 input_mode = set_no; | |
522 break; | |
523 case 'm': | |
524 input_mode = set_mod; | |
525 break; | |
526 case 'y': | |
527 input_mode = set_yes; | |
528 break; | |
529 case 'r': | |
530 input_mode = set_random; | |
531 srandom(time(NULL)); | |
532 break; | |
533 case 'h': | |
534 case '?': | |
535 fprintf(stderr, "See README for usage info\n"); | |
536 exit(0); | |
537 } | |
538 } | |
539 name = av[i]; | |
540 if (!name) { | |
541 printf(_("%s: Kconfig file missing\n"), av[0]); | |
542 exit(1); | |
543 } | |
544 conf_parse(name); | |
545 //zconfdump(stdout); | |
546 switch (input_mode) { | |
547 case set_default: | |
548 if (!defconfig_file) | |
549 defconfig_file = conf_get_default_confname(); | |
550 if (conf_read(defconfig_file)) { | |
551 printf("***\n" | |
552 "*** Can't find default configuration \"%s\"!\n" | |
553 "***\n", defconfig_file); | |
554 exit(1); | |
555 } | |
556 break; | |
557 case ask_silent: | |
558 if (stat(".config", &tmpstat)) { | |
559 printf(_("***\n" | |
560 "*** You have not yet configured your "PROJECT_NAME"!\n" | |
561 "***\n" | |
562 "*** Please run some configurator (e.g. \"make oldconfig\" or\n" | |
563 "*** \"make menuconfig\" or \"make xconfig\").\n" | |
564 "***\n")); | |
565 exit(1); | |
566 } | |
567 case ask_all: | |
568 case ask_new: | |
569 conf_read(NULL); | |
570 break; | |
571 case set_no: | |
572 case set_mod: | |
573 case set_yes: | |
574 case set_random: | |
575 name = getenv("KCONFIG_ALLCONFIG"); | |
576 if (name && !stat(name, &tmpstat)) { | |
577 conf_read_simple(name, S_DEF_USER); | |
578 break; | |
579 } | |
580 switch (input_mode) { | |
581 case set_no: name = "allno.config"; break; | |
582 case set_mod: name = "allmod.config"; break; | |
583 case set_yes: name = "allyes.config"; break; | |
584 case set_random: name = "allrandom.config"; break; | |
585 default: break; | |
586 } | |
587 if (!stat(name, &tmpstat)) | |
588 conf_read_simple(name, S_DEF_USER); | |
589 else if (!stat("all.config", &tmpstat)) | |
590 conf_read_simple("all.config", S_DEF_USER); | |
591 break; | |
592 default: | |
593 break; | |
594 } | |
595 | |
596 if (input_mode != ask_silent) { | |
597 rootEntry = &rootmenu; | |
598 conf(&rootmenu); | |
599 if (input_mode == ask_all) { | |
600 input_mode = ask_silent; | |
601 valid_stdin = 1; | |
602 } | |
603 } else if (sym_change_count) { | |
604 name = getenv("KCONFIG_NOSILENTUPDATE"); | |
605 if (name && *name) { | |
606 fprintf(stderr, _("\n*** "PROJECT_NAME" configuration requires explicit update.\n\n")); | |
607 return 1; | |
608 } | |
609 } else | |
610 goto skip_check; | |
611 | |
612 do { | |
613 conf_cnt = 0; | |
614 check_conf(&rootmenu); | |
615 } while (conf_cnt); | |
616 | |
617 if (!conf_write(NULL)) { | |
618 skip_check: | |
619 if (!(input_mode == ask_silent && conf_write_autoconf())) | |
620 return 0; | |
621 } | |
622 fprintf(stderr, _("\n*** Error writing "PROJECT_NAME" configuration.\n\n")); | |
623 return 1; | |
624 } |