xref: /linux/scripts/kconfig/conf.c (revision 9ce7677cfd7cd871adb457c80bea3b581b839641)
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 <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 
16 static void conf(struct menu *menu);
17 static void check_conf(struct menu *menu);
18 
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;
30 
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;
36 
37 static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
38 
39 static void strip(char *str)
40 {
41 	char *p = str;
42 	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 
56 static void check_stdin(void)
57 {
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);
63 	}
64 }
65 
66 static 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) {
85 	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;
94 	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);
103 		fgets(line, 128, stdin);
104 		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 
170 int 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 
204 static 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;
270 help:
271 		help = nohelp_text;
272 		if (sym->help)
273 			help = sym->help;
274 		printf("\n%s\n", help);
275 	}
276 }
277 
278 static 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;
317 		line[0] = '0';
318 		line[1] = 0;
319 		for (child = menu->list; child; child = child->next) {
320 			if (!menu_is_visible(child))
321 				continue;
322 			if (!child->sym) {
323 				printf("%*c %s\n", indent, '*', menu_get_prompt(child));
324 				continue;
325 			}
326 			cnt++;
327 			if (child->sym == def_sym) {
328 				def = cnt;
329 				printf("%*c", indent, '>');
330 			} else
331 				printf("%*c", indent, ' ');
332 			printf(" %d. %s", cnt, menu_get_prompt(child));
333 			if (child->sym->name)
334 				printf(" (%s)", child->sym->name);
335 			if (!sym_has_value(child->sym))
336 				printf(" (NEW)");
337 			printf("\n");
338 		}
339 		printf("%*schoice", indent - 1, "");
340 		if (cnt == 1) {
341 			printf("[1]: 1\n");
342 			goto conf_childs;
343 		}
344 		printf("[1-%d", cnt);
345 		if (sym->help)
346 			printf("?");
347 		printf("]: ");
348 		switch (input_mode) {
349 		case ask_new:
350 		case ask_silent:
351 			if (!is_new) {
352 				cnt = def;
353 				printf("%d\n", cnt);
354 				break;
355 			}
356 			check_stdin();
357 		case ask_all:
358 			fflush(stdout);
359 			fgets(line, 128, stdin);
360 			strip(line);
361 			if (line[0] == '?') {
362 				printf("\n%s\n", menu->sym->help ?
363 					menu->sym->help : nohelp_text);
364 				continue;
365 			}
366 			if (!line[0])
367 				cnt = def;
368 			else if (isdigit(line[0]))
369 				cnt = atoi(line);
370 			else
371 				continue;
372 			break;
373 		case set_random:
374 			def = (random() % cnt) + 1;
375 		case set_default:
376 		case set_yes:
377 		case set_mod:
378 		case set_no:
379 			cnt = def;
380 			printf("%d\n", cnt);
381 			break;
382 		}
383 
384 	conf_childs:
385 		for (child = menu->list; child; child = child->next) {
386 			if (!child->sym || !menu_is_visible(child))
387 				continue;
388 			if (!--cnt)
389 				break;
390 		}
391 		if (!child)
392 			continue;
393 		if (line[strlen(line) - 1] == '?') {
394 			printf("\n%s\n", child->sym->help ?
395 				child->sym->help : nohelp_text);
396 			continue;
397 		}
398 		sym_set_choice_value(sym, child->sym);
399 		if (child->list) {
400 			indent += 2;
401 			conf(child->list);
402 			indent -= 2;
403 		}
404 		return 1;
405 	}
406 }
407 
408 static void conf(struct menu *menu)
409 {
410 	struct symbol *sym;
411 	struct property *prop;
412 	struct menu *child;
413 
414 	if (!menu_is_visible(menu))
415 		return;
416 
417 	sym = menu->sym;
418 	prop = menu->prompt;
419 	if (prop) {
420 		const char *prompt;
421 
422 		switch (prop->type) {
423 		case P_MENU:
424 			if (input_mode == ask_silent && rootEntry != menu) {
425 				check_conf(menu);
426 				return;
427 			}
428 		case P_COMMENT:
429 			prompt = menu_get_prompt(menu);
430 			if (prompt)
431 				printf("%*c\n%*c %s\n%*c\n",
432 					indent, '*',
433 					indent, '*', prompt,
434 					indent, '*');
435 		default:
436 			;
437 		}
438 	}
439 
440 	if (!sym)
441 		goto conf_childs;
442 
443 	if (sym_is_choice(sym)) {
444 		conf_choice(menu);
445 		if (sym->curr.tri != mod)
446 			return;
447 		goto conf_childs;
448 	}
449 
450 	switch (sym->type) {
451 	case S_INT:
452 	case S_HEX:
453 	case S_STRING:
454 		conf_string(menu);
455 		break;
456 	default:
457 		conf_sym(menu);
458 		break;
459 	}
460 
461 conf_childs:
462 	if (sym)
463 		indent += 2;
464 	for (child = menu->list; child; child = child->next)
465 		conf(child);
466 	if (sym)
467 		indent -= 2;
468 }
469 
470 static void check_conf(struct menu *menu)
471 {
472 	struct symbol *sym;
473 	struct menu *child;
474 
475 	if (!menu_is_visible(menu))
476 		return;
477 
478 	sym = menu->sym;
479 	if (sym && !sym_has_value(sym)) {
480 		if (sym_is_changable(sym) ||
481 		    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
482 			if (!conf_cnt++)
483 				printf(_("*\n* Restart config...\n*\n"));
484 			rootEntry = menu_get_parent_menu(menu);
485 			conf(rootEntry);
486 		}
487 	}
488 
489 	for (child = menu->list; child; child = child->next)
490 		check_conf(child);
491 }
492 
493 int main(int ac, char **av)
494 {
495 	int i = 1;
496 	const char *name;
497 	struct stat tmpstat;
498 
499 	if (ac > i && av[i][0] == '-') {
500 		switch (av[i++][1]) {
501 		case 'o':
502 			input_mode = ask_new;
503 			break;
504 		case 's':
505 			input_mode = ask_silent;
506 			valid_stdin = isatty(0) && isatty(1) && isatty(2);
507 			break;
508 		case 'd':
509 			input_mode = set_default;
510 			break;
511 		case 'D':
512 			input_mode = set_default;
513 			defconfig_file = av[i++];
514 			if (!defconfig_file) {
515 				printf(_("%s: No default config file specified\n"),
516 					av[0]);
517 				exit(1);
518 			}
519 			break;
520 		case 'n':
521 			input_mode = set_no;
522 			break;
523 		case 'm':
524 			input_mode = set_mod;
525 			break;
526 		case 'y':
527 			input_mode = set_yes;
528 			break;
529 		case 'r':
530 			input_mode = set_random;
531 			srandom(time(NULL));
532 			break;
533 		case 'h':
534 		case '?':
535 			printf("%s [-o|-s] config\n", av[0]);
536 			exit(0);
537 		}
538 	}
539   	name = av[i];
540 	if (!name) {
541 		printf(_("%s: Kconfig file missing\n"), av[0]);
542 	}
543 	conf_parse(name);
544 	//zconfdump(stdout);
545 	switch (input_mode) {
546 	case set_default:
547 		if (!defconfig_file)
548 			defconfig_file = conf_get_default_confname();
549 		if (conf_read(defconfig_file)) {
550 			printf("***\n"
551 				"*** Can't find default configuration \"%s\"!\n"
552 				"***\n", defconfig_file);
553 			exit(1);
554 		}
555 		break;
556 	case ask_silent:
557 		if (stat(".config", &tmpstat)) {
558 			printf(_("***\n"
559 				"*** You have not yet configured your kernel!\n"
560 				"***\n"
561 				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
562 				"*** \"make menuconfig\" or \"make xconfig\").\n"
563 				"***\n"));
564 			exit(1);
565 		}
566 	case ask_all:
567 	case ask_new:
568 		conf_read(NULL);
569 		break;
570 	case set_no:
571 	case set_mod:
572 	case set_yes:
573 	case set_random:
574 		name = getenv("KCONFIG_ALLCONFIG");
575 		if (name && !stat(name, &tmpstat)) {
576 			conf_read_simple(name);
577 			break;
578 		}
579 		switch (input_mode) {
580 		case set_no:	 name = "allno.config"; break;
581 		case set_mod:	 name = "allmod.config"; break;
582 		case set_yes:	 name = "allyes.config"; break;
583 		case set_random: name = "allrandom.config"; break;
584 		default: break;
585 		}
586 		if (!stat(name, &tmpstat))
587 			conf_read_simple(name);
588 		else if (!stat("all.config", &tmpstat))
589 			conf_read_simple("all.config");
590 		break;
591 	default:
592 		break;
593 	}
594 
595 	if (input_mode != ask_silent) {
596 		rootEntry = &rootmenu;
597 		conf(&rootmenu);
598 		if (input_mode == ask_all) {
599 			input_mode = ask_silent;
600 			valid_stdin = 1;
601 		}
602 	}
603 	do {
604 		conf_cnt = 0;
605 		check_conf(&rootmenu);
606 	} while (conf_cnt);
607 	if (conf_write(NULL)) {
608 		fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
609 		return 1;
610 	}
611 	return 0;
612 }
613