xref: /OK3568_Linux_fs/u-boot/scripts/kconfig/conf.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3*4882a593Smuzhiyun  * Released under the terms of the GNU GPL v2.0.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <locale.h>
7*4882a593Smuzhiyun #include <ctype.h>
8*4882a593Smuzhiyun #include <limits.h>
9*4882a593Smuzhiyun #include <stdio.h>
10*4882a593Smuzhiyun #include <stdlib.h>
11*4882a593Smuzhiyun #include <string.h>
12*4882a593Smuzhiyun #include <time.h>
13*4882a593Smuzhiyun #include <unistd.h>
14*4882a593Smuzhiyun #include <getopt.h>
15*4882a593Smuzhiyun #include <sys/stat.h>
16*4882a593Smuzhiyun #include <sys/time.h>
17*4882a593Smuzhiyun #include <errno.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include "lkc.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun static void conf(struct menu *menu);
22*4882a593Smuzhiyun static void check_conf(struct menu *menu);
23*4882a593Smuzhiyun static void xfgets(char *str, int size, FILE *in);
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun enum input_mode {
26*4882a593Smuzhiyun 	oldaskconfig,
27*4882a593Smuzhiyun 	silentoldconfig,
28*4882a593Smuzhiyun 	oldconfig,
29*4882a593Smuzhiyun 	allnoconfig,
30*4882a593Smuzhiyun 	allyesconfig,
31*4882a593Smuzhiyun 	allmodconfig,
32*4882a593Smuzhiyun 	alldefconfig,
33*4882a593Smuzhiyun 	randconfig,
34*4882a593Smuzhiyun 	defconfig,
35*4882a593Smuzhiyun 	savedefconfig,
36*4882a593Smuzhiyun 	listnewconfig,
37*4882a593Smuzhiyun 	olddefconfig,
38*4882a593Smuzhiyun } input_mode = oldaskconfig;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static int indent = 1;
41*4882a593Smuzhiyun static int tty_stdio;
42*4882a593Smuzhiyun static int valid_stdin = 1;
43*4882a593Smuzhiyun static int sync_kconfig;
44*4882a593Smuzhiyun static int conf_cnt;
45*4882a593Smuzhiyun static char line[PATH_MAX];
46*4882a593Smuzhiyun static struct menu *rootEntry;
47*4882a593Smuzhiyun 
print_help(struct menu * menu)48*4882a593Smuzhiyun static void print_help(struct menu *menu)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	struct gstr help = str_new();
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	menu_get_ext_help(menu, &help);
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	printf("\n%s\n", str_get(&help));
55*4882a593Smuzhiyun 	str_free(&help);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
strip(char * str)58*4882a593Smuzhiyun static void strip(char *str)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	char *p = str;
61*4882a593Smuzhiyun 	int l;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	while ((isspace(*p)))
64*4882a593Smuzhiyun 		p++;
65*4882a593Smuzhiyun 	l = strlen(p);
66*4882a593Smuzhiyun 	if (p != str)
67*4882a593Smuzhiyun 		memmove(str, p, l + 1);
68*4882a593Smuzhiyun 	if (!l)
69*4882a593Smuzhiyun 		return;
70*4882a593Smuzhiyun 	p = str + l - 1;
71*4882a593Smuzhiyun 	while ((isspace(*p)))
72*4882a593Smuzhiyun 		*p-- = 0;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
check_stdin(void)75*4882a593Smuzhiyun static void check_stdin(void)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	if (!valid_stdin) {
78*4882a593Smuzhiyun 		printf(_("aborted!\n\n"));
79*4882a593Smuzhiyun 		printf(_("Console input/output is redirected. "));
80*4882a593Smuzhiyun 		printf(_("Run 'make oldconfig' to update configuration.\n\n"));
81*4882a593Smuzhiyun 		exit(1);
82*4882a593Smuzhiyun 	}
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
conf_askvalue(struct symbol * sym,const char * def)85*4882a593Smuzhiyun static int conf_askvalue(struct symbol *sym, const char *def)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun 	enum symbol_type type = sym_get_type(sym);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	if (!sym_has_value(sym))
90*4882a593Smuzhiyun 		printf(_("(NEW) "));
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	line[0] = '\n';
93*4882a593Smuzhiyun 	line[1] = 0;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	if (!sym_is_changable(sym)) {
96*4882a593Smuzhiyun 		printf("%s\n", def);
97*4882a593Smuzhiyun 		line[0] = '\n';
98*4882a593Smuzhiyun 		line[1] = 0;
99*4882a593Smuzhiyun 		return 0;
100*4882a593Smuzhiyun 	}
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	switch (input_mode) {
103*4882a593Smuzhiyun 	case oldconfig:
104*4882a593Smuzhiyun 	case silentoldconfig:
105*4882a593Smuzhiyun 		if (sym_has_value(sym)) {
106*4882a593Smuzhiyun 			printf("%s\n", def);
107*4882a593Smuzhiyun 			return 0;
108*4882a593Smuzhiyun 		}
109*4882a593Smuzhiyun 		check_stdin();
110*4882a593Smuzhiyun 		/* fall through */
111*4882a593Smuzhiyun 	case oldaskconfig:
112*4882a593Smuzhiyun 		fflush(stdout);
113*4882a593Smuzhiyun 		xfgets(line, sizeof(line), stdin);
114*4882a593Smuzhiyun 		if (!tty_stdio)
115*4882a593Smuzhiyun 			printf("\n");
116*4882a593Smuzhiyun 		return 1;
117*4882a593Smuzhiyun 	default:
118*4882a593Smuzhiyun 		break;
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	switch (type) {
122*4882a593Smuzhiyun 	case S_INT:
123*4882a593Smuzhiyun 	case S_HEX:
124*4882a593Smuzhiyun 	case S_STRING:
125*4882a593Smuzhiyun 		printf("%s\n", def);
126*4882a593Smuzhiyun 		return 1;
127*4882a593Smuzhiyun 	default:
128*4882a593Smuzhiyun 		;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 	printf("%s", line);
131*4882a593Smuzhiyun 	return 1;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun 
conf_string(struct menu * menu)134*4882a593Smuzhiyun static int conf_string(struct menu *menu)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun 	struct symbol *sym = menu->sym;
137*4882a593Smuzhiyun 	const char *def;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	while (1) {
140*4882a593Smuzhiyun 		printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
141*4882a593Smuzhiyun 		printf("(%s) ", sym->name);
142*4882a593Smuzhiyun 		def = sym_get_string_value(sym);
143*4882a593Smuzhiyun 		if (sym_get_string_value(sym))
144*4882a593Smuzhiyun 			printf("[%s] ", def);
145*4882a593Smuzhiyun 		if (!conf_askvalue(sym, def))
146*4882a593Smuzhiyun 			return 0;
147*4882a593Smuzhiyun 		switch (line[0]) {
148*4882a593Smuzhiyun 		case '\n':
149*4882a593Smuzhiyun 			break;
150*4882a593Smuzhiyun 		case '?':
151*4882a593Smuzhiyun 			/* print help */
152*4882a593Smuzhiyun 			if (line[1] == '\n') {
153*4882a593Smuzhiyun 				print_help(menu);
154*4882a593Smuzhiyun 				def = NULL;
155*4882a593Smuzhiyun 				break;
156*4882a593Smuzhiyun 			}
157*4882a593Smuzhiyun 			/* fall through */
158*4882a593Smuzhiyun 		default:
159*4882a593Smuzhiyun 			line[strlen(line)-1] = 0;
160*4882a593Smuzhiyun 			def = line;
161*4882a593Smuzhiyun 		}
162*4882a593Smuzhiyun 		if (def && sym_set_string_value(sym, def))
163*4882a593Smuzhiyun 			return 0;
164*4882a593Smuzhiyun 	}
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
conf_sym(struct menu * menu)167*4882a593Smuzhiyun static int conf_sym(struct menu *menu)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	struct symbol *sym = menu->sym;
170*4882a593Smuzhiyun 	tristate oldval, newval;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	while (1) {
173*4882a593Smuzhiyun 		printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
174*4882a593Smuzhiyun 		if (sym->name)
175*4882a593Smuzhiyun 			printf("(%s) ", sym->name);
176*4882a593Smuzhiyun 		putchar('[');
177*4882a593Smuzhiyun 		oldval = sym_get_tristate_value(sym);
178*4882a593Smuzhiyun 		switch (oldval) {
179*4882a593Smuzhiyun 		case no:
180*4882a593Smuzhiyun 			putchar('N');
181*4882a593Smuzhiyun 			break;
182*4882a593Smuzhiyun 		case mod:
183*4882a593Smuzhiyun 			putchar('M');
184*4882a593Smuzhiyun 			break;
185*4882a593Smuzhiyun 		case yes:
186*4882a593Smuzhiyun 			putchar('Y');
187*4882a593Smuzhiyun 			break;
188*4882a593Smuzhiyun 		}
189*4882a593Smuzhiyun 		if (oldval != no && sym_tristate_within_range(sym, no))
190*4882a593Smuzhiyun 			printf("/n");
191*4882a593Smuzhiyun 		if (oldval != mod && sym_tristate_within_range(sym, mod))
192*4882a593Smuzhiyun 			printf("/m");
193*4882a593Smuzhiyun 		if (oldval != yes && sym_tristate_within_range(sym, yes))
194*4882a593Smuzhiyun 			printf("/y");
195*4882a593Smuzhiyun 		if (menu_has_help(menu))
196*4882a593Smuzhiyun 			printf("/?");
197*4882a593Smuzhiyun 		printf("] ");
198*4882a593Smuzhiyun 		if (!conf_askvalue(sym, sym_get_string_value(sym)))
199*4882a593Smuzhiyun 			return 0;
200*4882a593Smuzhiyun 		strip(line);
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 		switch (line[0]) {
203*4882a593Smuzhiyun 		case 'n':
204*4882a593Smuzhiyun 		case 'N':
205*4882a593Smuzhiyun 			newval = no;
206*4882a593Smuzhiyun 			if (!line[1] || !strcmp(&line[1], "o"))
207*4882a593Smuzhiyun 				break;
208*4882a593Smuzhiyun 			continue;
209*4882a593Smuzhiyun 		case 'm':
210*4882a593Smuzhiyun 		case 'M':
211*4882a593Smuzhiyun 			newval = mod;
212*4882a593Smuzhiyun 			if (!line[1])
213*4882a593Smuzhiyun 				break;
214*4882a593Smuzhiyun 			continue;
215*4882a593Smuzhiyun 		case 'y':
216*4882a593Smuzhiyun 		case 'Y':
217*4882a593Smuzhiyun 			newval = yes;
218*4882a593Smuzhiyun 			if (!line[1] || !strcmp(&line[1], "es"))
219*4882a593Smuzhiyun 				break;
220*4882a593Smuzhiyun 			continue;
221*4882a593Smuzhiyun 		case 0:
222*4882a593Smuzhiyun 			newval = oldval;
223*4882a593Smuzhiyun 			break;
224*4882a593Smuzhiyun 		case '?':
225*4882a593Smuzhiyun 			goto help;
226*4882a593Smuzhiyun 		default:
227*4882a593Smuzhiyun 			continue;
228*4882a593Smuzhiyun 		}
229*4882a593Smuzhiyun 		if (sym_set_tristate_value(sym, newval))
230*4882a593Smuzhiyun 			return 0;
231*4882a593Smuzhiyun help:
232*4882a593Smuzhiyun 		print_help(menu);
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
conf_choice(struct menu * menu)236*4882a593Smuzhiyun static int conf_choice(struct menu *menu)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	struct symbol *sym, *def_sym;
239*4882a593Smuzhiyun 	struct menu *child;
240*4882a593Smuzhiyun 	bool is_new;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	sym = menu->sym;
243*4882a593Smuzhiyun 	is_new = !sym_has_value(sym);
244*4882a593Smuzhiyun 	if (sym_is_changable(sym)) {
245*4882a593Smuzhiyun 		conf_sym(menu);
246*4882a593Smuzhiyun 		sym_calc_value(sym);
247*4882a593Smuzhiyun 		switch (sym_get_tristate_value(sym)) {
248*4882a593Smuzhiyun 		case no:
249*4882a593Smuzhiyun 			return 1;
250*4882a593Smuzhiyun 		case mod:
251*4882a593Smuzhiyun 			return 0;
252*4882a593Smuzhiyun 		case yes:
253*4882a593Smuzhiyun 			break;
254*4882a593Smuzhiyun 		}
255*4882a593Smuzhiyun 	} else {
256*4882a593Smuzhiyun 		switch (sym_get_tristate_value(sym)) {
257*4882a593Smuzhiyun 		case no:
258*4882a593Smuzhiyun 			return 1;
259*4882a593Smuzhiyun 		case mod:
260*4882a593Smuzhiyun 			printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
261*4882a593Smuzhiyun 			return 0;
262*4882a593Smuzhiyun 		case yes:
263*4882a593Smuzhiyun 			break;
264*4882a593Smuzhiyun 		}
265*4882a593Smuzhiyun 	}
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	while (1) {
268*4882a593Smuzhiyun 		int cnt, def;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 		printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
271*4882a593Smuzhiyun 		def_sym = sym_get_choice_value(sym);
272*4882a593Smuzhiyun 		cnt = def = 0;
273*4882a593Smuzhiyun 		line[0] = 0;
274*4882a593Smuzhiyun 		for (child = menu->list; child; child = child->next) {
275*4882a593Smuzhiyun 			if (!menu_is_visible(child))
276*4882a593Smuzhiyun 				continue;
277*4882a593Smuzhiyun 			if (!child->sym) {
278*4882a593Smuzhiyun 				printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
279*4882a593Smuzhiyun 				continue;
280*4882a593Smuzhiyun 			}
281*4882a593Smuzhiyun 			cnt++;
282*4882a593Smuzhiyun 			if (child->sym == def_sym) {
283*4882a593Smuzhiyun 				def = cnt;
284*4882a593Smuzhiyun 				printf("%*c", indent, '>');
285*4882a593Smuzhiyun 			} else
286*4882a593Smuzhiyun 				printf("%*c", indent, ' ');
287*4882a593Smuzhiyun 			printf(" %d. %s", cnt, _(menu_get_prompt(child)));
288*4882a593Smuzhiyun 			if (child->sym->name)
289*4882a593Smuzhiyun 				printf(" (%s)", child->sym->name);
290*4882a593Smuzhiyun 			if (!sym_has_value(child->sym))
291*4882a593Smuzhiyun 				printf(_(" (NEW)"));
292*4882a593Smuzhiyun 			printf("\n");
293*4882a593Smuzhiyun 		}
294*4882a593Smuzhiyun 		printf(_("%*schoice"), indent - 1, "");
295*4882a593Smuzhiyun 		if (cnt == 1) {
296*4882a593Smuzhiyun 			printf("[1]: 1\n");
297*4882a593Smuzhiyun 			goto conf_childs;
298*4882a593Smuzhiyun 		}
299*4882a593Smuzhiyun 		printf("[1-%d", cnt);
300*4882a593Smuzhiyun 		if (menu_has_help(menu))
301*4882a593Smuzhiyun 			printf("?");
302*4882a593Smuzhiyun 		printf("]: ");
303*4882a593Smuzhiyun 		switch (input_mode) {
304*4882a593Smuzhiyun 		case oldconfig:
305*4882a593Smuzhiyun 		case silentoldconfig:
306*4882a593Smuzhiyun 			if (!is_new) {
307*4882a593Smuzhiyun 				cnt = def;
308*4882a593Smuzhiyun 				printf("%d\n", cnt);
309*4882a593Smuzhiyun 				break;
310*4882a593Smuzhiyun 			}
311*4882a593Smuzhiyun 			check_stdin();
312*4882a593Smuzhiyun 			/* fall through */
313*4882a593Smuzhiyun 		case oldaskconfig:
314*4882a593Smuzhiyun 			fflush(stdout);
315*4882a593Smuzhiyun 			xfgets(line, sizeof(line), stdin);
316*4882a593Smuzhiyun 			strip(line);
317*4882a593Smuzhiyun 			if (line[0] == '?') {
318*4882a593Smuzhiyun 				print_help(menu);
319*4882a593Smuzhiyun 				continue;
320*4882a593Smuzhiyun 			}
321*4882a593Smuzhiyun 			if (!line[0])
322*4882a593Smuzhiyun 				cnt = def;
323*4882a593Smuzhiyun 			else if (isdigit(line[0]))
324*4882a593Smuzhiyun 				cnt = atoi(line);
325*4882a593Smuzhiyun 			else
326*4882a593Smuzhiyun 				continue;
327*4882a593Smuzhiyun 			break;
328*4882a593Smuzhiyun 		default:
329*4882a593Smuzhiyun 			break;
330*4882a593Smuzhiyun 		}
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	conf_childs:
333*4882a593Smuzhiyun 		for (child = menu->list; child; child = child->next) {
334*4882a593Smuzhiyun 			if (!child->sym || !menu_is_visible(child))
335*4882a593Smuzhiyun 				continue;
336*4882a593Smuzhiyun 			if (!--cnt)
337*4882a593Smuzhiyun 				break;
338*4882a593Smuzhiyun 		}
339*4882a593Smuzhiyun 		if (!child)
340*4882a593Smuzhiyun 			continue;
341*4882a593Smuzhiyun 		if (line[0] && line[strlen(line) - 1] == '?') {
342*4882a593Smuzhiyun 			print_help(child);
343*4882a593Smuzhiyun 			continue;
344*4882a593Smuzhiyun 		}
345*4882a593Smuzhiyun 		sym_set_choice_value(sym, child->sym);
346*4882a593Smuzhiyun 		for (child = child->list; child; child = child->next) {
347*4882a593Smuzhiyun 			indent += 2;
348*4882a593Smuzhiyun 			conf(child);
349*4882a593Smuzhiyun 			indent -= 2;
350*4882a593Smuzhiyun 		}
351*4882a593Smuzhiyun 		return 1;
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
conf(struct menu * menu)355*4882a593Smuzhiyun static void conf(struct menu *menu)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun 	struct symbol *sym;
358*4882a593Smuzhiyun 	struct property *prop;
359*4882a593Smuzhiyun 	struct menu *child;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	if (!menu_is_visible(menu))
362*4882a593Smuzhiyun 		return;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	sym = menu->sym;
365*4882a593Smuzhiyun 	prop = menu->prompt;
366*4882a593Smuzhiyun 	if (prop) {
367*4882a593Smuzhiyun 		const char *prompt;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 		switch (prop->type) {
370*4882a593Smuzhiyun 		case P_MENU:
371*4882a593Smuzhiyun 			if ((input_mode == silentoldconfig ||
372*4882a593Smuzhiyun 			     input_mode == listnewconfig ||
373*4882a593Smuzhiyun 			     input_mode == olddefconfig) &&
374*4882a593Smuzhiyun 			    rootEntry != menu) {
375*4882a593Smuzhiyun 				check_conf(menu);
376*4882a593Smuzhiyun 				return;
377*4882a593Smuzhiyun 			}
378*4882a593Smuzhiyun 			/* fall through */
379*4882a593Smuzhiyun 		case P_COMMENT:
380*4882a593Smuzhiyun 			prompt = menu_get_prompt(menu);
381*4882a593Smuzhiyun 			if (prompt)
382*4882a593Smuzhiyun 				printf("%*c\n%*c %s\n%*c\n",
383*4882a593Smuzhiyun 					indent, '*',
384*4882a593Smuzhiyun 					indent, '*', _(prompt),
385*4882a593Smuzhiyun 					indent, '*');
386*4882a593Smuzhiyun 		default:
387*4882a593Smuzhiyun 			;
388*4882a593Smuzhiyun 		}
389*4882a593Smuzhiyun 	}
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	if (!sym)
392*4882a593Smuzhiyun 		goto conf_childs;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	if (sym_is_choice(sym)) {
395*4882a593Smuzhiyun 		conf_choice(menu);
396*4882a593Smuzhiyun 		if (sym->curr.tri != mod)
397*4882a593Smuzhiyun 			return;
398*4882a593Smuzhiyun 		goto conf_childs;
399*4882a593Smuzhiyun 	}
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	switch (sym->type) {
402*4882a593Smuzhiyun 	case S_INT:
403*4882a593Smuzhiyun 	case S_HEX:
404*4882a593Smuzhiyun 	case S_STRING:
405*4882a593Smuzhiyun 		conf_string(menu);
406*4882a593Smuzhiyun 		break;
407*4882a593Smuzhiyun 	default:
408*4882a593Smuzhiyun 		conf_sym(menu);
409*4882a593Smuzhiyun 		break;
410*4882a593Smuzhiyun 	}
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun conf_childs:
413*4882a593Smuzhiyun 	if (sym)
414*4882a593Smuzhiyun 		indent += 2;
415*4882a593Smuzhiyun 	for (child = menu->list; child; child = child->next)
416*4882a593Smuzhiyun 		conf(child);
417*4882a593Smuzhiyun 	if (sym)
418*4882a593Smuzhiyun 		indent -= 2;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun 
check_conf(struct menu * menu)421*4882a593Smuzhiyun static void check_conf(struct menu *menu)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun 	struct symbol *sym;
424*4882a593Smuzhiyun 	struct menu *child;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	if (!menu_is_visible(menu))
427*4882a593Smuzhiyun 		return;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	sym = menu->sym;
430*4882a593Smuzhiyun 	if (sym && !sym_has_value(sym)) {
431*4882a593Smuzhiyun 		if (sym_is_changable(sym) ||
432*4882a593Smuzhiyun 		    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
433*4882a593Smuzhiyun 			if (input_mode == listnewconfig) {
434*4882a593Smuzhiyun 				if (sym->name && !sym_is_choice_value(sym)) {
435*4882a593Smuzhiyun 					printf("%s%s\n", CONFIG_, sym->name);
436*4882a593Smuzhiyun 				}
437*4882a593Smuzhiyun 			} else if (input_mode != olddefconfig) {
438*4882a593Smuzhiyun 				if (!conf_cnt++)
439*4882a593Smuzhiyun 					printf(_("*\n* Restart config...\n*\n"));
440*4882a593Smuzhiyun 				rootEntry = menu_get_parent_menu(menu);
441*4882a593Smuzhiyun 				conf(rootEntry);
442*4882a593Smuzhiyun 			}
443*4882a593Smuzhiyun 		}
444*4882a593Smuzhiyun 	}
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	for (child = menu->list; child; child = child->next)
447*4882a593Smuzhiyun 		check_conf(child);
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun static struct option long_opts[] = {
451*4882a593Smuzhiyun 	{"oldaskconfig",    no_argument,       NULL, oldaskconfig},
452*4882a593Smuzhiyun 	{"oldconfig",       no_argument,       NULL, oldconfig},
453*4882a593Smuzhiyun 	{"silentoldconfig", no_argument,       NULL, silentoldconfig},
454*4882a593Smuzhiyun 	{"defconfig",       optional_argument, NULL, defconfig},
455*4882a593Smuzhiyun 	{"savedefconfig",   required_argument, NULL, savedefconfig},
456*4882a593Smuzhiyun 	{"allnoconfig",     no_argument,       NULL, allnoconfig},
457*4882a593Smuzhiyun 	{"allyesconfig",    no_argument,       NULL, allyesconfig},
458*4882a593Smuzhiyun 	{"allmodconfig",    no_argument,       NULL, allmodconfig},
459*4882a593Smuzhiyun 	{"alldefconfig",    no_argument,       NULL, alldefconfig},
460*4882a593Smuzhiyun 	{"randconfig",      no_argument,       NULL, randconfig},
461*4882a593Smuzhiyun 	{"listnewconfig",   no_argument,       NULL, listnewconfig},
462*4882a593Smuzhiyun 	{"olddefconfig",    no_argument,       NULL, olddefconfig},
463*4882a593Smuzhiyun 	/*
464*4882a593Smuzhiyun 	 * oldnoconfig is an alias of olddefconfig, because people already
465*4882a593Smuzhiyun 	 * are dependent on its behavior(sets new symbols to their default
466*4882a593Smuzhiyun 	 * value but not 'n') with the counter-intuitive name.
467*4882a593Smuzhiyun 	 */
468*4882a593Smuzhiyun 	{"oldnoconfig",     no_argument,       NULL, olddefconfig},
469*4882a593Smuzhiyun 	{NULL, 0, NULL, 0}
470*4882a593Smuzhiyun };
471*4882a593Smuzhiyun 
conf_usage(const char * progname)472*4882a593Smuzhiyun static void conf_usage(const char *progname)
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	printf("Usage: %s [-s] [option] <kconfig-file>\n", progname);
476*4882a593Smuzhiyun 	printf("[option] is _one_ of the following:\n");
477*4882a593Smuzhiyun 	printf("  --listnewconfig         List new options\n");
478*4882a593Smuzhiyun 	printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n");
479*4882a593Smuzhiyun 	printf("  --oldconfig             Update a configuration using a provided .config as base\n");
480*4882a593Smuzhiyun 	printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n");
481*4882a593Smuzhiyun 	printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n");
482*4882a593Smuzhiyun 	printf("  --oldnoconfig           An alias of olddefconfig\n");
483*4882a593Smuzhiyun 	printf("  --defconfig <file>      New config with default defined in <file>\n");
484*4882a593Smuzhiyun 	printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n");
485*4882a593Smuzhiyun 	printf("  --allnoconfig           New config where all options are answered with no\n");
486*4882a593Smuzhiyun 	printf("  --allyesconfig          New config where all options are answered with yes\n");
487*4882a593Smuzhiyun 	printf("  --allmodconfig          New config where all options are answered with mod\n");
488*4882a593Smuzhiyun 	printf("  --alldefconfig          New config with all symbols set to default\n");
489*4882a593Smuzhiyun 	printf("  --randconfig            New config with random answer to all options\n");
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun 
main(int ac,char ** av)492*4882a593Smuzhiyun int main(int ac, char **av)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun 	const char *progname = av[0];
495*4882a593Smuzhiyun 	int opt;
496*4882a593Smuzhiyun 	const char *name, *defconfig_file = NULL /* gcc uninit */;
497*4882a593Smuzhiyun 	struct stat tmpstat;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	setlocale(LC_ALL, "");
500*4882a593Smuzhiyun 	bindtextdomain(PACKAGE, LOCALEDIR);
501*4882a593Smuzhiyun 	textdomain(PACKAGE);
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	tty_stdio = isatty(0) && isatty(1) && isatty(2);
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
506*4882a593Smuzhiyun 		if (opt == 's') {
507*4882a593Smuzhiyun 			conf_set_message_callback(NULL);
508*4882a593Smuzhiyun 			continue;
509*4882a593Smuzhiyun 		}
510*4882a593Smuzhiyun 		input_mode = (enum input_mode)opt;
511*4882a593Smuzhiyun 		switch (opt) {
512*4882a593Smuzhiyun 		case silentoldconfig:
513*4882a593Smuzhiyun 			sync_kconfig = 1;
514*4882a593Smuzhiyun 			break;
515*4882a593Smuzhiyun 		case defconfig:
516*4882a593Smuzhiyun 		case savedefconfig:
517*4882a593Smuzhiyun 			defconfig_file = optarg;
518*4882a593Smuzhiyun 			break;
519*4882a593Smuzhiyun 		case randconfig:
520*4882a593Smuzhiyun 		{
521*4882a593Smuzhiyun 			struct timeval now;
522*4882a593Smuzhiyun 			unsigned int seed;
523*4882a593Smuzhiyun 			char *seed_env;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 			/*
526*4882a593Smuzhiyun 			 * Use microseconds derived seed,
527*4882a593Smuzhiyun 			 * compensate for systems where it may be zero
528*4882a593Smuzhiyun 			 */
529*4882a593Smuzhiyun 			gettimeofday(&now, NULL);
530*4882a593Smuzhiyun 			seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 			seed_env = getenv("KCONFIG_SEED");
533*4882a593Smuzhiyun 			if( seed_env && *seed_env ) {
534*4882a593Smuzhiyun 				char *endp;
535*4882a593Smuzhiyun 				int tmp = (int)strtol(seed_env, &endp, 0);
536*4882a593Smuzhiyun 				if (*endp == '\0') {
537*4882a593Smuzhiyun 					seed = tmp;
538*4882a593Smuzhiyun 				}
539*4882a593Smuzhiyun 			}
540*4882a593Smuzhiyun 			fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
541*4882a593Smuzhiyun 			srand(seed);
542*4882a593Smuzhiyun 			break;
543*4882a593Smuzhiyun 		}
544*4882a593Smuzhiyun 		case oldaskconfig:
545*4882a593Smuzhiyun 		case oldconfig:
546*4882a593Smuzhiyun 		case allnoconfig:
547*4882a593Smuzhiyun 		case allyesconfig:
548*4882a593Smuzhiyun 		case allmodconfig:
549*4882a593Smuzhiyun 		case alldefconfig:
550*4882a593Smuzhiyun 		case listnewconfig:
551*4882a593Smuzhiyun 		case olddefconfig:
552*4882a593Smuzhiyun 			break;
553*4882a593Smuzhiyun 		case '?':
554*4882a593Smuzhiyun 			conf_usage(progname);
555*4882a593Smuzhiyun 			exit(1);
556*4882a593Smuzhiyun 			break;
557*4882a593Smuzhiyun 		}
558*4882a593Smuzhiyun 	}
559*4882a593Smuzhiyun 	if (ac == optind) {
560*4882a593Smuzhiyun 		printf(_("%s: Kconfig file missing\n"), av[0]);
561*4882a593Smuzhiyun 		conf_usage(progname);
562*4882a593Smuzhiyun 		exit(1);
563*4882a593Smuzhiyun 	}
564*4882a593Smuzhiyun 	name = av[optind];
565*4882a593Smuzhiyun 	conf_parse(name);
566*4882a593Smuzhiyun 	//zconfdump(stdout);
567*4882a593Smuzhiyun 	if (sync_kconfig) {
568*4882a593Smuzhiyun 		name = conf_get_configname();
569*4882a593Smuzhiyun 		if (stat(name, &tmpstat)) {
570*4882a593Smuzhiyun 			fprintf(stderr, _("***\n"
571*4882a593Smuzhiyun 				"*** Configuration file \"%s\" not found!\n"
572*4882a593Smuzhiyun 				"***\n"
573*4882a593Smuzhiyun 				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
574*4882a593Smuzhiyun 				"*** \"make menuconfig\" or \"make xconfig\").\n"
575*4882a593Smuzhiyun 				"***\n"), name);
576*4882a593Smuzhiyun 			exit(1);
577*4882a593Smuzhiyun 		}
578*4882a593Smuzhiyun 	}
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	switch (input_mode) {
581*4882a593Smuzhiyun 	case defconfig:
582*4882a593Smuzhiyun 		if (!defconfig_file)
583*4882a593Smuzhiyun 			defconfig_file = conf_get_default_confname();
584*4882a593Smuzhiyun 		if (conf_read(defconfig_file)) {
585*4882a593Smuzhiyun 			printf(_("***\n"
586*4882a593Smuzhiyun 				"*** Can't find default configuration \"%s\"!\n"
587*4882a593Smuzhiyun 				"***\n"), defconfig_file);
588*4882a593Smuzhiyun 			exit(1);
589*4882a593Smuzhiyun 		}
590*4882a593Smuzhiyun 		break;
591*4882a593Smuzhiyun 	case savedefconfig:
592*4882a593Smuzhiyun 	case silentoldconfig:
593*4882a593Smuzhiyun 	case oldaskconfig:
594*4882a593Smuzhiyun 	case oldconfig:
595*4882a593Smuzhiyun 	case listnewconfig:
596*4882a593Smuzhiyun 	case olddefconfig:
597*4882a593Smuzhiyun 		conf_read(NULL);
598*4882a593Smuzhiyun 		break;
599*4882a593Smuzhiyun 	case allnoconfig:
600*4882a593Smuzhiyun 	case allyesconfig:
601*4882a593Smuzhiyun 	case allmodconfig:
602*4882a593Smuzhiyun 	case alldefconfig:
603*4882a593Smuzhiyun 	case randconfig:
604*4882a593Smuzhiyun 		name = getenv("KCONFIG_ALLCONFIG");
605*4882a593Smuzhiyun 		if (!name)
606*4882a593Smuzhiyun 			break;
607*4882a593Smuzhiyun 		if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
608*4882a593Smuzhiyun 			if (conf_read_simple(name, S_DEF_USER)) {
609*4882a593Smuzhiyun 				fprintf(stderr,
610*4882a593Smuzhiyun 					_("*** Can't read seed configuration \"%s\"!\n"),
611*4882a593Smuzhiyun 					name);
612*4882a593Smuzhiyun 				exit(1);
613*4882a593Smuzhiyun 			}
614*4882a593Smuzhiyun 			break;
615*4882a593Smuzhiyun 		}
616*4882a593Smuzhiyun 		switch (input_mode) {
617*4882a593Smuzhiyun 		case allnoconfig:	name = "allno.config"; break;
618*4882a593Smuzhiyun 		case allyesconfig:	name = "allyes.config"; break;
619*4882a593Smuzhiyun 		case allmodconfig:	name = "allmod.config"; break;
620*4882a593Smuzhiyun 		case alldefconfig:	name = "alldef.config"; break;
621*4882a593Smuzhiyun 		case randconfig:	name = "allrandom.config"; break;
622*4882a593Smuzhiyun 		default: break;
623*4882a593Smuzhiyun 		}
624*4882a593Smuzhiyun 		if (conf_read_simple(name, S_DEF_USER) &&
625*4882a593Smuzhiyun 		    conf_read_simple("all.config", S_DEF_USER)) {
626*4882a593Smuzhiyun 			fprintf(stderr,
627*4882a593Smuzhiyun 				_("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
628*4882a593Smuzhiyun 				name);
629*4882a593Smuzhiyun 			exit(1);
630*4882a593Smuzhiyun 		}
631*4882a593Smuzhiyun 		break;
632*4882a593Smuzhiyun 	default:
633*4882a593Smuzhiyun 		break;
634*4882a593Smuzhiyun 	}
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	if (sync_kconfig) {
637*4882a593Smuzhiyun 		if (conf_get_changed()) {
638*4882a593Smuzhiyun 			name = getenv("KCONFIG_NOSILENTUPDATE");
639*4882a593Smuzhiyun 			if (name && *name) {
640*4882a593Smuzhiyun 				fprintf(stderr,
641*4882a593Smuzhiyun 					_("\n*** The configuration requires explicit update.\n\n"));
642*4882a593Smuzhiyun 				return 1;
643*4882a593Smuzhiyun 			}
644*4882a593Smuzhiyun 		}
645*4882a593Smuzhiyun 		valid_stdin = tty_stdio;
646*4882a593Smuzhiyun 	}
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	switch (input_mode) {
649*4882a593Smuzhiyun 	case allnoconfig:
650*4882a593Smuzhiyun 		conf_set_all_new_symbols(def_no);
651*4882a593Smuzhiyun 		break;
652*4882a593Smuzhiyun 	case allyesconfig:
653*4882a593Smuzhiyun 		conf_set_all_new_symbols(def_yes);
654*4882a593Smuzhiyun 		break;
655*4882a593Smuzhiyun 	case allmodconfig:
656*4882a593Smuzhiyun 		conf_set_all_new_symbols(def_mod);
657*4882a593Smuzhiyun 		break;
658*4882a593Smuzhiyun 	case alldefconfig:
659*4882a593Smuzhiyun 		conf_set_all_new_symbols(def_default);
660*4882a593Smuzhiyun 		break;
661*4882a593Smuzhiyun 	case randconfig:
662*4882a593Smuzhiyun 		/* Really nothing to do in this loop */
663*4882a593Smuzhiyun 		while (conf_set_all_new_symbols(def_random)) ;
664*4882a593Smuzhiyun 		break;
665*4882a593Smuzhiyun 	case defconfig:
666*4882a593Smuzhiyun 		conf_set_all_new_symbols(def_default);
667*4882a593Smuzhiyun 		break;
668*4882a593Smuzhiyun 	case savedefconfig:
669*4882a593Smuzhiyun 		break;
670*4882a593Smuzhiyun 	case oldaskconfig:
671*4882a593Smuzhiyun 		rootEntry = &rootmenu;
672*4882a593Smuzhiyun 		conf(&rootmenu);
673*4882a593Smuzhiyun 		input_mode = silentoldconfig;
674*4882a593Smuzhiyun 		/* fall through */
675*4882a593Smuzhiyun 	case oldconfig:
676*4882a593Smuzhiyun 	case listnewconfig:
677*4882a593Smuzhiyun 	case olddefconfig:
678*4882a593Smuzhiyun 	case silentoldconfig:
679*4882a593Smuzhiyun 		/* Update until a loop caused no more changes */
680*4882a593Smuzhiyun 		do {
681*4882a593Smuzhiyun 			conf_cnt = 0;
682*4882a593Smuzhiyun 			check_conf(&rootmenu);
683*4882a593Smuzhiyun 		} while (conf_cnt &&
684*4882a593Smuzhiyun 			 (input_mode != listnewconfig &&
685*4882a593Smuzhiyun 			  input_mode != olddefconfig));
686*4882a593Smuzhiyun 		break;
687*4882a593Smuzhiyun 	}
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 	if (sync_kconfig) {
690*4882a593Smuzhiyun 		/* silentoldconfig is used during the build so we shall update autoconf.
691*4882a593Smuzhiyun 		 * All other commands are only used to generate a config.
692*4882a593Smuzhiyun 		 */
693*4882a593Smuzhiyun 		if (conf_get_changed() && conf_write(NULL)) {
694*4882a593Smuzhiyun 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
695*4882a593Smuzhiyun 			exit(1);
696*4882a593Smuzhiyun 		}
697*4882a593Smuzhiyun 		if (conf_write_autoconf()) {
698*4882a593Smuzhiyun 			fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
699*4882a593Smuzhiyun 			return 1;
700*4882a593Smuzhiyun 		}
701*4882a593Smuzhiyun 	} else if (input_mode == savedefconfig) {
702*4882a593Smuzhiyun 		if (conf_write_defconfig(defconfig_file)) {
703*4882a593Smuzhiyun 			fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
704*4882a593Smuzhiyun 				defconfig_file);
705*4882a593Smuzhiyun 			return 1;
706*4882a593Smuzhiyun 		}
707*4882a593Smuzhiyun 	} else if (input_mode != listnewconfig) {
708*4882a593Smuzhiyun 		if (conf_write(NULL)) {
709*4882a593Smuzhiyun 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
710*4882a593Smuzhiyun 			exit(1);
711*4882a593Smuzhiyun 		}
712*4882a593Smuzhiyun 	}
713*4882a593Smuzhiyun 	return 0;
714*4882a593Smuzhiyun }
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun /*
717*4882a593Smuzhiyun  * Helper function to facilitate fgets() by Jean Sacren.
718*4882a593Smuzhiyun  */
xfgets(char * str,int size,FILE * in)719*4882a593Smuzhiyun void xfgets(char *str, int size, FILE *in)
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun 	if (fgets(str, size, in) == NULL)
722*4882a593Smuzhiyun 		fprintf(stderr, "\nError in reading or end of file.\n");
723*4882a593Smuzhiyun }
724