kconfig: fix default value for choice input
[linux-2.6/btrfs-unstable.git] / scripts / kconfig / conf.c
blobb86c64f90c943676c45f8e814f3a86953b3a5e50
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 <ctype.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <time.h>
11 #include <sys/stat.h>
13 #define LKC_DIRECT_LINK
14 #include "lkc.h"
16 static void conf(struct menu *menu);
17 static void check_conf(struct menu *menu);
19 enum {
20 ask_all,
21 ask_new,
22 ask_silent,
23 set_default,
24 set_yes,
25 set_mod,
26 set_no,
27 set_random
28 } input_mode = ask_all;
29 char *defconfig_file;
31 static int indent = 1;
32 static int valid_stdin = 1;
33 static int conf_cnt;
34 static char line[128];
35 static struct menu *rootEntry;
37 static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
39 static void strip(char *str)
41 char *p = str;
42 int l;
44 while ((isspace(*p)))
45 p++;
46 l = strlen(p);
47 if (p != str)
48 memmove(str, p, l + 1);
49 if (!l)
50 return;
51 p = str + l - 1;
52 while ((isspace(*p)))
53 *p-- = 0;
56 static void check_stdin(void)
58 if (!valid_stdin && input_mode == ask_silent) {
59 printf(_("aborted!\n\n"));
60 printf(_("Console input/output is redirected. "));
61 printf(_("Run 'make oldconfig' to update configuration.\n\n"));
62 exit(1);
66 static char *fgets_check_stream(char *s, int size, FILE *stream)
68 char *ret = fgets(s, size, stream);
70 if (ret == NULL && feof(stream)) {
71 printf(_("aborted!\n\n"));
72 printf(_("Console input is closed. "));
73 printf(_("Run 'make oldconfig' to update configuration.\n\n"));
74 exit(1);
77 return ret;
80 static void conf_askvalue(struct symbol *sym, const char *def)
82 enum symbol_type type = sym_get_type(sym);
83 tristate val;
85 if (!sym_has_value(sym))
86 printf("(NEW) ");
88 line[0] = '\n';
89 line[1] = 0;
91 if (!sym_is_changable(sym)) {
92 printf("%s\n", def);
93 line[0] = '\n';
94 line[1] = 0;
95 return;
98 switch (input_mode) {
99 case set_no:
100 case set_mod:
101 case set_yes:
102 case set_random:
103 if (sym_has_value(sym)) {
104 printf("%s\n", def);
105 return;
107 break;
108 case ask_new:
109 case ask_silent:
110 if (sym_has_value(sym)) {
111 printf("%s\n", def);
112 return;
114 check_stdin();
115 case ask_all:
116 fflush(stdout);
117 fgets_check_stream(line, 128, stdin);
118 return;
119 case set_default:
120 printf("%s\n", def);
121 return;
122 default:
123 break;
126 switch (type) {
127 case S_INT:
128 case S_HEX:
129 case S_STRING:
130 printf("%s\n", def);
131 return;
132 default:
135 switch (input_mode) {
136 case set_yes:
137 if (sym_tristate_within_range(sym, yes)) {
138 line[0] = 'y';
139 line[1] = '\n';
140 line[2] = 0;
141 break;
143 case set_mod:
144 if (type == S_TRISTATE) {
145 if (sym_tristate_within_range(sym, mod)) {
146 line[0] = 'm';
147 line[1] = '\n';
148 line[2] = 0;
149 break;
151 } else {
152 if (sym_tristate_within_range(sym, yes)) {
153 line[0] = 'y';
154 line[1] = '\n';
155 line[2] = 0;
156 break;
159 case set_no:
160 if (sym_tristate_within_range(sym, no)) {
161 line[0] = 'n';
162 line[1] = '\n';
163 line[2] = 0;
164 break;
166 case set_random:
167 do {
168 val = (tristate)(random() % 3);
169 } while (!sym_tristate_within_range(sym, val));
170 switch (val) {
171 case no: line[0] = 'n'; break;
172 case mod: line[0] = 'm'; break;
173 case yes: line[0] = 'y'; break;
175 line[1] = '\n';
176 line[2] = 0;
177 break;
178 default:
179 break;
181 printf("%s", line);
184 int conf_string(struct menu *menu)
186 struct symbol *sym = menu->sym;
187 const char *def, *help;
189 while (1) {
190 printf("%*s%s ", indent - 1, "", menu->prompt->text);
191 printf("(%s) ", sym->name);
192 def = sym_get_string_value(sym);
193 if (sym_get_string_value(sym))
194 printf("[%s] ", def);
195 conf_askvalue(sym, def);
196 switch (line[0]) {
197 case '\n':
198 break;
199 case '?':
200 /* print help */
201 if (line[1] == '\n') {
202 help = nohelp_text;
203 if (menu->sym->help)
204 help = menu->sym->help;
205 printf("\n%s\n", menu->sym->help);
206 def = NULL;
207 break;
209 default:
210 line[strlen(line)-1] = 0;
211 def = line;
213 if (def && sym_set_string_value(sym, def))
214 return 0;
218 static int conf_sym(struct menu *menu)
220 struct symbol *sym = menu->sym;
221 int type;
222 tristate oldval, newval;
223 const char *help;
225 while (1) {
226 printf("%*s%s ", indent - 1, "", menu->prompt->text);
227 if (sym->name)
228 printf("(%s) ", sym->name);
229 type = sym_get_type(sym);
230 putchar('[');
231 oldval = sym_get_tristate_value(sym);
232 switch (oldval) {
233 case no:
234 putchar('N');
235 break;
236 case mod:
237 putchar('M');
238 break;
239 case yes:
240 putchar('Y');
241 break;
243 if (oldval != no && sym_tristate_within_range(sym, no))
244 printf("/n");
245 if (oldval != mod && sym_tristate_within_range(sym, mod))
246 printf("/m");
247 if (oldval != yes && sym_tristate_within_range(sym, yes))
248 printf("/y");
249 if (sym->help)
250 printf("/?");
251 printf("] ");
252 conf_askvalue(sym, sym_get_string_value(sym));
253 strip(line);
255 switch (line[0]) {
256 case 'n':
257 case 'N':
258 newval = no;
259 if (!line[1] || !strcmp(&line[1], "o"))
260 break;
261 continue;
262 case 'm':
263 case 'M':
264 newval = mod;
265 if (!line[1])
266 break;
267 continue;
268 case 'y':
269 case 'Y':
270 newval = yes;
271 if (!line[1] || !strcmp(&line[1], "es"))
272 break;
273 continue;
274 case 0:
275 newval = oldval;
276 break;
277 case '?':
278 goto help;
279 default:
280 continue;
282 if (sym_set_tristate_value(sym, newval))
283 return 0;
284 help:
285 help = nohelp_text;
286 if (sym->help)
287 help = sym->help;
288 printf("\n%s\n", help);
292 static int conf_choice(struct menu *menu)
294 struct symbol *sym, *def_sym;
295 struct menu *child;
296 int type;
297 bool is_new;
299 sym = menu->sym;
300 type = sym_get_type(sym);
301 is_new = !sym_has_value(sym);
302 if (sym_is_changable(sym)) {
303 conf_sym(menu);
304 sym_calc_value(sym);
305 switch (sym_get_tristate_value(sym)) {
306 case no:
307 return 1;
308 case mod:
309 return 0;
310 case yes:
311 break;
313 } else {
314 switch (sym_get_tristate_value(sym)) {
315 case no:
316 return 1;
317 case mod:
318 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
319 return 0;
320 case yes:
321 break;
325 while (1) {
326 int cnt, def;
328 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
329 def_sym = sym_get_choice_value(sym);
330 cnt = def = 0;
331 line[0] = 0;
332 for (child = menu->list; child; child = child->next) {
333 if (!menu_is_visible(child))
334 continue;
335 if (!child->sym) {
336 printf("%*c %s\n", indent, '*', menu_get_prompt(child));
337 continue;
339 cnt++;
340 if (child->sym == def_sym) {
341 def = cnt;
342 printf("%*c", indent, '>');
343 } else
344 printf("%*c", indent, ' ');
345 printf(" %d. %s", cnt, menu_get_prompt(child));
346 if (child->sym->name)
347 printf(" (%s)", child->sym->name);
348 if (!sym_has_value(child->sym))
349 printf(" (NEW)");
350 printf("\n");
352 printf("%*schoice", indent - 1, "");
353 if (cnt == 1) {
354 printf("[1]: 1\n");
355 goto conf_childs;
357 printf("[1-%d", cnt);
358 if (sym->help)
359 printf("?");
360 printf("]: ");
361 switch (input_mode) {
362 case ask_new:
363 case ask_silent:
364 if (!is_new) {
365 cnt = def;
366 printf("%d\n", cnt);
367 break;
369 check_stdin();
370 case ask_all:
371 fflush(stdout);
372 fgets_check_stream(line, 128, stdin);
373 strip(line);
374 if (line[0] == '?') {
375 printf("\n%s\n", menu->sym->help ?
376 menu->sym->help : nohelp_text);
377 continue;
379 if (!line[0])
380 cnt = def;
381 else if (isdigit(line[0]))
382 cnt = atoi(line);
383 else
384 continue;
385 break;
386 case set_random:
387 def = (random() % cnt) + 1;
388 case set_default:
389 case set_yes:
390 case set_mod:
391 case set_no:
392 cnt = def;
393 printf("%d\n", cnt);
394 break;
397 conf_childs:
398 for (child = menu->list; child; child = child->next) {
399 if (!child->sym || !menu_is_visible(child))
400 continue;
401 if (!--cnt)
402 break;
404 if (!child)
405 continue;
406 if (line[strlen(line) - 1] == '?') {
407 printf("\n%s\n", child->sym->help ?
408 child->sym->help : nohelp_text);
409 continue;
411 sym_set_choice_value(sym, child->sym);
412 if (child->list) {
413 indent += 2;
414 conf(child->list);
415 indent -= 2;
417 return 1;
421 static void conf(struct menu *menu)
423 struct symbol *sym;
424 struct property *prop;
425 struct menu *child;
427 if (!menu_is_visible(menu))
428 return;
430 sym = menu->sym;
431 prop = menu->prompt;
432 if (prop) {
433 const char *prompt;
435 switch (prop->type) {
436 case P_MENU:
437 if (input_mode == ask_silent && rootEntry != menu) {
438 check_conf(menu);
439 return;
441 case P_COMMENT:
442 prompt = menu_get_prompt(menu);
443 if (prompt)
444 printf("%*c\n%*c %s\n%*c\n",
445 indent, '*',
446 indent, '*', prompt,
447 indent, '*');
448 default:
453 if (!sym)
454 goto conf_childs;
456 if (sym_is_choice(sym)) {
457 conf_choice(menu);
458 if (sym->curr.tri != mod)
459 return;
460 goto conf_childs;
463 switch (sym->type) {
464 case S_INT:
465 case S_HEX:
466 case S_STRING:
467 conf_string(menu);
468 break;
469 default:
470 conf_sym(menu);
471 break;
474 conf_childs:
475 if (sym)
476 indent += 2;
477 for (child = menu->list; child; child = child->next)
478 conf(child);
479 if (sym)
480 indent -= 2;
483 static void check_conf(struct menu *menu)
485 struct symbol *sym;
486 struct menu *child;
488 if (!menu_is_visible(menu))
489 return;
491 sym = menu->sym;
492 if (sym && !sym_has_value(sym)) {
493 if (sym_is_changable(sym) ||
494 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
495 if (!conf_cnt++)
496 printf(_("*\n* Restart config...\n*\n"));
497 rootEntry = menu_get_parent_menu(menu);
498 conf(rootEntry);
502 for (child = menu->list; child; child = child->next)
503 check_conf(child);
506 int main(int ac, char **av)
508 int i = 1;
509 const char *name;
510 struct stat tmpstat;
512 if (ac > i && av[i][0] == '-') {
513 switch (av[i++][1]) {
514 case 'o':
515 input_mode = ask_new;
516 break;
517 case 's':
518 input_mode = ask_silent;
519 valid_stdin = isatty(0) && isatty(1) && isatty(2);
520 break;
521 case 'd':
522 input_mode = set_default;
523 break;
524 case 'D':
525 input_mode = set_default;
526 defconfig_file = av[i++];
527 if (!defconfig_file) {
528 printf(_("%s: No default config file specified\n"),
529 av[0]);
530 exit(1);
532 break;
533 case 'n':
534 input_mode = set_no;
535 break;
536 case 'm':
537 input_mode = set_mod;
538 break;
539 case 'y':
540 input_mode = set_yes;
541 break;
542 case 'r':
543 input_mode = set_random;
544 srandom(time(NULL));
545 break;
546 case 'h':
547 case '?':
548 printf("%s [-o|-s] config\n", av[0]);
549 exit(0);
552 name = av[i];
553 if (!name) {
554 printf(_("%s: Kconfig file missing\n"), av[0]);
556 conf_parse(name);
557 //zconfdump(stdout);
558 switch (input_mode) {
559 case set_default:
560 if (!defconfig_file)
561 defconfig_file = conf_get_default_confname();
562 if (conf_read(defconfig_file)) {
563 printf("***\n"
564 "*** Can't find default configuration \"%s\"!\n"
565 "***\n", defconfig_file);
566 exit(1);
568 break;
569 case ask_silent:
570 if (stat(".config", &tmpstat)) {
571 printf(_("***\n"
572 "*** You have not yet configured your kernel!\n"
573 "***\n"
574 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
575 "*** \"make menuconfig\" or \"make xconfig\").\n"
576 "***\n"));
577 exit(1);
579 case ask_all:
580 case ask_new:
581 conf_read(NULL);
582 break;
583 case set_no:
584 case set_mod:
585 case set_yes:
586 case set_random:
587 name = getenv("KCONFIG_ALLCONFIG");
588 if (name && !stat(name, &tmpstat)) {
589 conf_read_simple(name);
590 break;
592 switch (input_mode) {
593 case set_no: name = "allno.config"; break;
594 case set_mod: name = "allmod.config"; break;
595 case set_yes: name = "allyes.config"; break;
596 case set_random: name = "allrandom.config"; break;
597 default: break;
599 if (!stat(name, &tmpstat))
600 conf_read_simple(name);
601 else if (!stat("all.config", &tmpstat))
602 conf_read_simple("all.config");
603 break;
604 default:
605 break;
608 if (input_mode != ask_silent) {
609 rootEntry = &rootmenu;
610 conf(&rootmenu);
611 if (input_mode == ask_all) {
612 input_mode = ask_silent;
613 valid_stdin = 1;
616 do {
617 conf_cnt = 0;
618 check_conf(&rootmenu);
619 } while (conf_cnt);
620 if (conf_write(NULL)) {
621 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
622 return 1;
624 return 0;