xref: /openbmc/linux/scripts/kconfig/conf.c (revision a1e58bbd)
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 	tristate val;
80 
81 	if (!sym_has_value(sym))
82 		printf(_("(NEW) "));
83 
84 	line[0] = '\n';
85 	line[1] = 0;
86 
87 	if (!sym_is_changable(sym)) {
88 		printf("%s\n", def);
89 		line[0] = '\n';
90 		line[1] = 0;
91 		return 0;
92 	}
93 
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;
102 		}
103 		break;
104 	case ask_new:
105 	case ask_silent:
106 		if (sym_has_value(sym)) {
107 			printf("%s\n", def);
108 			return 0;
109 		}
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;
120 	}
121 
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:
129 		;
130 	}
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;
138 		}
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;
146 			}
147 		} else {
148 			if (sym_tristate_within_range(sym, yes)) {
149 				line[0] = 'y';
150 				line[1] = '\n';
151 				line[2] = 0;
152 				break;
153 			}
154 		}
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;
161 		}
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;
170 		}
171 		line[1] = '\n';
172 		line[2] = 0;
173 		break;
174 	default:
175 		break;
176 	}
177 	printf("%s", line);
178 	return 1;
179 }
180 
181 int conf_string(struct menu *menu)
182 {
183 	struct symbol *sym = menu->sym;
184 	const char *def;
185 
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;
203 			}
204 		default:
205 			line[strlen(line)-1] = 0;
206 			def = line;
207 		}
208 		if (def && sym_set_string_value(sym, def))
209 			return 0;
210 	}
211 }
212 
213 static int conf_sym(struct menu *menu)
214 {
215 	struct symbol *sym = menu->sym;
216 	int type;
217 	tristate oldval, newval;
218 
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;
236 		}
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);
249 
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;
276 		}
277 		if (sym_set_tristate_value(sym, newval))
278 			return 0;
279 help:
280 		printf("\n%s\n", get_help(menu));
281 	}
282 }
283 
284 static int conf_choice(struct menu *menu)
285 {
286 	struct symbol *sym, *def_sym;
287 	struct menu *child;
288 	int type;
289 	bool is_new;
290 
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;
304 		}
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;
314 		}
315 	}
316 
317 	while (1) {
318 		int cnt, def;
319 
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;
330 			}
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");
343 		}
344 		printf(_("%*schoice"), indent - 1, "");
345 		if (cnt == 1) {
346 			printf("[1]: 1\n");
347 			goto conf_childs;
348 		}
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;
360 			}
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;
369 			}
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;
387 		}
388 
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;
395 		}
396 		if (!child)
397 			continue;
398 		if (line[strlen(line) - 1] == '?') {
399 			printf("\n%s\n", get_help(child));
400 			continue;
401 		}
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;
407 		}
408 		return 1;
409 	}
410 }
411 
412 static void conf(struct menu *menu)
413 {
414 	struct symbol *sym;
415 	struct property *prop;
416 	struct menu *child;
417 
418 	if (!menu_is_visible(menu))
419 		return;
420 
421 	sym = menu->sym;
422 	prop = menu->prompt;
423 	if (prop) {
424 		const char *prompt;
425 
426 		switch (prop->type) {
427 		case P_MENU:
428 			if (input_mode == ask_silent && rootEntry != menu) {
429 				check_conf(menu);
430 				return;
431 			}
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:
440 			;
441 		}
442 	}
443 
444 	if (!sym)
445 		goto conf_childs;
446 
447 	if (sym_is_choice(sym)) {
448 		conf_choice(menu);
449 		if (sym->curr.tri != mod)
450 			return;
451 		goto conf_childs;
452 	}
453 
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;
463 	}
464 
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;
472 }
473 
474 static void check_conf(struct menu *menu)
475 {
476 	struct symbol *sym;
477 	struct menu *child;
478 
479 	if (!menu_is_visible(menu))
480 		return;
481 
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);
490 		}
491 	}
492 
493 	for (child = menu->list; child; child = child->next)
494 		check_conf(child);
495 }
496 
497 int main(int ac, char **av)
498 {
499 	int opt;
500 	const char *name;
501 	struct stat tmpstat;
502 
503 	setlocale(LC_ALL, "");
504 	bindtextdomain(PACKAGE, LOCALEDIR);
505 	textdomain(PACKAGE);
506 
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);
543 		}
544 	}
545 	if (ac == optind) {
546 		printf(_("%s: Kconfig file missing\n"), av[0]);
547 		exit(1);
548 	}
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);
561 		}
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);
573 		}
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;
586 		}
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;
593 		}
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;
601 	}
602 
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;
609 		}
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;
615 		}
616 	} else
617 		goto skip_check;
618 
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;
626 	}
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;
631 	}
632 
633 	return 0;
634 }
635