Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / scripts / kconfig / conf.c
blobfda63136ae6809512c6d84ab5c11d1497eee3bc5
1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
6 #include <locale.h>
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <time.h>
12 #include <unistd.h>
13 #include <sys/stat.h>
15 #define LKC_DIRECT_LINK
16 #include "lkc.h"
18 static void conf(struct menu *menu);
19 static void check_conf(struct menu *menu);
21 enum {
22 ask_all,
23 ask_new,
24 ask_silent,
25 set_default,
26 set_yes,
27 set_mod,
28 set_no,
29 set_random
30 } input_mode = ask_all;
31 char *defconfig_file;
33 static int indent = 1;
34 static int valid_stdin = 1;
35 static int conf_cnt;
36 static char line[128];
37 static struct menu *rootEntry;
39 static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
41 static const char *get_help(struct menu *menu)
43 if (menu_has_help(menu))
44 return _(menu_get_help(menu));
45 else
46 return nohelp_text;
49 static void strip(char *str)
51 char *p = str;
52 int l;
54 while ((isspace(*p)))
55 p++;
56 l = strlen(p);
57 if (p != str)
58 memmove(str, p, l + 1);
59 if (!l)
60 return;
61 p = str + l - 1;
62 while ((isspace(*p)))
63 *p-- = 0;
66 static void check_stdin(void)
68 if (!valid_stdin && input_mode == ask_silent) {
69 printf(_("aborted!\n\n"));
70 printf(_("Console input/output is redirected. "));
71 printf(_("Run 'make oldconfig' to update configuration.\n\n"));
72 exit(1);
76 static int conf_askvalue(struct symbol *sym, const char *def)
78 enum symbol_type type = sym_get_type(sym);
79 tristate val;
81 if (!sym_has_value(sym))
82 printf(_("(NEW) "));
84 line[0] = '\n';
85 line[1] = 0;
87 if (!sym_is_changable(sym)) {
88 printf("%s\n", def);
89 line[0] = '\n';
90 line[1] = 0;
91 return 0;
94 switch (input_mode) {
95 case set_no:
96 case set_mod:
97 case set_yes:
98 case set_random:
99 if (sym_has_value(sym)) {
100 printf("%s\n", def);
101 return 0;
103 break;
104 case ask_new:
105 case ask_silent:
106 if (sym_has_value(sym)) {
107 printf("%s\n", def);
108 return 0;
110 check_stdin();
111 case ask_all:
112 fflush(stdout);
113 fgets(line, 128, stdin);
114 return 1;
115 case set_default:
116 printf("%s\n", def);
117 return 1;
118 default:
119 break;
122 switch (type) {
123 case S_INT:
124 case S_HEX:
125 case S_STRING:
126 printf("%s\n", def);
127 return 1;
128 default:
131 switch (input_mode) {
132 case set_yes:
133 if (sym_tristate_within_range(sym, yes)) {
134 line[0] = 'y';
135 line[1] = '\n';
136 line[2] = 0;
137 break;
139 case set_mod:
140 if (type == S_TRISTATE) {
141 if (sym_tristate_within_range(sym, mod)) {
142 line[0] = 'm';
143 line[1] = '\n';
144 line[2] = 0;
145 break;
147 } else {
148 if (sym_tristate_within_range(sym, yes)) {
149 line[0] = 'y';
150 line[1] = '\n';
151 line[2] = 0;
152 break;
155 case set_no:
156 if (sym_tristate_within_range(sym, no)) {
157 line[0] = 'n';
158 line[1] = '\n';
159 line[2] = 0;
160 break;
162 case set_random:
163 do {
164 val = (tristate)(rand() % 3);
165 } while (!sym_tristate_within_range(sym, val));
166 switch (val) {
167 case no: line[0] = 'n'; break;
168 case mod: line[0] = 'm'; break;
169 case yes: line[0] = 'y'; break;
171 line[1] = '\n';
172 line[2] = 0;
173 break;
174 default:
175 break;
177 printf("%s", line);
178 return 1;
181 int conf_string(struct menu *menu)
183 struct symbol *sym = menu->sym;
184 const char *def;
186 while (1) {
187 printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
188 printf("(%s) ", sym->name);
189 def = sym_get_string_value(sym);
190 if (sym_get_string_value(sym))
191 printf("[%s] ", def);
192 if (!conf_askvalue(sym, def))
193 return 0;
194 switch (line[0]) {
195 case '\n':
196 break;
197 case '?':
198 /* print help */
199 if (line[1] == '\n') {
200 printf("\n%s\n", get_help(menu));
201 def = NULL;
202 break;
204 default:
205 line[strlen(line)-1] = 0;
206 def = line;
208 if (def && sym_set_string_value(sym, def))
209 return 0;
213 static int conf_sym(struct menu *menu)
215 struct symbol *sym = menu->sym;
216 int type;
217 tristate oldval, newval;
219 while (1) {
220 printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
221 if (sym->name)
222 printf("(%s) ", sym->name);
223 type = sym_get_type(sym);
224 putchar('[');
225 oldval = sym_get_tristate_value(sym);
226 switch (oldval) {
227 case no:
228 putchar('N');
229 break;
230 case mod:
231 putchar('M');
232 break;
233 case yes:
234 putchar('Y');
235 break;
237 if (oldval != no && sym_tristate_within_range(sym, no))
238 printf("/n");
239 if (oldval != mod && sym_tristate_within_range(sym, mod))
240 printf("/m");
241 if (oldval != yes && sym_tristate_within_range(sym, yes))
242 printf("/y");
243 if (menu_has_help(menu))
244 printf("/?");
245 printf("] ");
246 if (!conf_askvalue(sym, sym_get_string_value(sym)))
247 return 0;
248 strip(line);
250 switch (line[0]) {
251 case 'n':
252 case 'N':
253 newval = no;
254 if (!line[1] || !strcmp(&line[1], "o"))
255 break;
256 continue;
257 case 'm':
258 case 'M':
259 newval = mod;
260 if (!line[1])
261 break;
262 continue;
263 case 'y':
264 case 'Y':
265 newval = yes;
266 if (!line[1] || !strcmp(&line[1], "es"))
267 break;
268 continue;
269 case 0:
270 newval = oldval;
271 break;
272 case '?':
273 goto help;
274 default:
275 continue;
277 if (sym_set_tristate_value(sym, newval))
278 return 0;
279 help:
280 printf("\n%s\n", get_help(menu));
284 static int conf_choice(struct menu *menu)
286 struct symbol *sym, *def_sym;
287 struct menu *child;
288 int type;
289 bool is_new;
291 sym = menu->sym;
292 type = sym_get_type(sym);
293 is_new = !sym_has_value(sym);
294 if (sym_is_changable(sym)) {
295 conf_sym(menu);
296 sym_calc_value(sym);
297 switch (sym_get_tristate_value(sym)) {
298 case no:
299 return 1;
300 case mod:
301 return 0;
302 case yes:
303 break;
305 } else {
306 switch (sym_get_tristate_value(sym)) {
307 case no:
308 return 1;
309 case mod:
310 printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
311 return 0;
312 case yes:
313 break;
317 while (1) {
318 int cnt, def;
320 printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
321 def_sym = sym_get_choice_value(sym);
322 cnt = def = 0;
323 line[0] = 0;
324 for (child = menu->list; child; child = child->next) {
325 if (!menu_is_visible(child))
326 continue;
327 if (!child->sym) {
328 printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
329 continue;
331 cnt++;
332 if (child->sym == def_sym) {
333 def = cnt;
334 printf("%*c", indent, '>');
335 } else
336 printf("%*c", indent, ' ');
337 printf(" %d. %s", cnt, _(menu_get_prompt(child)));
338 if (child->sym->name)
339 printf(" (%s)", child->sym->name);
340 if (!sym_has_value(child->sym))
341 printf(_(" (NEW)"));
342 printf("\n");
344 printf(_("%*schoice"), indent - 1, "");
345 if (cnt == 1) {
346 printf("[1]: 1\n");
347 goto conf_childs;
349 printf("[1-%d", cnt);
350 if (menu_has_help(menu))
351 printf("?");
352 printf("]: ");
353 switch (input_mode) {
354 case ask_new:
355 case ask_silent:
356 if (!is_new) {
357 cnt = def;
358 printf("%d\n", cnt);
359 break;
361 check_stdin();
362 case ask_all:
363 fflush(stdout);
364 fgets(line, 128, stdin);
365 strip(line);
366 if (line[0] == '?') {
367 printf("\n%s\n", get_help(menu));
368 continue;
370 if (!line[0])
371 cnt = def;
372 else if (isdigit(line[0]))
373 cnt = atoi(line);
374 else
375 continue;
376 break;
377 case set_random:
378 if (is_new)
379 def = (rand() % cnt) + 1;
380 case set_default:
381 case set_yes:
382 case set_mod:
383 case set_no:
384 cnt = def;
385 printf("%d\n", cnt);
386 break;
389 conf_childs:
390 for (child = menu->list; child; child = child->next) {
391 if (!child->sym || !menu_is_visible(child))
392 continue;
393 if (!--cnt)
394 break;
396 if (!child)
397 continue;
398 if (line[strlen(line) - 1] == '?') {
399 printf("\n%s\n", get_help(child));
400 continue;
402 sym_set_choice_value(sym, child->sym);
403 for (child = child->list; child; child = child->next) {
404 indent += 2;
405 conf(child);
406 indent -= 2;
408 return 1;
412 static void conf(struct menu *menu)
414 struct symbol *sym;
415 struct property *prop;
416 struct menu *child;
418 if (!menu_is_visible(menu))
419 return;
421 sym = menu->sym;
422 prop = menu->prompt;
423 if (prop) {
424 const char *prompt;
426 switch (prop->type) {
427 case P_MENU:
428 if (input_mode == ask_silent && rootEntry != menu) {
429 check_conf(menu);
430 return;
432 case P_COMMENT:
433 prompt = menu_get_prompt(menu);
434 if (prompt)
435 printf("%*c\n%*c %s\n%*c\n",
436 indent, '*',
437 indent, '*', _(prompt),
438 indent, '*');
439 default:
444 if (!sym)
445 goto conf_childs;
447 if (sym_is_choice(sym)) {
448 conf_choice(menu);
449 if (sym->curr.tri != mod)
450 return;
451 goto conf_childs;
454 switch (sym->type) {
455 case S_INT:
456 case S_HEX:
457 case S_STRING:
458 conf_string(menu);
459 break;
460 default:
461 conf_sym(menu);
462 break;
465 conf_childs:
466 if (sym)
467 indent += 2;
468 for (child = menu->list; child; child = child->next)
469 conf(child);
470 if (sym)
471 indent -= 2;
474 static void check_conf(struct menu *menu)
476 struct symbol *sym;
477 struct menu *child;
479 if (!menu_is_visible(menu))
480 return;
482 sym = menu->sym;
483 if (sym && !sym_has_value(sym)) {
484 if (sym_is_changable(sym) ||
485 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
486 if (!conf_cnt++)
487 printf(_("*\n* Restart config...\n*\n"));
488 rootEntry = menu_get_parent_menu(menu);
489 conf(rootEntry);
493 for (child = menu->list; child; child = child->next)
494 check_conf(child);
497 int main(int ac, char **av)
499 int opt;
500 const char *name;
501 struct stat tmpstat;
503 setlocale(LC_ALL, "");
504 bindtextdomain(PACKAGE, LOCALEDIR);
505 textdomain(PACKAGE);
507 while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
508 switch (opt) {
509 case 'o':
510 input_mode = ask_new;
511 break;
512 case 's':
513 input_mode = ask_silent;
514 valid_stdin = isatty(0) && isatty(1) && isatty(2);
515 break;
516 case 'd':
517 input_mode = set_default;
518 break;
519 case 'D':
520 input_mode = set_default;
521 defconfig_file = optarg;
522 break;
523 case 'n':
524 input_mode = set_no;
525 break;
526 case 'm':
527 input_mode = set_mod;
528 break;
529 case 'y':
530 input_mode = set_yes;
531 break;
532 case 'r':
533 input_mode = set_random;
534 srand(time(NULL));
535 break;
536 case 'h':
537 printf(_("See README for usage info\n"));
538 exit(0);
539 break;
540 default:
541 fprintf(stderr, _("See README for usage info\n"));
542 exit(1);
545 if (ac == optind) {
546 printf(_("%s: Kconfig file missing\n"), av[0]);
547 exit(1);
549 name = av[optind];
550 conf_parse(name);
551 //zconfdump(stdout);
552 switch (input_mode) {
553 case set_default:
554 if (!defconfig_file)
555 defconfig_file = conf_get_default_confname();
556 if (conf_read(defconfig_file)) {
557 printf(_("***\n"
558 "*** Can't find default configuration \"%s\"!\n"
559 "***\n"), defconfig_file);
560 exit(1);
562 break;
563 case ask_silent:
564 if (stat(".config", &tmpstat)) {
565 printf(_("***\n"
566 "*** You have not yet configured your kernel!\n"
567 "*** (missing kernel .config file)\n"
568 "***\n"
569 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
570 "*** \"make menuconfig\" or \"make xconfig\").\n"
571 "***\n"));
572 exit(1);
574 case ask_all:
575 case ask_new:
576 conf_read(NULL);
577 break;
578 case set_no:
579 case set_mod:
580 case set_yes:
581 case set_random:
582 name = getenv("KCONFIG_ALLCONFIG");
583 if (name && !stat(name, &tmpstat)) {
584 conf_read_simple(name, S_DEF_USER);
585 break;
587 switch (input_mode) {
588 case set_no: name = "allno.config"; break;
589 case set_mod: name = "allmod.config"; break;
590 case set_yes: name = "allyes.config"; break;
591 case set_random: name = "allrandom.config"; break;
592 default: break;
594 if (!stat(name, &tmpstat))
595 conf_read_simple(name, S_DEF_USER);
596 else if (!stat("all.config", &tmpstat))
597 conf_read_simple("all.config", S_DEF_USER);
598 break;
599 default:
600 break;
603 if (input_mode != ask_silent) {
604 rootEntry = &rootmenu;
605 conf(&rootmenu);
606 if (input_mode == ask_all) {
607 input_mode = ask_silent;
608 valid_stdin = 1;
610 } else if (conf_get_changed()) {
611 name = getenv("KCONFIG_NOSILENTUPDATE");
612 if (name && *name) {
613 fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
614 return 1;
616 } else
617 goto skip_check;
619 do {
620 conf_cnt = 0;
621 check_conf(&rootmenu);
622 } while (conf_cnt);
623 if (conf_write(NULL)) {
624 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
625 return 1;
627 skip_check:
628 if (input_mode == ask_silent && conf_write_autoconf()) {
629 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
630 return 1;
633 return 0;