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