blob: ae5ab981bb1d170d215bf9bde96845d731c8e7e0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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 <string.h>
9#include <unistd.h>
10#include <time.h>
11#include <sys/stat.h>
12
13#define LKC_DIRECT_LINK
14#include "lkc.h"
15
16static void conf(struct menu *menu);
17static void check_conf(struct menu *menu);
18
19enum {
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;
29char *defconfig_file;
30
31static int indent = 1;
32static int valid_stdin = 1;
33static int conf_cnt;
J.A. Magallon48b9d032005-06-25 14:59:22 -070034static char line[128];
Linus Torvalds1da177e2005-04-16 15:20:36 -070035static struct menu *rootEntry;
36
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070037static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
J.A. Magallon48b9d032005-06-25 14:59:22 -070039static void strip(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -070040{
J.A. Magallon48b9d032005-06-25 14:59:22 -070041 char *p = str;
Linus Torvalds1da177e2005-04-16 15:20:36 -070042 int l;
43
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;
54}
55
56static void check_stdin(void)
57{
58 if (!valid_stdin && input_mode == ask_silent) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070059 printf(_("aborted!\n\n"));
60 printf(_("Console input/output is redirected. "));
61 printf(_("Run 'make oldconfig' to update configuration.\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 exit(1);
63 }
64}
65
66static void conf_askvalue(struct symbol *sym, const char *def)
67{
68 enum symbol_type type = sym_get_type(sym);
69 tristate val;
70
71 if (!sym_has_value(sym))
72 printf("(NEW) ");
73
74 line[0] = '\n';
75 line[1] = 0;
76
77 if (!sym_is_changable(sym)) {
78 printf("%s\n", def);
79 line[0] = '\n';
80 line[1] = 0;
81 return;
82 }
83
84 switch (input_mode) {
Roman Zippel90389162005-11-08 21:34:49 -080085 case set_no:
86 case set_mod:
87 case set_yes:
88 case set_random:
89 if (sym_has_value(sym)) {
90 printf("%s\n", def);
91 return;
92 }
93 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 case ask_new:
95 case ask_silent:
96 if (sym_has_value(sym)) {
97 printf("%s\n", def);
98 return;
99 }
100 check_stdin();
101 case ask_all:
102 fflush(stdout);
Roman Zippel59c6a3f2006-04-09 17:26:50 +0200103 fgets(line, 128, stdin);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 return;
105 case set_default:
106 printf("%s\n", def);
107 return;
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;
118 default:
119 ;
120 }
121 switch (input_mode) {
122 case set_yes:
123 if (sym_tristate_within_range(sym, yes)) {
124 line[0] = 'y';
125 line[1] = '\n';
126 line[2] = 0;
127 break;
128 }
129 case set_mod:
130 if (type == S_TRISTATE) {
131 if (sym_tristate_within_range(sym, mod)) {
132 line[0] = 'm';
133 line[1] = '\n';
134 line[2] = 0;
135 break;
136 }
137 } else {
138 if (sym_tristate_within_range(sym, yes)) {
139 line[0] = 'y';
140 line[1] = '\n';
141 line[2] = 0;
142 break;
143 }
144 }
145 case set_no:
146 if (sym_tristate_within_range(sym, no)) {
147 line[0] = 'n';
148 line[1] = '\n';
149 line[2] = 0;
150 break;
151 }
152 case set_random:
153 do {
154 val = (tristate)(random() % 3);
155 } while (!sym_tristate_within_range(sym, val));
156 switch (val) {
157 case no: line[0] = 'n'; break;
158 case mod: line[0] = 'm'; break;
159 case yes: line[0] = 'y'; break;
160 }
161 line[1] = '\n';
162 line[2] = 0;
163 break;
164 default:
165 break;
166 }
167 printf("%s", line);
168}
169
170int conf_string(struct menu *menu)
171{
172 struct symbol *sym = menu->sym;
173 const char *def, *help;
174
175 while (1) {
176 printf("%*s%s ", indent - 1, "", menu->prompt->text);
177 printf("(%s) ", sym->name);
178 def = sym_get_string_value(sym);
179 if (sym_get_string_value(sym))
180 printf("[%s] ", def);
181 conf_askvalue(sym, def);
182 switch (line[0]) {
183 case '\n':
184 break;
185 case '?':
186 /* print help */
187 if (line[1] == '\n') {
188 help = nohelp_text;
189 if (menu->sym->help)
190 help = menu->sym->help;
191 printf("\n%s\n", menu->sym->help);
192 def = NULL;
193 break;
194 }
195 default:
196 line[strlen(line)-1] = 0;
197 def = line;
198 }
199 if (def && sym_set_string_value(sym, def))
200 return 0;
201 }
202}
203
204static int conf_sym(struct menu *menu)
205{
206 struct symbol *sym = menu->sym;
207 int type;
208 tristate oldval, newval;
209 const char *help;
210
211 while (1) {
212 printf("%*s%s ", indent - 1, "", menu->prompt->text);
213 if (sym->name)
214 printf("(%s) ", sym->name);
215 type = sym_get_type(sym);
216 putchar('[');
217 oldval = sym_get_tristate_value(sym);
218 switch (oldval) {
219 case no:
220 putchar('N');
221 break;
222 case mod:
223 putchar('M');
224 break;
225 case yes:
226 putchar('Y');
227 break;
228 }
229 if (oldval != no && sym_tristate_within_range(sym, no))
230 printf("/n");
231 if (oldval != mod && sym_tristate_within_range(sym, mod))
232 printf("/m");
233 if (oldval != yes && sym_tristate_within_range(sym, yes))
234 printf("/y");
235 if (sym->help)
236 printf("/?");
237 printf("] ");
238 conf_askvalue(sym, sym_get_string_value(sym));
239 strip(line);
240
241 switch (line[0]) {
242 case 'n':
243 case 'N':
244 newval = no;
245 if (!line[1] || !strcmp(&line[1], "o"))
246 break;
247 continue;
248 case 'm':
249 case 'M':
250 newval = mod;
251 if (!line[1])
252 break;
253 continue;
254 case 'y':
255 case 'Y':
256 newval = yes;
257 if (!line[1] || !strcmp(&line[1], "es"))
258 break;
259 continue;
260 case 0:
261 newval = oldval;
262 break;
263 case '?':
264 goto help;
265 default:
266 continue;
267 }
268 if (sym_set_tristate_value(sym, newval))
269 return 0;
270help:
271 help = nohelp_text;
272 if (sym->help)
273 help = sym->help;
274 printf("\n%s\n", help);
275 }
276}
277
278static int conf_choice(struct menu *menu)
279{
280 struct symbol *sym, *def_sym;
281 struct menu *child;
282 int type;
283 bool is_new;
284
285 sym = menu->sym;
286 type = sym_get_type(sym);
287 is_new = !sym_has_value(sym);
288 if (sym_is_changable(sym)) {
289 conf_sym(menu);
290 sym_calc_value(sym);
291 switch (sym_get_tristate_value(sym)) {
292 case no:
293 return 1;
294 case mod:
295 return 0;
296 case yes:
297 break;
298 }
299 } else {
300 switch (sym_get_tristate_value(sym)) {
301 case no:
302 return 1;
303 case mod:
304 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
305 return 0;
306 case yes:
307 break;
308 }
309 }
310
311 while (1) {
312 int cnt, def;
313
314 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
315 def_sym = sym_get_choice_value(sym);
316 cnt = def = 0;
Roman Zippel40aee722006-04-09 17:26:39 +0200317 line[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 for (child = menu->list; child; child = child->next) {
319 if (!menu_is_visible(child))
320 continue;
321 if (!child->sym) {
322 printf("%*c %s\n", indent, '*', menu_get_prompt(child));
323 continue;
324 }
325 cnt++;
326 if (child->sym == def_sym) {
327 def = cnt;
328 printf("%*c", indent, '>');
329 } else
330 printf("%*c", indent, ' ');
331 printf(" %d. %s", cnt, menu_get_prompt(child));
332 if (child->sym->name)
333 printf(" (%s)", child->sym->name);
334 if (!sym_has_value(child->sym))
335 printf(" (NEW)");
336 printf("\n");
337 }
338 printf("%*schoice", indent - 1, "");
339 if (cnt == 1) {
340 printf("[1]: 1\n");
341 goto conf_childs;
342 }
343 printf("[1-%d", cnt);
344 if (sym->help)
345 printf("?");
346 printf("]: ");
347 switch (input_mode) {
348 case ask_new:
349 case ask_silent:
350 if (!is_new) {
351 cnt = def;
352 printf("%d\n", cnt);
353 break;
354 }
355 check_stdin();
356 case ask_all:
357 fflush(stdout);
Roman Zippel59c6a3f2006-04-09 17:26:50 +0200358 fgets(line, 128, stdin);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 strip(line);
360 if (line[0] == '?') {
361 printf("\n%s\n", menu->sym->help ?
362 menu->sym->help : nohelp_text);
363 continue;
364 }
365 if (!line[0])
366 cnt = def;
367 else if (isdigit(line[0]))
368 cnt = atoi(line);
369 else
370 continue;
371 break;
372 case set_random:
373 def = (random() % cnt) + 1;
374 case set_default:
375 case set_yes:
376 case set_mod:
377 case set_no:
378 cnt = def;
379 printf("%d\n", cnt);
380 break;
381 }
382
383 conf_childs:
384 for (child = menu->list; child; child = child->next) {
385 if (!child->sym || !menu_is_visible(child))
386 continue;
387 if (!--cnt)
388 break;
389 }
390 if (!child)
391 continue;
392 if (line[strlen(line) - 1] == '?') {
393 printf("\n%s\n", child->sym->help ?
394 child->sym->help : nohelp_text);
395 continue;
396 }
397 sym_set_choice_value(sym, child->sym);
398 if (child->list) {
399 indent += 2;
400 conf(child->list);
401 indent -= 2;
402 }
403 return 1;
404 }
405}
406
407static void conf(struct menu *menu)
408{
409 struct symbol *sym;
410 struct property *prop;
411 struct menu *child;
412
413 if (!menu_is_visible(menu))
414 return;
415
416 sym = menu->sym;
417 prop = menu->prompt;
418 if (prop) {
419 const char *prompt;
420
421 switch (prop->type) {
422 case P_MENU:
423 if (input_mode == ask_silent && rootEntry != menu) {
424 check_conf(menu);
425 return;
426 }
427 case P_COMMENT:
428 prompt = menu_get_prompt(menu);
429 if (prompt)
430 printf("%*c\n%*c %s\n%*c\n",
431 indent, '*',
432 indent, '*', prompt,
433 indent, '*');
434 default:
435 ;
436 }
437 }
438
439 if (!sym)
440 goto conf_childs;
441
442 if (sym_is_choice(sym)) {
443 conf_choice(menu);
444 if (sym->curr.tri != mod)
445 return;
446 goto conf_childs;
447 }
448
449 switch (sym->type) {
450 case S_INT:
451 case S_HEX:
452 case S_STRING:
453 conf_string(menu);
454 break;
455 default:
456 conf_sym(menu);
457 break;
458 }
459
460conf_childs:
461 if (sym)
462 indent += 2;
463 for (child = menu->list; child; child = child->next)
464 conf(child);
465 if (sym)
466 indent -= 2;
467}
468
469static void check_conf(struct menu *menu)
470{
471 struct symbol *sym;
472 struct menu *child;
473
474 if (!menu_is_visible(menu))
475 return;
476
477 sym = menu->sym;
Roman Zippel3f23ca22005-11-08 21:34:48 -0800478 if (sym && !sym_has_value(sym)) {
479 if (sym_is_changable(sym) ||
480 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 if (!conf_cnt++)
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700482 printf(_("*\n* Restart config...\n*\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 rootEntry = menu_get_parent_menu(menu);
484 conf(rootEntry);
485 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 }
487
488 for (child = menu->list; child; child = child->next)
489 check_conf(child);
490}
491
492int main(int ac, char **av)
493{
494 int i = 1;
495 const char *name;
496 struct stat tmpstat;
497
498 if (ac > i && av[i][0] == '-') {
499 switch (av[i++][1]) {
500 case 'o':
501 input_mode = ask_new;
502 break;
503 case 's':
504 input_mode = ask_silent;
505 valid_stdin = isatty(0) && isatty(1) && isatty(2);
506 break;
507 case 'd':
508 input_mode = set_default;
509 break;
510 case 'D':
511 input_mode = set_default;
512 defconfig_file = av[i++];
513 if (!defconfig_file) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700514 printf(_("%s: No default config file specified\n"),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 av[0]);
516 exit(1);
517 }
518 break;
519 case 'n':
520 input_mode = set_no;
521 break;
522 case 'm':
523 input_mode = set_mod;
524 break;
525 case 'y':
526 input_mode = set_yes;
527 break;
528 case 'r':
529 input_mode = set_random;
530 srandom(time(NULL));
531 break;
532 case 'h':
533 case '?':
534 printf("%s [-o|-s] config\n", av[0]);
535 exit(0);
536 }
537 }
538 name = av[i];
539 if (!name) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700540 printf(_("%s: Kconfig file missing\n"), av[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 }
542 conf_parse(name);
543 //zconfdump(stdout);
544 switch (input_mode) {
545 case set_default:
546 if (!defconfig_file)
547 defconfig_file = conf_get_default_confname();
548 if (conf_read(defconfig_file)) {
549 printf("***\n"
550 "*** Can't find default configuration \"%s\"!\n"
551 "***\n", defconfig_file);
552 exit(1);
553 }
554 break;
555 case ask_silent:
556 if (stat(".config", &tmpstat)) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700557 printf(_("***\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 "*** You have not yet configured your kernel!\n"
559 "***\n"
560 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
561 "*** \"make menuconfig\" or \"make xconfig\").\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700562 "***\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 exit(1);
564 }
565 case ask_all:
566 case ask_new:
567 conf_read(NULL);
568 break;
Roman Zippel90389162005-11-08 21:34:49 -0800569 case set_no:
570 case set_mod:
571 case set_yes:
572 case set_random:
573 name = getenv("KCONFIG_ALLCONFIG");
574 if (name && !stat(name, &tmpstat)) {
575 conf_read_simple(name);
576 break;
577 }
578 switch (input_mode) {
579 case set_no: name = "allno.config"; break;
580 case set_mod: name = "allmod.config"; break;
581 case set_yes: name = "allyes.config"; break;
582 case set_random: name = "allrandom.config"; break;
583 default: break;
584 }
585 if (!stat(name, &tmpstat))
586 conf_read_simple(name);
587 else if (!stat("all.config", &tmpstat))
588 conf_read_simple("all.config");
589 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 default:
591 break;
592 }
593
594 if (input_mode != ask_silent) {
595 rootEntry = &rootmenu;
596 conf(&rootmenu);
597 if (input_mode == ask_all) {
598 input_mode = ask_silent;
599 valid_stdin = 1;
600 }
601 }
602 do {
603 conf_cnt = 0;
604 check_conf(&rootmenu);
605 } while (conf_cnt);
606 if (conf_write(NULL)) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700607 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 return 1;
609 }
610 return 0;
611}