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