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