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