xref: /openbmc/u-boot/scripts/kconfig/confdata.c (revision 0a9064fb47bb0a239c04b0b63edebfdd3a201fdc)
1*0a9064fbSMasahiro Yamada /*
2*0a9064fbSMasahiro Yamada  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3*0a9064fbSMasahiro Yamada  * Released under the terms of the GNU GPL v2.0.
4*0a9064fbSMasahiro Yamada  */
5*0a9064fbSMasahiro Yamada 
6*0a9064fbSMasahiro Yamada #include <sys/stat.h>
7*0a9064fbSMasahiro Yamada #include <ctype.h>
8*0a9064fbSMasahiro Yamada #include <errno.h>
9*0a9064fbSMasahiro Yamada #include <fcntl.h>
10*0a9064fbSMasahiro Yamada #include <stdarg.h>
11*0a9064fbSMasahiro Yamada #include <stdio.h>
12*0a9064fbSMasahiro Yamada #include <stdlib.h>
13*0a9064fbSMasahiro Yamada #include <string.h>
14*0a9064fbSMasahiro Yamada #include <time.h>
15*0a9064fbSMasahiro Yamada #include <unistd.h>
16*0a9064fbSMasahiro Yamada 
17*0a9064fbSMasahiro Yamada #include "lkc.h"
18*0a9064fbSMasahiro Yamada 
19*0a9064fbSMasahiro Yamada static void conf_warning(const char *fmt, ...)
20*0a9064fbSMasahiro Yamada 	__attribute__ ((format (printf, 1, 2)));
21*0a9064fbSMasahiro Yamada 
22*0a9064fbSMasahiro Yamada static void conf_message(const char *fmt, ...)
23*0a9064fbSMasahiro Yamada 	__attribute__ ((format (printf, 1, 2)));
24*0a9064fbSMasahiro Yamada 
25*0a9064fbSMasahiro Yamada static const char *conf_filename;
26*0a9064fbSMasahiro Yamada static int conf_lineno, conf_warnings, conf_unsaved;
27*0a9064fbSMasahiro Yamada 
28*0a9064fbSMasahiro Yamada const char conf_defname[] = "arch/$ARCH/defconfig";
29*0a9064fbSMasahiro Yamada 
30*0a9064fbSMasahiro Yamada static void conf_warning(const char *fmt, ...)
31*0a9064fbSMasahiro Yamada {
32*0a9064fbSMasahiro Yamada 	va_list ap;
33*0a9064fbSMasahiro Yamada 	va_start(ap, fmt);
34*0a9064fbSMasahiro Yamada 	fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
35*0a9064fbSMasahiro Yamada 	vfprintf(stderr, fmt, ap);
36*0a9064fbSMasahiro Yamada 	fprintf(stderr, "\n");
37*0a9064fbSMasahiro Yamada 	va_end(ap);
38*0a9064fbSMasahiro Yamada 	conf_warnings++;
39*0a9064fbSMasahiro Yamada }
40*0a9064fbSMasahiro Yamada 
41*0a9064fbSMasahiro Yamada static void conf_default_message_callback(const char *fmt, va_list ap)
42*0a9064fbSMasahiro Yamada {
43*0a9064fbSMasahiro Yamada 	printf("#\n# ");
44*0a9064fbSMasahiro Yamada 	vprintf(fmt, ap);
45*0a9064fbSMasahiro Yamada 	printf("\n#\n");
46*0a9064fbSMasahiro Yamada }
47*0a9064fbSMasahiro Yamada 
48*0a9064fbSMasahiro Yamada static void (*conf_message_callback) (const char *fmt, va_list ap) =
49*0a9064fbSMasahiro Yamada 	conf_default_message_callback;
50*0a9064fbSMasahiro Yamada void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
51*0a9064fbSMasahiro Yamada {
52*0a9064fbSMasahiro Yamada 	conf_message_callback = fn;
53*0a9064fbSMasahiro Yamada }
54*0a9064fbSMasahiro Yamada 
55*0a9064fbSMasahiro Yamada static void conf_message(const char *fmt, ...)
56*0a9064fbSMasahiro Yamada {
57*0a9064fbSMasahiro Yamada 	va_list ap;
58*0a9064fbSMasahiro Yamada 
59*0a9064fbSMasahiro Yamada 	va_start(ap, fmt);
60*0a9064fbSMasahiro Yamada 	if (conf_message_callback)
61*0a9064fbSMasahiro Yamada 		conf_message_callback(fmt, ap);
62*0a9064fbSMasahiro Yamada }
63*0a9064fbSMasahiro Yamada 
64*0a9064fbSMasahiro Yamada const char *conf_get_configname(void)
65*0a9064fbSMasahiro Yamada {
66*0a9064fbSMasahiro Yamada 	char *name = getenv("KCONFIG_CONFIG");
67*0a9064fbSMasahiro Yamada 
68*0a9064fbSMasahiro Yamada 	return name ? name : ".config";
69*0a9064fbSMasahiro Yamada }
70*0a9064fbSMasahiro Yamada 
71*0a9064fbSMasahiro Yamada const char *conf_get_autoconfig_name(void)
72*0a9064fbSMasahiro Yamada {
73*0a9064fbSMasahiro Yamada 	char *name = getenv("KCONFIG_AUTOCONFIG");
74*0a9064fbSMasahiro Yamada 
75*0a9064fbSMasahiro Yamada 	return name ? name : "include/config/auto.conf";
76*0a9064fbSMasahiro Yamada }
77*0a9064fbSMasahiro Yamada 
78*0a9064fbSMasahiro Yamada static char *conf_expand_value(const char *in)
79*0a9064fbSMasahiro Yamada {
80*0a9064fbSMasahiro Yamada 	struct symbol *sym;
81*0a9064fbSMasahiro Yamada 	const char *src;
82*0a9064fbSMasahiro Yamada 	static char res_value[SYMBOL_MAXLENGTH];
83*0a9064fbSMasahiro Yamada 	char *dst, name[SYMBOL_MAXLENGTH];
84*0a9064fbSMasahiro Yamada 
85*0a9064fbSMasahiro Yamada 	res_value[0] = 0;
86*0a9064fbSMasahiro Yamada 	dst = name;
87*0a9064fbSMasahiro Yamada 	while ((src = strchr(in, '$'))) {
88*0a9064fbSMasahiro Yamada 		strncat(res_value, in, src - in);
89*0a9064fbSMasahiro Yamada 		src++;
90*0a9064fbSMasahiro Yamada 		dst = name;
91*0a9064fbSMasahiro Yamada 		while (isalnum(*src) || *src == '_')
92*0a9064fbSMasahiro Yamada 			*dst++ = *src++;
93*0a9064fbSMasahiro Yamada 		*dst = 0;
94*0a9064fbSMasahiro Yamada 		sym = sym_lookup(name, 0);
95*0a9064fbSMasahiro Yamada 		sym_calc_value(sym);
96*0a9064fbSMasahiro Yamada 		strcat(res_value, sym_get_string_value(sym));
97*0a9064fbSMasahiro Yamada 		in = src;
98*0a9064fbSMasahiro Yamada 	}
99*0a9064fbSMasahiro Yamada 	strcat(res_value, in);
100*0a9064fbSMasahiro Yamada 
101*0a9064fbSMasahiro Yamada 	return res_value;
102*0a9064fbSMasahiro Yamada }
103*0a9064fbSMasahiro Yamada 
104*0a9064fbSMasahiro Yamada char *conf_get_default_confname(void)
105*0a9064fbSMasahiro Yamada {
106*0a9064fbSMasahiro Yamada 	struct stat buf;
107*0a9064fbSMasahiro Yamada 	static char fullname[PATH_MAX+1];
108*0a9064fbSMasahiro Yamada 	char *env, *name;
109*0a9064fbSMasahiro Yamada 
110*0a9064fbSMasahiro Yamada 	name = conf_expand_value(conf_defname);
111*0a9064fbSMasahiro Yamada 	env = getenv(SRCTREE);
112*0a9064fbSMasahiro Yamada 	if (env) {
113*0a9064fbSMasahiro Yamada 		sprintf(fullname, "%s/%s", env, name);
114*0a9064fbSMasahiro Yamada 		if (!stat(fullname, &buf))
115*0a9064fbSMasahiro Yamada 			return fullname;
116*0a9064fbSMasahiro Yamada 	}
117*0a9064fbSMasahiro Yamada 	return name;
118*0a9064fbSMasahiro Yamada }
119*0a9064fbSMasahiro Yamada 
120*0a9064fbSMasahiro Yamada static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
121*0a9064fbSMasahiro Yamada {
122*0a9064fbSMasahiro Yamada 	char *p2;
123*0a9064fbSMasahiro Yamada 
124*0a9064fbSMasahiro Yamada 	switch (sym->type) {
125*0a9064fbSMasahiro Yamada 	case S_TRISTATE:
126*0a9064fbSMasahiro Yamada 		if (p[0] == 'm') {
127*0a9064fbSMasahiro Yamada 			sym->def[def].tri = mod;
128*0a9064fbSMasahiro Yamada 			sym->flags |= def_flags;
129*0a9064fbSMasahiro Yamada 			break;
130*0a9064fbSMasahiro Yamada 		}
131*0a9064fbSMasahiro Yamada 		/* fall through */
132*0a9064fbSMasahiro Yamada 	case S_BOOLEAN:
133*0a9064fbSMasahiro Yamada 		if (p[0] == 'y') {
134*0a9064fbSMasahiro Yamada 			sym->def[def].tri = yes;
135*0a9064fbSMasahiro Yamada 			sym->flags |= def_flags;
136*0a9064fbSMasahiro Yamada 			break;
137*0a9064fbSMasahiro Yamada 		}
138*0a9064fbSMasahiro Yamada 		if (p[0] == 'n') {
139*0a9064fbSMasahiro Yamada 			sym->def[def].tri = no;
140*0a9064fbSMasahiro Yamada 			sym->flags |= def_flags;
141*0a9064fbSMasahiro Yamada 			break;
142*0a9064fbSMasahiro Yamada 		}
143*0a9064fbSMasahiro Yamada 		if (def != S_DEF_AUTO)
144*0a9064fbSMasahiro Yamada 			conf_warning("symbol value '%s' invalid for %s",
145*0a9064fbSMasahiro Yamada 				     p, sym->name);
146*0a9064fbSMasahiro Yamada 		return 1;
147*0a9064fbSMasahiro Yamada 	case S_OTHER:
148*0a9064fbSMasahiro Yamada 		if (*p != '"') {
149*0a9064fbSMasahiro Yamada 			for (p2 = p; *p2 && !isspace(*p2); p2++)
150*0a9064fbSMasahiro Yamada 				;
151*0a9064fbSMasahiro Yamada 			sym->type = S_STRING;
152*0a9064fbSMasahiro Yamada 			goto done;
153*0a9064fbSMasahiro Yamada 		}
154*0a9064fbSMasahiro Yamada 		/* fall through */
155*0a9064fbSMasahiro Yamada 	case S_STRING:
156*0a9064fbSMasahiro Yamada 		if (*p++ != '"')
157*0a9064fbSMasahiro Yamada 			break;
158*0a9064fbSMasahiro Yamada 		for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
159*0a9064fbSMasahiro Yamada 			if (*p2 == '"') {
160*0a9064fbSMasahiro Yamada 				*p2 = 0;
161*0a9064fbSMasahiro Yamada 				break;
162*0a9064fbSMasahiro Yamada 			}
163*0a9064fbSMasahiro Yamada 			memmove(p2, p2 + 1, strlen(p2));
164*0a9064fbSMasahiro Yamada 		}
165*0a9064fbSMasahiro Yamada 		if (!p2) {
166*0a9064fbSMasahiro Yamada 			if (def != S_DEF_AUTO)
167*0a9064fbSMasahiro Yamada 				conf_warning("invalid string found");
168*0a9064fbSMasahiro Yamada 			return 1;
169*0a9064fbSMasahiro Yamada 		}
170*0a9064fbSMasahiro Yamada 		/* fall through */
171*0a9064fbSMasahiro Yamada 	case S_INT:
172*0a9064fbSMasahiro Yamada 	case S_HEX:
173*0a9064fbSMasahiro Yamada 	done:
174*0a9064fbSMasahiro Yamada 		if (sym_string_valid(sym, p)) {
175*0a9064fbSMasahiro Yamada 			sym->def[def].val = strdup(p);
176*0a9064fbSMasahiro Yamada 			sym->flags |= def_flags;
177*0a9064fbSMasahiro Yamada 		} else {
178*0a9064fbSMasahiro Yamada 			if (def != S_DEF_AUTO)
179*0a9064fbSMasahiro Yamada 				conf_warning("symbol value '%s' invalid for %s",
180*0a9064fbSMasahiro Yamada 					     p, sym->name);
181*0a9064fbSMasahiro Yamada 			return 1;
182*0a9064fbSMasahiro Yamada 		}
183*0a9064fbSMasahiro Yamada 		break;
184*0a9064fbSMasahiro Yamada 	default:
185*0a9064fbSMasahiro Yamada 		;
186*0a9064fbSMasahiro Yamada 	}
187*0a9064fbSMasahiro Yamada 	return 0;
188*0a9064fbSMasahiro Yamada }
189*0a9064fbSMasahiro Yamada 
190*0a9064fbSMasahiro Yamada #define LINE_GROWTH 16
191*0a9064fbSMasahiro Yamada static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
192*0a9064fbSMasahiro Yamada {
193*0a9064fbSMasahiro Yamada 	char *nline;
194*0a9064fbSMasahiro Yamada 	size_t new_size = slen + 1;
195*0a9064fbSMasahiro Yamada 	if (new_size > *n) {
196*0a9064fbSMasahiro Yamada 		new_size += LINE_GROWTH - 1;
197*0a9064fbSMasahiro Yamada 		new_size *= 2;
198*0a9064fbSMasahiro Yamada 		nline = realloc(*lineptr, new_size);
199*0a9064fbSMasahiro Yamada 		if (!nline)
200*0a9064fbSMasahiro Yamada 			return -1;
201*0a9064fbSMasahiro Yamada 
202*0a9064fbSMasahiro Yamada 		*lineptr = nline;
203*0a9064fbSMasahiro Yamada 		*n = new_size;
204*0a9064fbSMasahiro Yamada 	}
205*0a9064fbSMasahiro Yamada 
206*0a9064fbSMasahiro Yamada 	(*lineptr)[slen] = c;
207*0a9064fbSMasahiro Yamada 
208*0a9064fbSMasahiro Yamada 	return 0;
209*0a9064fbSMasahiro Yamada }
210*0a9064fbSMasahiro Yamada 
211*0a9064fbSMasahiro Yamada static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
212*0a9064fbSMasahiro Yamada {
213*0a9064fbSMasahiro Yamada 	char *line = *lineptr;
214*0a9064fbSMasahiro Yamada 	size_t slen = 0;
215*0a9064fbSMasahiro Yamada 
216*0a9064fbSMasahiro Yamada 	for (;;) {
217*0a9064fbSMasahiro Yamada 		int c = getc(stream);
218*0a9064fbSMasahiro Yamada 
219*0a9064fbSMasahiro Yamada 		switch (c) {
220*0a9064fbSMasahiro Yamada 		case '\n':
221*0a9064fbSMasahiro Yamada 			if (add_byte(c, &line, slen, n) < 0)
222*0a9064fbSMasahiro Yamada 				goto e_out;
223*0a9064fbSMasahiro Yamada 			slen++;
224*0a9064fbSMasahiro Yamada 			/* fall through */
225*0a9064fbSMasahiro Yamada 		case EOF:
226*0a9064fbSMasahiro Yamada 			if (add_byte('\0', &line, slen, n) < 0)
227*0a9064fbSMasahiro Yamada 				goto e_out;
228*0a9064fbSMasahiro Yamada 			*lineptr = line;
229*0a9064fbSMasahiro Yamada 			if (slen == 0)
230*0a9064fbSMasahiro Yamada 				return -1;
231*0a9064fbSMasahiro Yamada 			return slen;
232*0a9064fbSMasahiro Yamada 		default:
233*0a9064fbSMasahiro Yamada 			if (add_byte(c, &line, slen, n) < 0)
234*0a9064fbSMasahiro Yamada 				goto e_out;
235*0a9064fbSMasahiro Yamada 			slen++;
236*0a9064fbSMasahiro Yamada 		}
237*0a9064fbSMasahiro Yamada 	}
238*0a9064fbSMasahiro Yamada 
239*0a9064fbSMasahiro Yamada e_out:
240*0a9064fbSMasahiro Yamada 	line[slen-1] = '\0';
241*0a9064fbSMasahiro Yamada 	*lineptr = line;
242*0a9064fbSMasahiro Yamada 	return -1;
243*0a9064fbSMasahiro Yamada }
244*0a9064fbSMasahiro Yamada 
245*0a9064fbSMasahiro Yamada int conf_read_simple(const char *name, int def)
246*0a9064fbSMasahiro Yamada {
247*0a9064fbSMasahiro Yamada 	FILE *in = NULL;
248*0a9064fbSMasahiro Yamada 	char   *line = NULL;
249*0a9064fbSMasahiro Yamada 	size_t  line_asize = 0;
250*0a9064fbSMasahiro Yamada 	char *p, *p2;
251*0a9064fbSMasahiro Yamada 	struct symbol *sym;
252*0a9064fbSMasahiro Yamada 	int i, def_flags;
253*0a9064fbSMasahiro Yamada 
254*0a9064fbSMasahiro Yamada 	if (name) {
255*0a9064fbSMasahiro Yamada 		in = zconf_fopen(name);
256*0a9064fbSMasahiro Yamada 	} else {
257*0a9064fbSMasahiro Yamada 		struct property *prop;
258*0a9064fbSMasahiro Yamada 
259*0a9064fbSMasahiro Yamada 		name = conf_get_configname();
260*0a9064fbSMasahiro Yamada 		in = zconf_fopen(name);
261*0a9064fbSMasahiro Yamada 		if (in)
262*0a9064fbSMasahiro Yamada 			goto load;
263*0a9064fbSMasahiro Yamada 		sym_add_change_count(1);
264*0a9064fbSMasahiro Yamada 		if (!sym_defconfig_list) {
265*0a9064fbSMasahiro Yamada 			if (modules_sym)
266*0a9064fbSMasahiro Yamada 				sym_calc_value(modules_sym);
267*0a9064fbSMasahiro Yamada 			return 1;
268*0a9064fbSMasahiro Yamada 		}
269*0a9064fbSMasahiro Yamada 
270*0a9064fbSMasahiro Yamada 		for_all_defaults(sym_defconfig_list, prop) {
271*0a9064fbSMasahiro Yamada 			if (expr_calc_value(prop->visible.expr) == no ||
272*0a9064fbSMasahiro Yamada 			    prop->expr->type != E_SYMBOL)
273*0a9064fbSMasahiro Yamada 				continue;
274*0a9064fbSMasahiro Yamada 			name = conf_expand_value(prop->expr->left.sym->name);
275*0a9064fbSMasahiro Yamada 			in = zconf_fopen(name);
276*0a9064fbSMasahiro Yamada 			if (in) {
277*0a9064fbSMasahiro Yamada 				conf_message(_("using defaults found in %s"),
278*0a9064fbSMasahiro Yamada 					 name);
279*0a9064fbSMasahiro Yamada 				goto load;
280*0a9064fbSMasahiro Yamada 			}
281*0a9064fbSMasahiro Yamada 		}
282*0a9064fbSMasahiro Yamada 	}
283*0a9064fbSMasahiro Yamada 	if (!in)
284*0a9064fbSMasahiro Yamada 		return 1;
285*0a9064fbSMasahiro Yamada 
286*0a9064fbSMasahiro Yamada load:
287*0a9064fbSMasahiro Yamada 	conf_filename = name;
288*0a9064fbSMasahiro Yamada 	conf_lineno = 0;
289*0a9064fbSMasahiro Yamada 	conf_warnings = 0;
290*0a9064fbSMasahiro Yamada 	conf_unsaved = 0;
291*0a9064fbSMasahiro Yamada 
292*0a9064fbSMasahiro Yamada 	def_flags = SYMBOL_DEF << def;
293*0a9064fbSMasahiro Yamada 	for_all_symbols(i, sym) {
294*0a9064fbSMasahiro Yamada 		sym->flags |= SYMBOL_CHANGED;
295*0a9064fbSMasahiro Yamada 		sym->flags &= ~(def_flags|SYMBOL_VALID);
296*0a9064fbSMasahiro Yamada 		if (sym_is_choice(sym))
297*0a9064fbSMasahiro Yamada 			sym->flags |= def_flags;
298*0a9064fbSMasahiro Yamada 		switch (sym->type) {
299*0a9064fbSMasahiro Yamada 		case S_INT:
300*0a9064fbSMasahiro Yamada 		case S_HEX:
301*0a9064fbSMasahiro Yamada 		case S_STRING:
302*0a9064fbSMasahiro Yamada 			if (sym->def[def].val)
303*0a9064fbSMasahiro Yamada 				free(sym->def[def].val);
304*0a9064fbSMasahiro Yamada 			/* fall through */
305*0a9064fbSMasahiro Yamada 		default:
306*0a9064fbSMasahiro Yamada 			sym->def[def].val = NULL;
307*0a9064fbSMasahiro Yamada 			sym->def[def].tri = no;
308*0a9064fbSMasahiro Yamada 		}
309*0a9064fbSMasahiro Yamada 	}
310*0a9064fbSMasahiro Yamada 
311*0a9064fbSMasahiro Yamada 	while (compat_getline(&line, &line_asize, in) != -1) {
312*0a9064fbSMasahiro Yamada 		conf_lineno++;
313*0a9064fbSMasahiro Yamada 		sym = NULL;
314*0a9064fbSMasahiro Yamada 		if (line[0] == '#') {
315*0a9064fbSMasahiro Yamada 			if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
316*0a9064fbSMasahiro Yamada 				continue;
317*0a9064fbSMasahiro Yamada 			p = strchr(line + 2 + strlen(CONFIG_), ' ');
318*0a9064fbSMasahiro Yamada 			if (!p)
319*0a9064fbSMasahiro Yamada 				continue;
320*0a9064fbSMasahiro Yamada 			*p++ = 0;
321*0a9064fbSMasahiro Yamada 			if (strncmp(p, "is not set", 10))
322*0a9064fbSMasahiro Yamada 				continue;
323*0a9064fbSMasahiro Yamada 			if (def == S_DEF_USER) {
324*0a9064fbSMasahiro Yamada 				sym = sym_find(line + 2 + strlen(CONFIG_));
325*0a9064fbSMasahiro Yamada 				if (!sym) {
326*0a9064fbSMasahiro Yamada 					sym_add_change_count(1);
327*0a9064fbSMasahiro Yamada 					goto setsym;
328*0a9064fbSMasahiro Yamada 				}
329*0a9064fbSMasahiro Yamada 			} else {
330*0a9064fbSMasahiro Yamada 				sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
331*0a9064fbSMasahiro Yamada 				if (sym->type == S_UNKNOWN)
332*0a9064fbSMasahiro Yamada 					sym->type = S_BOOLEAN;
333*0a9064fbSMasahiro Yamada 			}
334*0a9064fbSMasahiro Yamada 			if (sym->flags & def_flags) {
335*0a9064fbSMasahiro Yamada 				conf_warning("override: reassigning to symbol %s", sym->name);
336*0a9064fbSMasahiro Yamada 			}
337*0a9064fbSMasahiro Yamada 			switch (sym->type) {
338*0a9064fbSMasahiro Yamada 			case S_BOOLEAN:
339*0a9064fbSMasahiro Yamada 			case S_TRISTATE:
340*0a9064fbSMasahiro Yamada 				sym->def[def].tri = no;
341*0a9064fbSMasahiro Yamada 				sym->flags |= def_flags;
342*0a9064fbSMasahiro Yamada 				break;
343*0a9064fbSMasahiro Yamada 			default:
344*0a9064fbSMasahiro Yamada 				;
345*0a9064fbSMasahiro Yamada 			}
346*0a9064fbSMasahiro Yamada 		} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
347*0a9064fbSMasahiro Yamada 			p = strchr(line + strlen(CONFIG_), '=');
348*0a9064fbSMasahiro Yamada 			if (!p)
349*0a9064fbSMasahiro Yamada 				continue;
350*0a9064fbSMasahiro Yamada 			*p++ = 0;
351*0a9064fbSMasahiro Yamada 			p2 = strchr(p, '\n');
352*0a9064fbSMasahiro Yamada 			if (p2) {
353*0a9064fbSMasahiro Yamada 				*p2-- = 0;
354*0a9064fbSMasahiro Yamada 				if (*p2 == '\r')
355*0a9064fbSMasahiro Yamada 					*p2 = 0;
356*0a9064fbSMasahiro Yamada 			}
357*0a9064fbSMasahiro Yamada 			if (def == S_DEF_USER) {
358*0a9064fbSMasahiro Yamada 				sym = sym_find(line + strlen(CONFIG_));
359*0a9064fbSMasahiro Yamada 				if (!sym) {
360*0a9064fbSMasahiro Yamada 					sym_add_change_count(1);
361*0a9064fbSMasahiro Yamada 					goto setsym;
362*0a9064fbSMasahiro Yamada 				}
363*0a9064fbSMasahiro Yamada 			} else {
364*0a9064fbSMasahiro Yamada 				sym = sym_lookup(line + strlen(CONFIG_), 0);
365*0a9064fbSMasahiro Yamada 				if (sym->type == S_UNKNOWN)
366*0a9064fbSMasahiro Yamada 					sym->type = S_OTHER;
367*0a9064fbSMasahiro Yamada 			}
368*0a9064fbSMasahiro Yamada 			if (sym->flags & def_flags) {
369*0a9064fbSMasahiro Yamada 				conf_warning("override: reassigning to symbol %s", sym->name);
370*0a9064fbSMasahiro Yamada 			}
371*0a9064fbSMasahiro Yamada 			if (conf_set_sym_val(sym, def, def_flags, p))
372*0a9064fbSMasahiro Yamada 				continue;
373*0a9064fbSMasahiro Yamada 		} else {
374*0a9064fbSMasahiro Yamada 			if (line[0] != '\r' && line[0] != '\n')
375*0a9064fbSMasahiro Yamada 				conf_warning("unexpected data");
376*0a9064fbSMasahiro Yamada 			continue;
377*0a9064fbSMasahiro Yamada 		}
378*0a9064fbSMasahiro Yamada setsym:
379*0a9064fbSMasahiro Yamada 		if (sym && sym_is_choice_value(sym)) {
380*0a9064fbSMasahiro Yamada 			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
381*0a9064fbSMasahiro Yamada 			switch (sym->def[def].tri) {
382*0a9064fbSMasahiro Yamada 			case no:
383*0a9064fbSMasahiro Yamada 				break;
384*0a9064fbSMasahiro Yamada 			case mod:
385*0a9064fbSMasahiro Yamada 				if (cs->def[def].tri == yes) {
386*0a9064fbSMasahiro Yamada 					conf_warning("%s creates inconsistent choice state", sym->name);
387*0a9064fbSMasahiro Yamada 					cs->flags &= ~def_flags;
388*0a9064fbSMasahiro Yamada 				}
389*0a9064fbSMasahiro Yamada 				break;
390*0a9064fbSMasahiro Yamada 			case yes:
391*0a9064fbSMasahiro Yamada 				if (cs->def[def].tri != no)
392*0a9064fbSMasahiro Yamada 					conf_warning("override: %s changes choice state", sym->name);
393*0a9064fbSMasahiro Yamada 				cs->def[def].val = sym;
394*0a9064fbSMasahiro Yamada 				break;
395*0a9064fbSMasahiro Yamada 			}
396*0a9064fbSMasahiro Yamada 			cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
397*0a9064fbSMasahiro Yamada 		}
398*0a9064fbSMasahiro Yamada 	}
399*0a9064fbSMasahiro Yamada 	free(line);
400*0a9064fbSMasahiro Yamada 	fclose(in);
401*0a9064fbSMasahiro Yamada 
402*0a9064fbSMasahiro Yamada 	if (modules_sym)
403*0a9064fbSMasahiro Yamada 		sym_calc_value(modules_sym);
404*0a9064fbSMasahiro Yamada 	return 0;
405*0a9064fbSMasahiro Yamada }
406*0a9064fbSMasahiro Yamada 
407*0a9064fbSMasahiro Yamada int conf_read(const char *name)
408*0a9064fbSMasahiro Yamada {
409*0a9064fbSMasahiro Yamada 	struct symbol *sym;
410*0a9064fbSMasahiro Yamada 	int i;
411*0a9064fbSMasahiro Yamada 
412*0a9064fbSMasahiro Yamada 	sym_set_change_count(0);
413*0a9064fbSMasahiro Yamada 
414*0a9064fbSMasahiro Yamada 	if (conf_read_simple(name, S_DEF_USER))
415*0a9064fbSMasahiro Yamada 		return 1;
416*0a9064fbSMasahiro Yamada 
417*0a9064fbSMasahiro Yamada 	for_all_symbols(i, sym) {
418*0a9064fbSMasahiro Yamada 		sym_calc_value(sym);
419*0a9064fbSMasahiro Yamada 		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
420*0a9064fbSMasahiro Yamada 			continue;
421*0a9064fbSMasahiro Yamada 		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
422*0a9064fbSMasahiro Yamada 			/* check that calculated value agrees with saved value */
423*0a9064fbSMasahiro Yamada 			switch (sym->type) {
424*0a9064fbSMasahiro Yamada 			case S_BOOLEAN:
425*0a9064fbSMasahiro Yamada 			case S_TRISTATE:
426*0a9064fbSMasahiro Yamada 				if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
427*0a9064fbSMasahiro Yamada 					break;
428*0a9064fbSMasahiro Yamada 				if (!sym_is_choice(sym))
429*0a9064fbSMasahiro Yamada 					continue;
430*0a9064fbSMasahiro Yamada 				/* fall through */
431*0a9064fbSMasahiro Yamada 			default:
432*0a9064fbSMasahiro Yamada 				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
433*0a9064fbSMasahiro Yamada 					continue;
434*0a9064fbSMasahiro Yamada 				break;
435*0a9064fbSMasahiro Yamada 			}
436*0a9064fbSMasahiro Yamada 		} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
437*0a9064fbSMasahiro Yamada 			/* no previous value and not saved */
438*0a9064fbSMasahiro Yamada 			continue;
439*0a9064fbSMasahiro Yamada 		conf_unsaved++;
440*0a9064fbSMasahiro Yamada 		/* maybe print value in verbose mode... */
441*0a9064fbSMasahiro Yamada 	}
442*0a9064fbSMasahiro Yamada 
443*0a9064fbSMasahiro Yamada 	for_all_symbols(i, sym) {
444*0a9064fbSMasahiro Yamada 		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
445*0a9064fbSMasahiro Yamada 			/* Reset values of generates values, so they'll appear
446*0a9064fbSMasahiro Yamada 			 * as new, if they should become visible, but that
447*0a9064fbSMasahiro Yamada 			 * doesn't quite work if the Kconfig and the saved
448*0a9064fbSMasahiro Yamada 			 * configuration disagree.
449*0a9064fbSMasahiro Yamada 			 */
450*0a9064fbSMasahiro Yamada 			if (sym->visible == no && !conf_unsaved)
451*0a9064fbSMasahiro Yamada 				sym->flags &= ~SYMBOL_DEF_USER;
452*0a9064fbSMasahiro Yamada 			switch (sym->type) {
453*0a9064fbSMasahiro Yamada 			case S_STRING:
454*0a9064fbSMasahiro Yamada 			case S_INT:
455*0a9064fbSMasahiro Yamada 			case S_HEX:
456*0a9064fbSMasahiro Yamada 				/* Reset a string value if it's out of range */
457*0a9064fbSMasahiro Yamada 				if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
458*0a9064fbSMasahiro Yamada 					break;
459*0a9064fbSMasahiro Yamada 				sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
460*0a9064fbSMasahiro Yamada 				conf_unsaved++;
461*0a9064fbSMasahiro Yamada 				break;
462*0a9064fbSMasahiro Yamada 			default:
463*0a9064fbSMasahiro Yamada 				break;
464*0a9064fbSMasahiro Yamada 			}
465*0a9064fbSMasahiro Yamada 		}
466*0a9064fbSMasahiro Yamada 	}
467*0a9064fbSMasahiro Yamada 
468*0a9064fbSMasahiro Yamada 	sym_add_change_count(conf_warnings || conf_unsaved);
469*0a9064fbSMasahiro Yamada 
470*0a9064fbSMasahiro Yamada 	return 0;
471*0a9064fbSMasahiro Yamada }
472*0a9064fbSMasahiro Yamada 
473*0a9064fbSMasahiro Yamada /*
474*0a9064fbSMasahiro Yamada  * Kconfig configuration printer
475*0a9064fbSMasahiro Yamada  *
476*0a9064fbSMasahiro Yamada  * This printer is used when generating the resulting configuration after
477*0a9064fbSMasahiro Yamada  * kconfig invocation and `defconfig' files. Unset symbol might be omitted by
478*0a9064fbSMasahiro Yamada  * passing a non-NULL argument to the printer.
479*0a9064fbSMasahiro Yamada  *
480*0a9064fbSMasahiro Yamada  */
481*0a9064fbSMasahiro Yamada static void
482*0a9064fbSMasahiro Yamada kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
483*0a9064fbSMasahiro Yamada {
484*0a9064fbSMasahiro Yamada 
485*0a9064fbSMasahiro Yamada 	switch (sym->type) {
486*0a9064fbSMasahiro Yamada 	case S_BOOLEAN:
487*0a9064fbSMasahiro Yamada 	case S_TRISTATE:
488*0a9064fbSMasahiro Yamada 		if (*value == 'n') {
489*0a9064fbSMasahiro Yamada 			bool skip_unset = (arg != NULL);
490*0a9064fbSMasahiro Yamada 
491*0a9064fbSMasahiro Yamada 			if (!skip_unset)
492*0a9064fbSMasahiro Yamada 				fprintf(fp, "# %s%s is not set\n",
493*0a9064fbSMasahiro Yamada 				    CONFIG_, sym->name);
494*0a9064fbSMasahiro Yamada 			return;
495*0a9064fbSMasahiro Yamada 		}
496*0a9064fbSMasahiro Yamada 		break;
497*0a9064fbSMasahiro Yamada 	default:
498*0a9064fbSMasahiro Yamada 		break;
499*0a9064fbSMasahiro Yamada 	}
500*0a9064fbSMasahiro Yamada 
501*0a9064fbSMasahiro Yamada 	fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
502*0a9064fbSMasahiro Yamada }
503*0a9064fbSMasahiro Yamada 
504*0a9064fbSMasahiro Yamada static void
505*0a9064fbSMasahiro Yamada kconfig_print_comment(FILE *fp, const char *value, void *arg)
506*0a9064fbSMasahiro Yamada {
507*0a9064fbSMasahiro Yamada 	const char *p = value;
508*0a9064fbSMasahiro Yamada 	size_t l;
509*0a9064fbSMasahiro Yamada 
510*0a9064fbSMasahiro Yamada 	for (;;) {
511*0a9064fbSMasahiro Yamada 		l = strcspn(p, "\n");
512*0a9064fbSMasahiro Yamada 		fprintf(fp, "#");
513*0a9064fbSMasahiro Yamada 		if (l) {
514*0a9064fbSMasahiro Yamada 			fprintf(fp, " ");
515*0a9064fbSMasahiro Yamada 			xfwrite(p, l, 1, fp);
516*0a9064fbSMasahiro Yamada 			p += l;
517*0a9064fbSMasahiro Yamada 		}
518*0a9064fbSMasahiro Yamada 		fprintf(fp, "\n");
519*0a9064fbSMasahiro Yamada 		if (*p++ == '\0')
520*0a9064fbSMasahiro Yamada 			break;
521*0a9064fbSMasahiro Yamada 	}
522*0a9064fbSMasahiro Yamada }
523*0a9064fbSMasahiro Yamada 
524*0a9064fbSMasahiro Yamada static struct conf_printer kconfig_printer_cb =
525*0a9064fbSMasahiro Yamada {
526*0a9064fbSMasahiro Yamada 	.print_symbol = kconfig_print_symbol,
527*0a9064fbSMasahiro Yamada 	.print_comment = kconfig_print_comment,
528*0a9064fbSMasahiro Yamada };
529*0a9064fbSMasahiro Yamada 
530*0a9064fbSMasahiro Yamada /*
531*0a9064fbSMasahiro Yamada  * Header printer
532*0a9064fbSMasahiro Yamada  *
533*0a9064fbSMasahiro Yamada  * This printer is used when generating the `include/generated/autoconf.h' file.
534*0a9064fbSMasahiro Yamada  */
535*0a9064fbSMasahiro Yamada static void
536*0a9064fbSMasahiro Yamada header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
537*0a9064fbSMasahiro Yamada {
538*0a9064fbSMasahiro Yamada 
539*0a9064fbSMasahiro Yamada 	switch (sym->type) {
540*0a9064fbSMasahiro Yamada 	case S_BOOLEAN:
541*0a9064fbSMasahiro Yamada 	case S_TRISTATE: {
542*0a9064fbSMasahiro Yamada 		const char *suffix = "";
543*0a9064fbSMasahiro Yamada 
544*0a9064fbSMasahiro Yamada 		switch (*value) {
545*0a9064fbSMasahiro Yamada 		case 'n':
546*0a9064fbSMasahiro Yamada 			break;
547*0a9064fbSMasahiro Yamada 		case 'm':
548*0a9064fbSMasahiro Yamada 			suffix = "_MODULE";
549*0a9064fbSMasahiro Yamada 			/* fall through */
550*0a9064fbSMasahiro Yamada 		default:
551*0a9064fbSMasahiro Yamada 			fprintf(fp, "#define %s%s%s 1\n",
552*0a9064fbSMasahiro Yamada 			    CONFIG_, sym->name, suffix);
553*0a9064fbSMasahiro Yamada 		}
554*0a9064fbSMasahiro Yamada 		break;
555*0a9064fbSMasahiro Yamada 	}
556*0a9064fbSMasahiro Yamada 	case S_HEX: {
557*0a9064fbSMasahiro Yamada 		const char *prefix = "";
558*0a9064fbSMasahiro Yamada 
559*0a9064fbSMasahiro Yamada 		if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
560*0a9064fbSMasahiro Yamada 			prefix = "0x";
561*0a9064fbSMasahiro Yamada 		fprintf(fp, "#define %s%s %s%s\n",
562*0a9064fbSMasahiro Yamada 		    CONFIG_, sym->name, prefix, value);
563*0a9064fbSMasahiro Yamada 		break;
564*0a9064fbSMasahiro Yamada 	}
565*0a9064fbSMasahiro Yamada 	case S_STRING:
566*0a9064fbSMasahiro Yamada 	case S_INT:
567*0a9064fbSMasahiro Yamada 		fprintf(fp, "#define %s%s %s\n",
568*0a9064fbSMasahiro Yamada 		    CONFIG_, sym->name, value);
569*0a9064fbSMasahiro Yamada 		break;
570*0a9064fbSMasahiro Yamada 	default:
571*0a9064fbSMasahiro Yamada 		break;
572*0a9064fbSMasahiro Yamada 	}
573*0a9064fbSMasahiro Yamada 
574*0a9064fbSMasahiro Yamada }
575*0a9064fbSMasahiro Yamada 
576*0a9064fbSMasahiro Yamada static void
577*0a9064fbSMasahiro Yamada header_print_comment(FILE *fp, const char *value, void *arg)
578*0a9064fbSMasahiro Yamada {
579*0a9064fbSMasahiro Yamada 	const char *p = value;
580*0a9064fbSMasahiro Yamada 	size_t l;
581*0a9064fbSMasahiro Yamada 
582*0a9064fbSMasahiro Yamada 	fprintf(fp, "/*\n");
583*0a9064fbSMasahiro Yamada 	for (;;) {
584*0a9064fbSMasahiro Yamada 		l = strcspn(p, "\n");
585*0a9064fbSMasahiro Yamada 		fprintf(fp, " *");
586*0a9064fbSMasahiro Yamada 		if (l) {
587*0a9064fbSMasahiro Yamada 			fprintf(fp, " ");
588*0a9064fbSMasahiro Yamada 			xfwrite(p, l, 1, fp);
589*0a9064fbSMasahiro Yamada 			p += l;
590*0a9064fbSMasahiro Yamada 		}
591*0a9064fbSMasahiro Yamada 		fprintf(fp, "\n");
592*0a9064fbSMasahiro Yamada 		if (*p++ == '\0')
593*0a9064fbSMasahiro Yamada 			break;
594*0a9064fbSMasahiro Yamada 	}
595*0a9064fbSMasahiro Yamada 	fprintf(fp, " */\n");
596*0a9064fbSMasahiro Yamada }
597*0a9064fbSMasahiro Yamada 
598*0a9064fbSMasahiro Yamada static struct conf_printer header_printer_cb =
599*0a9064fbSMasahiro Yamada {
600*0a9064fbSMasahiro Yamada 	.print_symbol = header_print_symbol,
601*0a9064fbSMasahiro Yamada 	.print_comment = header_print_comment,
602*0a9064fbSMasahiro Yamada };
603*0a9064fbSMasahiro Yamada 
604*0a9064fbSMasahiro Yamada /*
605*0a9064fbSMasahiro Yamada  * Tristate printer
606*0a9064fbSMasahiro Yamada  *
607*0a9064fbSMasahiro Yamada  * This printer is used when generating the `include/config/tristate.conf' file.
608*0a9064fbSMasahiro Yamada  */
609*0a9064fbSMasahiro Yamada static void
610*0a9064fbSMasahiro Yamada tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
611*0a9064fbSMasahiro Yamada {
612*0a9064fbSMasahiro Yamada 
613*0a9064fbSMasahiro Yamada 	if (sym->type == S_TRISTATE && *value != 'n')
614*0a9064fbSMasahiro Yamada 		fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
615*0a9064fbSMasahiro Yamada }
616*0a9064fbSMasahiro Yamada 
617*0a9064fbSMasahiro Yamada static struct conf_printer tristate_printer_cb =
618*0a9064fbSMasahiro Yamada {
619*0a9064fbSMasahiro Yamada 	.print_symbol = tristate_print_symbol,
620*0a9064fbSMasahiro Yamada 	.print_comment = kconfig_print_comment,
621*0a9064fbSMasahiro Yamada };
622*0a9064fbSMasahiro Yamada 
623*0a9064fbSMasahiro Yamada static void conf_write_symbol(FILE *fp, struct symbol *sym,
624*0a9064fbSMasahiro Yamada 			      struct conf_printer *printer, void *printer_arg)
625*0a9064fbSMasahiro Yamada {
626*0a9064fbSMasahiro Yamada 	const char *str;
627*0a9064fbSMasahiro Yamada 
628*0a9064fbSMasahiro Yamada 	switch (sym->type) {
629*0a9064fbSMasahiro Yamada 	case S_OTHER:
630*0a9064fbSMasahiro Yamada 	case S_UNKNOWN:
631*0a9064fbSMasahiro Yamada 		break;
632*0a9064fbSMasahiro Yamada 	case S_STRING:
633*0a9064fbSMasahiro Yamada 		str = sym_get_string_value(sym);
634*0a9064fbSMasahiro Yamada 		str = sym_escape_string_value(str);
635*0a9064fbSMasahiro Yamada 		printer->print_symbol(fp, sym, str, printer_arg);
636*0a9064fbSMasahiro Yamada 		free((void *)str);
637*0a9064fbSMasahiro Yamada 		break;
638*0a9064fbSMasahiro Yamada 	default:
639*0a9064fbSMasahiro Yamada 		str = sym_get_string_value(sym);
640*0a9064fbSMasahiro Yamada 		printer->print_symbol(fp, sym, str, printer_arg);
641*0a9064fbSMasahiro Yamada 	}
642*0a9064fbSMasahiro Yamada }
643*0a9064fbSMasahiro Yamada 
644*0a9064fbSMasahiro Yamada static void
645*0a9064fbSMasahiro Yamada conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
646*0a9064fbSMasahiro Yamada {
647*0a9064fbSMasahiro Yamada 	char buf[256];
648*0a9064fbSMasahiro Yamada 
649*0a9064fbSMasahiro Yamada 	snprintf(buf, sizeof(buf),
650*0a9064fbSMasahiro Yamada 	    "\n"
651*0a9064fbSMasahiro Yamada 	    "Automatically generated file; DO NOT EDIT.\n"
652*0a9064fbSMasahiro Yamada 	    "%s\n",
653*0a9064fbSMasahiro Yamada 	    rootmenu.prompt->text);
654*0a9064fbSMasahiro Yamada 
655*0a9064fbSMasahiro Yamada 	printer->print_comment(fp, buf, printer_arg);
656*0a9064fbSMasahiro Yamada }
657*0a9064fbSMasahiro Yamada 
658*0a9064fbSMasahiro Yamada /*
659*0a9064fbSMasahiro Yamada  * Write out a minimal config.
660*0a9064fbSMasahiro Yamada  * All values that has default values are skipped as this is redundant.
661*0a9064fbSMasahiro Yamada  */
662*0a9064fbSMasahiro Yamada int conf_write_defconfig(const char *filename)
663*0a9064fbSMasahiro Yamada {
664*0a9064fbSMasahiro Yamada 	struct symbol *sym;
665*0a9064fbSMasahiro Yamada 	struct menu *menu;
666*0a9064fbSMasahiro Yamada 	FILE *out;
667*0a9064fbSMasahiro Yamada 
668*0a9064fbSMasahiro Yamada 	out = fopen(filename, "w");
669*0a9064fbSMasahiro Yamada 	if (!out)
670*0a9064fbSMasahiro Yamada 		return 1;
671*0a9064fbSMasahiro Yamada 
672*0a9064fbSMasahiro Yamada 	sym_clear_all_valid();
673*0a9064fbSMasahiro Yamada 
674*0a9064fbSMasahiro Yamada 	/* Traverse all menus to find all relevant symbols */
675*0a9064fbSMasahiro Yamada 	menu = rootmenu.list;
676*0a9064fbSMasahiro Yamada 
677*0a9064fbSMasahiro Yamada 	while (menu != NULL)
678*0a9064fbSMasahiro Yamada 	{
679*0a9064fbSMasahiro Yamada 		sym = menu->sym;
680*0a9064fbSMasahiro Yamada 		if (sym == NULL) {
681*0a9064fbSMasahiro Yamada 			if (!menu_is_visible(menu))
682*0a9064fbSMasahiro Yamada 				goto next_menu;
683*0a9064fbSMasahiro Yamada 		} else if (!sym_is_choice(sym)) {
684*0a9064fbSMasahiro Yamada 			sym_calc_value(sym);
685*0a9064fbSMasahiro Yamada 			if (!(sym->flags & SYMBOL_WRITE))
686*0a9064fbSMasahiro Yamada 				goto next_menu;
687*0a9064fbSMasahiro Yamada 			sym->flags &= ~SYMBOL_WRITE;
688*0a9064fbSMasahiro Yamada 			/* If we cannot change the symbol - skip */
689*0a9064fbSMasahiro Yamada 			if (!sym_is_changable(sym))
690*0a9064fbSMasahiro Yamada 				goto next_menu;
691*0a9064fbSMasahiro Yamada 			/* If symbol equals to default value - skip */
692*0a9064fbSMasahiro Yamada 			if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
693*0a9064fbSMasahiro Yamada 				goto next_menu;
694*0a9064fbSMasahiro Yamada 
695*0a9064fbSMasahiro Yamada 			/*
696*0a9064fbSMasahiro Yamada 			 * If symbol is a choice value and equals to the
697*0a9064fbSMasahiro Yamada 			 * default for a choice - skip.
698*0a9064fbSMasahiro Yamada 			 * But only if value is bool and equal to "y" and
699*0a9064fbSMasahiro Yamada 			 * choice is not "optional".
700*0a9064fbSMasahiro Yamada 			 * (If choice is "optional" then all values can be "n")
701*0a9064fbSMasahiro Yamada 			 */
702*0a9064fbSMasahiro Yamada 			if (sym_is_choice_value(sym)) {
703*0a9064fbSMasahiro Yamada 				struct symbol *cs;
704*0a9064fbSMasahiro Yamada 				struct symbol *ds;
705*0a9064fbSMasahiro Yamada 
706*0a9064fbSMasahiro Yamada 				cs = prop_get_symbol(sym_get_choice_prop(sym));
707*0a9064fbSMasahiro Yamada 				ds = sym_choice_default(cs);
708*0a9064fbSMasahiro Yamada 				if (!sym_is_optional(cs) && sym == ds) {
709*0a9064fbSMasahiro Yamada 					if ((sym->type == S_BOOLEAN) &&
710*0a9064fbSMasahiro Yamada 					    sym_get_tristate_value(sym) == yes)
711*0a9064fbSMasahiro Yamada 						goto next_menu;
712*0a9064fbSMasahiro Yamada 				}
713*0a9064fbSMasahiro Yamada 			}
714*0a9064fbSMasahiro Yamada 			conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
715*0a9064fbSMasahiro Yamada 		}
716*0a9064fbSMasahiro Yamada next_menu:
717*0a9064fbSMasahiro Yamada 		if (menu->list != NULL) {
718*0a9064fbSMasahiro Yamada 			menu = menu->list;
719*0a9064fbSMasahiro Yamada 		}
720*0a9064fbSMasahiro Yamada 		else if (menu->next != NULL) {
721*0a9064fbSMasahiro Yamada 			menu = menu->next;
722*0a9064fbSMasahiro Yamada 		} else {
723*0a9064fbSMasahiro Yamada 			while ((menu = menu->parent)) {
724*0a9064fbSMasahiro Yamada 				if (menu->next != NULL) {
725*0a9064fbSMasahiro Yamada 					menu = menu->next;
726*0a9064fbSMasahiro Yamada 					break;
727*0a9064fbSMasahiro Yamada 				}
728*0a9064fbSMasahiro Yamada 			}
729*0a9064fbSMasahiro Yamada 		}
730*0a9064fbSMasahiro Yamada 	}
731*0a9064fbSMasahiro Yamada 	fclose(out);
732*0a9064fbSMasahiro Yamada 	return 0;
733*0a9064fbSMasahiro Yamada }
734*0a9064fbSMasahiro Yamada 
735*0a9064fbSMasahiro Yamada int conf_write(const char *name)
736*0a9064fbSMasahiro Yamada {
737*0a9064fbSMasahiro Yamada 	FILE *out;
738*0a9064fbSMasahiro Yamada 	struct symbol *sym;
739*0a9064fbSMasahiro Yamada 	struct menu *menu;
740*0a9064fbSMasahiro Yamada 	const char *basename;
741*0a9064fbSMasahiro Yamada 	const char *str;
742*0a9064fbSMasahiro Yamada 	char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
743*0a9064fbSMasahiro Yamada 	char *env;
744*0a9064fbSMasahiro Yamada 
745*0a9064fbSMasahiro Yamada 	dirname[0] = 0;
746*0a9064fbSMasahiro Yamada 	if (name && name[0]) {
747*0a9064fbSMasahiro Yamada 		struct stat st;
748*0a9064fbSMasahiro Yamada 		char *slash;
749*0a9064fbSMasahiro Yamada 
750*0a9064fbSMasahiro Yamada 		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
751*0a9064fbSMasahiro Yamada 			strcpy(dirname, name);
752*0a9064fbSMasahiro Yamada 			strcat(dirname, "/");
753*0a9064fbSMasahiro Yamada 			basename = conf_get_configname();
754*0a9064fbSMasahiro Yamada 		} else if ((slash = strrchr(name, '/'))) {
755*0a9064fbSMasahiro Yamada 			int size = slash - name + 1;
756*0a9064fbSMasahiro Yamada 			memcpy(dirname, name, size);
757*0a9064fbSMasahiro Yamada 			dirname[size] = 0;
758*0a9064fbSMasahiro Yamada 			if (slash[1])
759*0a9064fbSMasahiro Yamada 				basename = slash + 1;
760*0a9064fbSMasahiro Yamada 			else
761*0a9064fbSMasahiro Yamada 				basename = conf_get_configname();
762*0a9064fbSMasahiro Yamada 		} else
763*0a9064fbSMasahiro Yamada 			basename = name;
764*0a9064fbSMasahiro Yamada 	} else
765*0a9064fbSMasahiro Yamada 		basename = conf_get_configname();
766*0a9064fbSMasahiro Yamada 
767*0a9064fbSMasahiro Yamada 	sprintf(newname, "%s%s", dirname, basename);
768*0a9064fbSMasahiro Yamada 	env = getenv("KCONFIG_OVERWRITECONFIG");
769*0a9064fbSMasahiro Yamada 	if (!env || !*env) {
770*0a9064fbSMasahiro Yamada 		sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
771*0a9064fbSMasahiro Yamada 		out = fopen(tmpname, "w");
772*0a9064fbSMasahiro Yamada 	} else {
773*0a9064fbSMasahiro Yamada 		*tmpname = 0;
774*0a9064fbSMasahiro Yamada 		out = fopen(newname, "w");
775*0a9064fbSMasahiro Yamada 	}
776*0a9064fbSMasahiro Yamada 	if (!out)
777*0a9064fbSMasahiro Yamada 		return 1;
778*0a9064fbSMasahiro Yamada 
779*0a9064fbSMasahiro Yamada 	conf_write_heading(out, &kconfig_printer_cb, NULL);
780*0a9064fbSMasahiro Yamada 
781*0a9064fbSMasahiro Yamada 	if (!conf_get_changed())
782*0a9064fbSMasahiro Yamada 		sym_clear_all_valid();
783*0a9064fbSMasahiro Yamada 
784*0a9064fbSMasahiro Yamada 	menu = rootmenu.list;
785*0a9064fbSMasahiro Yamada 	while (menu) {
786*0a9064fbSMasahiro Yamada 		sym = menu->sym;
787*0a9064fbSMasahiro Yamada 		if (!sym) {
788*0a9064fbSMasahiro Yamada 			if (!menu_is_visible(menu))
789*0a9064fbSMasahiro Yamada 				goto next;
790*0a9064fbSMasahiro Yamada 			str = menu_get_prompt(menu);
791*0a9064fbSMasahiro Yamada 			fprintf(out, "\n"
792*0a9064fbSMasahiro Yamada 				     "#\n"
793*0a9064fbSMasahiro Yamada 				     "# %s\n"
794*0a9064fbSMasahiro Yamada 				     "#\n", str);
795*0a9064fbSMasahiro Yamada 		} else if (!(sym->flags & SYMBOL_CHOICE)) {
796*0a9064fbSMasahiro Yamada 			sym_calc_value(sym);
797*0a9064fbSMasahiro Yamada 			if (!(sym->flags & SYMBOL_WRITE))
798*0a9064fbSMasahiro Yamada 				goto next;
799*0a9064fbSMasahiro Yamada 			sym->flags &= ~SYMBOL_WRITE;
800*0a9064fbSMasahiro Yamada 
801*0a9064fbSMasahiro Yamada 			conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
802*0a9064fbSMasahiro Yamada 		}
803*0a9064fbSMasahiro Yamada 
804*0a9064fbSMasahiro Yamada next:
805*0a9064fbSMasahiro Yamada 		if (menu->list) {
806*0a9064fbSMasahiro Yamada 			menu = menu->list;
807*0a9064fbSMasahiro Yamada 			continue;
808*0a9064fbSMasahiro Yamada 		}
809*0a9064fbSMasahiro Yamada 		if (menu->next)
810*0a9064fbSMasahiro Yamada 			menu = menu->next;
811*0a9064fbSMasahiro Yamada 		else while ((menu = menu->parent)) {
812*0a9064fbSMasahiro Yamada 			if (menu->next) {
813*0a9064fbSMasahiro Yamada 				menu = menu->next;
814*0a9064fbSMasahiro Yamada 				break;
815*0a9064fbSMasahiro Yamada 			}
816*0a9064fbSMasahiro Yamada 		}
817*0a9064fbSMasahiro Yamada 	}
818*0a9064fbSMasahiro Yamada 	fclose(out);
819*0a9064fbSMasahiro Yamada 
820*0a9064fbSMasahiro Yamada 	if (*tmpname) {
821*0a9064fbSMasahiro Yamada 		strcat(dirname, basename);
822*0a9064fbSMasahiro Yamada 		strcat(dirname, ".old");
823*0a9064fbSMasahiro Yamada 		rename(newname, dirname);
824*0a9064fbSMasahiro Yamada 		if (rename(tmpname, newname))
825*0a9064fbSMasahiro Yamada 			return 1;
826*0a9064fbSMasahiro Yamada 	}
827*0a9064fbSMasahiro Yamada 
828*0a9064fbSMasahiro Yamada 	conf_message(_("configuration written to %s"), newname);
829*0a9064fbSMasahiro Yamada 
830*0a9064fbSMasahiro Yamada 	sym_set_change_count(0);
831*0a9064fbSMasahiro Yamada 
832*0a9064fbSMasahiro Yamada 	return 0;
833*0a9064fbSMasahiro Yamada }
834*0a9064fbSMasahiro Yamada 
835*0a9064fbSMasahiro Yamada static int conf_split_config(void)
836*0a9064fbSMasahiro Yamada {
837*0a9064fbSMasahiro Yamada 	const char *name;
838*0a9064fbSMasahiro Yamada 	char path[PATH_MAX+1];
839*0a9064fbSMasahiro Yamada 	char *s, *d, c;
840*0a9064fbSMasahiro Yamada 	struct symbol *sym;
841*0a9064fbSMasahiro Yamada 	struct stat sb;
842*0a9064fbSMasahiro Yamada 	int res, i, fd;
843*0a9064fbSMasahiro Yamada 
844*0a9064fbSMasahiro Yamada 	name = conf_get_autoconfig_name();
845*0a9064fbSMasahiro Yamada 	conf_read_simple(name, S_DEF_AUTO);
846*0a9064fbSMasahiro Yamada 
847*0a9064fbSMasahiro Yamada 	if (chdir("include/config"))
848*0a9064fbSMasahiro Yamada 		return 1;
849*0a9064fbSMasahiro Yamada 
850*0a9064fbSMasahiro Yamada 	res = 0;
851*0a9064fbSMasahiro Yamada 	for_all_symbols(i, sym) {
852*0a9064fbSMasahiro Yamada 		sym_calc_value(sym);
853*0a9064fbSMasahiro Yamada 		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
854*0a9064fbSMasahiro Yamada 			continue;
855*0a9064fbSMasahiro Yamada 		if (sym->flags & SYMBOL_WRITE) {
856*0a9064fbSMasahiro Yamada 			if (sym->flags & SYMBOL_DEF_AUTO) {
857*0a9064fbSMasahiro Yamada 				/*
858*0a9064fbSMasahiro Yamada 				 * symbol has old and new value,
859*0a9064fbSMasahiro Yamada 				 * so compare them...
860*0a9064fbSMasahiro Yamada 				 */
861*0a9064fbSMasahiro Yamada 				switch (sym->type) {
862*0a9064fbSMasahiro Yamada 				case S_BOOLEAN:
863*0a9064fbSMasahiro Yamada 				case S_TRISTATE:
864*0a9064fbSMasahiro Yamada 					if (sym_get_tristate_value(sym) ==
865*0a9064fbSMasahiro Yamada 					    sym->def[S_DEF_AUTO].tri)
866*0a9064fbSMasahiro Yamada 						continue;
867*0a9064fbSMasahiro Yamada 					break;
868*0a9064fbSMasahiro Yamada 				case S_STRING:
869*0a9064fbSMasahiro Yamada 				case S_HEX:
870*0a9064fbSMasahiro Yamada 				case S_INT:
871*0a9064fbSMasahiro Yamada 					if (!strcmp(sym_get_string_value(sym),
872*0a9064fbSMasahiro Yamada 						    sym->def[S_DEF_AUTO].val))
873*0a9064fbSMasahiro Yamada 						continue;
874*0a9064fbSMasahiro Yamada 					break;
875*0a9064fbSMasahiro Yamada 				default:
876*0a9064fbSMasahiro Yamada 					break;
877*0a9064fbSMasahiro Yamada 				}
878*0a9064fbSMasahiro Yamada 			} else {
879*0a9064fbSMasahiro Yamada 				/*
880*0a9064fbSMasahiro Yamada 				 * If there is no old value, only 'no' (unset)
881*0a9064fbSMasahiro Yamada 				 * is allowed as new value.
882*0a9064fbSMasahiro Yamada 				 */
883*0a9064fbSMasahiro Yamada 				switch (sym->type) {
884*0a9064fbSMasahiro Yamada 				case S_BOOLEAN:
885*0a9064fbSMasahiro Yamada 				case S_TRISTATE:
886*0a9064fbSMasahiro Yamada 					if (sym_get_tristate_value(sym) == no)
887*0a9064fbSMasahiro Yamada 						continue;
888*0a9064fbSMasahiro Yamada 					break;
889*0a9064fbSMasahiro Yamada 				default:
890*0a9064fbSMasahiro Yamada 					break;
891*0a9064fbSMasahiro Yamada 				}
892*0a9064fbSMasahiro Yamada 			}
893*0a9064fbSMasahiro Yamada 		} else if (!(sym->flags & SYMBOL_DEF_AUTO))
894*0a9064fbSMasahiro Yamada 			/* There is neither an old nor a new value. */
895*0a9064fbSMasahiro Yamada 			continue;
896*0a9064fbSMasahiro Yamada 		/* else
897*0a9064fbSMasahiro Yamada 		 *	There is an old value, but no new value ('no' (unset)
898*0a9064fbSMasahiro Yamada 		 *	isn't saved in auto.conf, so the old value is always
899*0a9064fbSMasahiro Yamada 		 *	different from 'no').
900*0a9064fbSMasahiro Yamada 		 */
901*0a9064fbSMasahiro Yamada 
902*0a9064fbSMasahiro Yamada 		/* Replace all '_' and append ".h" */
903*0a9064fbSMasahiro Yamada 		s = sym->name;
904*0a9064fbSMasahiro Yamada 		d = path;
905*0a9064fbSMasahiro Yamada 		while ((c = *s++)) {
906*0a9064fbSMasahiro Yamada 			c = tolower(c);
907*0a9064fbSMasahiro Yamada 			*d++ = (c == '_') ? '/' : c;
908*0a9064fbSMasahiro Yamada 		}
909*0a9064fbSMasahiro Yamada 		strcpy(d, ".h");
910*0a9064fbSMasahiro Yamada 
911*0a9064fbSMasahiro Yamada 		/* Assume directory path already exists. */
912*0a9064fbSMasahiro Yamada 		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
913*0a9064fbSMasahiro Yamada 		if (fd == -1) {
914*0a9064fbSMasahiro Yamada 			if (errno != ENOENT) {
915*0a9064fbSMasahiro Yamada 				res = 1;
916*0a9064fbSMasahiro Yamada 				break;
917*0a9064fbSMasahiro Yamada 			}
918*0a9064fbSMasahiro Yamada 			/*
919*0a9064fbSMasahiro Yamada 			 * Create directory components,
920*0a9064fbSMasahiro Yamada 			 * unless they exist already.
921*0a9064fbSMasahiro Yamada 			 */
922*0a9064fbSMasahiro Yamada 			d = path;
923*0a9064fbSMasahiro Yamada 			while ((d = strchr(d, '/'))) {
924*0a9064fbSMasahiro Yamada 				*d = 0;
925*0a9064fbSMasahiro Yamada 				if (stat(path, &sb) && mkdir(path, 0755)) {
926*0a9064fbSMasahiro Yamada 					res = 1;
927*0a9064fbSMasahiro Yamada 					goto out;
928*0a9064fbSMasahiro Yamada 				}
929*0a9064fbSMasahiro Yamada 				*d++ = '/';
930*0a9064fbSMasahiro Yamada 			}
931*0a9064fbSMasahiro Yamada 			/* Try it again. */
932*0a9064fbSMasahiro Yamada 			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
933*0a9064fbSMasahiro Yamada 			if (fd == -1) {
934*0a9064fbSMasahiro Yamada 				res = 1;
935*0a9064fbSMasahiro Yamada 				break;
936*0a9064fbSMasahiro Yamada 			}
937*0a9064fbSMasahiro Yamada 		}
938*0a9064fbSMasahiro Yamada 		close(fd);
939*0a9064fbSMasahiro Yamada 	}
940*0a9064fbSMasahiro Yamada out:
941*0a9064fbSMasahiro Yamada 	if (chdir("../.."))
942*0a9064fbSMasahiro Yamada 		return 1;
943*0a9064fbSMasahiro Yamada 
944*0a9064fbSMasahiro Yamada 	return res;
945*0a9064fbSMasahiro Yamada }
946*0a9064fbSMasahiro Yamada 
947*0a9064fbSMasahiro Yamada int conf_write_autoconf(void)
948*0a9064fbSMasahiro Yamada {
949*0a9064fbSMasahiro Yamada 	struct symbol *sym;
950*0a9064fbSMasahiro Yamada 	const char *name;
951*0a9064fbSMasahiro Yamada 	FILE *out, *tristate, *out_h;
952*0a9064fbSMasahiro Yamada 	int i;
953*0a9064fbSMasahiro Yamada 
954*0a9064fbSMasahiro Yamada 	sym_clear_all_valid();
955*0a9064fbSMasahiro Yamada 
956*0a9064fbSMasahiro Yamada 	file_write_dep("include/config/auto.conf.cmd");
957*0a9064fbSMasahiro Yamada 
958*0a9064fbSMasahiro Yamada 	if (conf_split_config())
959*0a9064fbSMasahiro Yamada 		return 1;
960*0a9064fbSMasahiro Yamada 
961*0a9064fbSMasahiro Yamada 	out = fopen(".tmpconfig", "w");
962*0a9064fbSMasahiro Yamada 	if (!out)
963*0a9064fbSMasahiro Yamada 		return 1;
964*0a9064fbSMasahiro Yamada 
965*0a9064fbSMasahiro Yamada 	tristate = fopen(".tmpconfig_tristate", "w");
966*0a9064fbSMasahiro Yamada 	if (!tristate) {
967*0a9064fbSMasahiro Yamada 		fclose(out);
968*0a9064fbSMasahiro Yamada 		return 1;
969*0a9064fbSMasahiro Yamada 	}
970*0a9064fbSMasahiro Yamada 
971*0a9064fbSMasahiro Yamada 	out_h = fopen(".tmpconfig.h", "w");
972*0a9064fbSMasahiro Yamada 	if (!out_h) {
973*0a9064fbSMasahiro Yamada 		fclose(out);
974*0a9064fbSMasahiro Yamada 		fclose(tristate);
975*0a9064fbSMasahiro Yamada 		return 1;
976*0a9064fbSMasahiro Yamada 	}
977*0a9064fbSMasahiro Yamada 
978*0a9064fbSMasahiro Yamada 	conf_write_heading(out, &kconfig_printer_cb, NULL);
979*0a9064fbSMasahiro Yamada 
980*0a9064fbSMasahiro Yamada 	conf_write_heading(tristate, &tristate_printer_cb, NULL);
981*0a9064fbSMasahiro Yamada 
982*0a9064fbSMasahiro Yamada 	conf_write_heading(out_h, &header_printer_cb, NULL);
983*0a9064fbSMasahiro Yamada 
984*0a9064fbSMasahiro Yamada 	for_all_symbols(i, sym) {
985*0a9064fbSMasahiro Yamada 		sym_calc_value(sym);
986*0a9064fbSMasahiro Yamada 		if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
987*0a9064fbSMasahiro Yamada 			continue;
988*0a9064fbSMasahiro Yamada 
989*0a9064fbSMasahiro Yamada 		/* write symbol to auto.conf, tristate and header files */
990*0a9064fbSMasahiro Yamada 		conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
991*0a9064fbSMasahiro Yamada 
992*0a9064fbSMasahiro Yamada 		conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
993*0a9064fbSMasahiro Yamada 
994*0a9064fbSMasahiro Yamada 		conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
995*0a9064fbSMasahiro Yamada 	}
996*0a9064fbSMasahiro Yamada 	fclose(out);
997*0a9064fbSMasahiro Yamada 	fclose(tristate);
998*0a9064fbSMasahiro Yamada 	fclose(out_h);
999*0a9064fbSMasahiro Yamada 
1000*0a9064fbSMasahiro Yamada 	name = getenv("KCONFIG_AUTOHEADER");
1001*0a9064fbSMasahiro Yamada 	if (!name)
1002*0a9064fbSMasahiro Yamada 		name = "include/generated/autoconf.h";
1003*0a9064fbSMasahiro Yamada 	if (rename(".tmpconfig.h", name))
1004*0a9064fbSMasahiro Yamada 		return 1;
1005*0a9064fbSMasahiro Yamada 	name = getenv("KCONFIG_TRISTATE");
1006*0a9064fbSMasahiro Yamada 	if (!name)
1007*0a9064fbSMasahiro Yamada 		name = "include/config/tristate.conf";
1008*0a9064fbSMasahiro Yamada 	if (rename(".tmpconfig_tristate", name))
1009*0a9064fbSMasahiro Yamada 		return 1;
1010*0a9064fbSMasahiro Yamada 	name = conf_get_autoconfig_name();
1011*0a9064fbSMasahiro Yamada 	/*
1012*0a9064fbSMasahiro Yamada 	 * This must be the last step, kbuild has a dependency on auto.conf
1013*0a9064fbSMasahiro Yamada 	 * and this marks the successful completion of the previous steps.
1014*0a9064fbSMasahiro Yamada 	 */
1015*0a9064fbSMasahiro Yamada 	if (rename(".tmpconfig", name))
1016*0a9064fbSMasahiro Yamada 		return 1;
1017*0a9064fbSMasahiro Yamada 
1018*0a9064fbSMasahiro Yamada 	return 0;
1019*0a9064fbSMasahiro Yamada }
1020*0a9064fbSMasahiro Yamada 
1021*0a9064fbSMasahiro Yamada static int sym_change_count;
1022*0a9064fbSMasahiro Yamada static void (*conf_changed_callback)(void);
1023*0a9064fbSMasahiro Yamada 
1024*0a9064fbSMasahiro Yamada void sym_set_change_count(int count)
1025*0a9064fbSMasahiro Yamada {
1026*0a9064fbSMasahiro Yamada 	int _sym_change_count = sym_change_count;
1027*0a9064fbSMasahiro Yamada 	sym_change_count = count;
1028*0a9064fbSMasahiro Yamada 	if (conf_changed_callback &&
1029*0a9064fbSMasahiro Yamada 	    (bool)_sym_change_count != (bool)count)
1030*0a9064fbSMasahiro Yamada 		conf_changed_callback();
1031*0a9064fbSMasahiro Yamada }
1032*0a9064fbSMasahiro Yamada 
1033*0a9064fbSMasahiro Yamada void sym_add_change_count(int count)
1034*0a9064fbSMasahiro Yamada {
1035*0a9064fbSMasahiro Yamada 	sym_set_change_count(count + sym_change_count);
1036*0a9064fbSMasahiro Yamada }
1037*0a9064fbSMasahiro Yamada 
1038*0a9064fbSMasahiro Yamada bool conf_get_changed(void)
1039*0a9064fbSMasahiro Yamada {
1040*0a9064fbSMasahiro Yamada 	return sym_change_count;
1041*0a9064fbSMasahiro Yamada }
1042*0a9064fbSMasahiro Yamada 
1043*0a9064fbSMasahiro Yamada void conf_set_changed_callback(void (*fn)(void))
1044*0a9064fbSMasahiro Yamada {
1045*0a9064fbSMasahiro Yamada 	conf_changed_callback = fn;
1046*0a9064fbSMasahiro Yamada }
1047*0a9064fbSMasahiro Yamada 
1048*0a9064fbSMasahiro Yamada static bool randomize_choice_values(struct symbol *csym)
1049*0a9064fbSMasahiro Yamada {
1050*0a9064fbSMasahiro Yamada 	struct property *prop;
1051*0a9064fbSMasahiro Yamada 	struct symbol *sym;
1052*0a9064fbSMasahiro Yamada 	struct expr *e;
1053*0a9064fbSMasahiro Yamada 	int cnt, def;
1054*0a9064fbSMasahiro Yamada 
1055*0a9064fbSMasahiro Yamada 	/*
1056*0a9064fbSMasahiro Yamada 	 * If choice is mod then we may have more items selected
1057*0a9064fbSMasahiro Yamada 	 * and if no then no-one.
1058*0a9064fbSMasahiro Yamada 	 * In both cases stop.
1059*0a9064fbSMasahiro Yamada 	 */
1060*0a9064fbSMasahiro Yamada 	if (csym->curr.tri != yes)
1061*0a9064fbSMasahiro Yamada 		return false;
1062*0a9064fbSMasahiro Yamada 
1063*0a9064fbSMasahiro Yamada 	prop = sym_get_choice_prop(csym);
1064*0a9064fbSMasahiro Yamada 
1065*0a9064fbSMasahiro Yamada 	/* count entries in choice block */
1066*0a9064fbSMasahiro Yamada 	cnt = 0;
1067*0a9064fbSMasahiro Yamada 	expr_list_for_each_sym(prop->expr, e, sym)
1068*0a9064fbSMasahiro Yamada 		cnt++;
1069*0a9064fbSMasahiro Yamada 
1070*0a9064fbSMasahiro Yamada 	/*
1071*0a9064fbSMasahiro Yamada 	 * find a random value and set it to yes,
1072*0a9064fbSMasahiro Yamada 	 * set the rest to no so we have only one set
1073*0a9064fbSMasahiro Yamada 	 */
1074*0a9064fbSMasahiro Yamada 	def = (rand() % cnt);
1075*0a9064fbSMasahiro Yamada 
1076*0a9064fbSMasahiro Yamada 	cnt = 0;
1077*0a9064fbSMasahiro Yamada 	expr_list_for_each_sym(prop->expr, e, sym) {
1078*0a9064fbSMasahiro Yamada 		if (def == cnt++) {
1079*0a9064fbSMasahiro Yamada 			sym->def[S_DEF_USER].tri = yes;
1080*0a9064fbSMasahiro Yamada 			csym->def[S_DEF_USER].val = sym;
1081*0a9064fbSMasahiro Yamada 		}
1082*0a9064fbSMasahiro Yamada 		else {
1083*0a9064fbSMasahiro Yamada 			sym->def[S_DEF_USER].tri = no;
1084*0a9064fbSMasahiro Yamada 		}
1085*0a9064fbSMasahiro Yamada 		sym->flags |= SYMBOL_DEF_USER;
1086*0a9064fbSMasahiro Yamada 		/* clear VALID to get value calculated */
1087*0a9064fbSMasahiro Yamada 		sym->flags &= ~SYMBOL_VALID;
1088*0a9064fbSMasahiro Yamada 	}
1089*0a9064fbSMasahiro Yamada 	csym->flags |= SYMBOL_DEF_USER;
1090*0a9064fbSMasahiro Yamada 	/* clear VALID to get value calculated */
1091*0a9064fbSMasahiro Yamada 	csym->flags &= ~(SYMBOL_VALID);
1092*0a9064fbSMasahiro Yamada 
1093*0a9064fbSMasahiro Yamada 	return true;
1094*0a9064fbSMasahiro Yamada }
1095*0a9064fbSMasahiro Yamada 
1096*0a9064fbSMasahiro Yamada void set_all_choice_values(struct symbol *csym)
1097*0a9064fbSMasahiro Yamada {
1098*0a9064fbSMasahiro Yamada 	struct property *prop;
1099*0a9064fbSMasahiro Yamada 	struct symbol *sym;
1100*0a9064fbSMasahiro Yamada 	struct expr *e;
1101*0a9064fbSMasahiro Yamada 
1102*0a9064fbSMasahiro Yamada 	prop = sym_get_choice_prop(csym);
1103*0a9064fbSMasahiro Yamada 
1104*0a9064fbSMasahiro Yamada 	/*
1105*0a9064fbSMasahiro Yamada 	 * Set all non-assinged choice values to no
1106*0a9064fbSMasahiro Yamada 	 */
1107*0a9064fbSMasahiro Yamada 	expr_list_for_each_sym(prop->expr, e, sym) {
1108*0a9064fbSMasahiro Yamada 		if (!sym_has_value(sym))
1109*0a9064fbSMasahiro Yamada 			sym->def[S_DEF_USER].tri = no;
1110*0a9064fbSMasahiro Yamada 	}
1111*0a9064fbSMasahiro Yamada 	csym->flags |= SYMBOL_DEF_USER;
1112*0a9064fbSMasahiro Yamada 	/* clear VALID to get value calculated */
1113*0a9064fbSMasahiro Yamada 	csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
1114*0a9064fbSMasahiro Yamada }
1115*0a9064fbSMasahiro Yamada 
1116*0a9064fbSMasahiro Yamada bool conf_set_all_new_symbols(enum conf_def_mode mode)
1117*0a9064fbSMasahiro Yamada {
1118*0a9064fbSMasahiro Yamada 	struct symbol *sym, *csym;
1119*0a9064fbSMasahiro Yamada 	int i, cnt, pby, pty, ptm;	/* pby: probability of boolean  = y
1120*0a9064fbSMasahiro Yamada 					 * pty: probability of tristate = y
1121*0a9064fbSMasahiro Yamada 					 * ptm: probability of tristate = m
1122*0a9064fbSMasahiro Yamada 					 */
1123*0a9064fbSMasahiro Yamada 
1124*0a9064fbSMasahiro Yamada 	pby = 50; pty = ptm = 33; /* can't go as the default in switch-case
1125*0a9064fbSMasahiro Yamada 				   * below, otherwise gcc whines about
1126*0a9064fbSMasahiro Yamada 				   * -Wmaybe-uninitialized */
1127*0a9064fbSMasahiro Yamada 	if (mode == def_random) {
1128*0a9064fbSMasahiro Yamada 		int n, p[3];
1129*0a9064fbSMasahiro Yamada 		char *env = getenv("KCONFIG_PROBABILITY");
1130*0a9064fbSMasahiro Yamada 		n = 0;
1131*0a9064fbSMasahiro Yamada 		while( env && *env ) {
1132*0a9064fbSMasahiro Yamada 			char *endp;
1133*0a9064fbSMasahiro Yamada 			int tmp = strtol( env, &endp, 10 );
1134*0a9064fbSMasahiro Yamada 			if( tmp >= 0 && tmp <= 100 ) {
1135*0a9064fbSMasahiro Yamada 				p[n++] = tmp;
1136*0a9064fbSMasahiro Yamada 			} else {
1137*0a9064fbSMasahiro Yamada 				errno = ERANGE;
1138*0a9064fbSMasahiro Yamada 				perror( "KCONFIG_PROBABILITY" );
1139*0a9064fbSMasahiro Yamada 				exit( 1 );
1140*0a9064fbSMasahiro Yamada 			}
1141*0a9064fbSMasahiro Yamada 			env = (*endp == ':') ? endp+1 : endp;
1142*0a9064fbSMasahiro Yamada 			if( n >=3 ) {
1143*0a9064fbSMasahiro Yamada 				break;
1144*0a9064fbSMasahiro Yamada 			}
1145*0a9064fbSMasahiro Yamada 		}
1146*0a9064fbSMasahiro Yamada 		switch( n ) {
1147*0a9064fbSMasahiro Yamada 		case 1:
1148*0a9064fbSMasahiro Yamada 			pby = p[0]; ptm = pby/2; pty = pby-ptm;
1149*0a9064fbSMasahiro Yamada 			break;
1150*0a9064fbSMasahiro Yamada 		case 2:
1151*0a9064fbSMasahiro Yamada 			pty = p[0]; ptm = p[1]; pby = pty + ptm;
1152*0a9064fbSMasahiro Yamada 			break;
1153*0a9064fbSMasahiro Yamada 		case 3:
1154*0a9064fbSMasahiro Yamada 			pby = p[0]; pty = p[1]; ptm = p[2];
1155*0a9064fbSMasahiro Yamada 			break;
1156*0a9064fbSMasahiro Yamada 		}
1157*0a9064fbSMasahiro Yamada 
1158*0a9064fbSMasahiro Yamada 		if( pty+ptm > 100 ) {
1159*0a9064fbSMasahiro Yamada 			errno = ERANGE;
1160*0a9064fbSMasahiro Yamada 			perror( "KCONFIG_PROBABILITY" );
1161*0a9064fbSMasahiro Yamada 			exit( 1 );
1162*0a9064fbSMasahiro Yamada 		}
1163*0a9064fbSMasahiro Yamada 	}
1164*0a9064fbSMasahiro Yamada 	bool has_changed = false;
1165*0a9064fbSMasahiro Yamada 
1166*0a9064fbSMasahiro Yamada 	for_all_symbols(i, sym) {
1167*0a9064fbSMasahiro Yamada 		if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
1168*0a9064fbSMasahiro Yamada 			continue;
1169*0a9064fbSMasahiro Yamada 		switch (sym_get_type(sym)) {
1170*0a9064fbSMasahiro Yamada 		case S_BOOLEAN:
1171*0a9064fbSMasahiro Yamada 		case S_TRISTATE:
1172*0a9064fbSMasahiro Yamada 			has_changed = true;
1173*0a9064fbSMasahiro Yamada 			switch (mode) {
1174*0a9064fbSMasahiro Yamada 			case def_yes:
1175*0a9064fbSMasahiro Yamada 				sym->def[S_DEF_USER].tri = yes;
1176*0a9064fbSMasahiro Yamada 				break;
1177*0a9064fbSMasahiro Yamada 			case def_mod:
1178*0a9064fbSMasahiro Yamada 				sym->def[S_DEF_USER].tri = mod;
1179*0a9064fbSMasahiro Yamada 				break;
1180*0a9064fbSMasahiro Yamada 			case def_no:
1181*0a9064fbSMasahiro Yamada 				if (sym->flags & SYMBOL_ALLNOCONFIG_Y)
1182*0a9064fbSMasahiro Yamada 					sym->def[S_DEF_USER].tri = yes;
1183*0a9064fbSMasahiro Yamada 				else
1184*0a9064fbSMasahiro Yamada 					sym->def[S_DEF_USER].tri = no;
1185*0a9064fbSMasahiro Yamada 				break;
1186*0a9064fbSMasahiro Yamada 			case def_random:
1187*0a9064fbSMasahiro Yamada 				sym->def[S_DEF_USER].tri = no;
1188*0a9064fbSMasahiro Yamada 				cnt = rand() % 100;
1189*0a9064fbSMasahiro Yamada 				if (sym->type == S_TRISTATE) {
1190*0a9064fbSMasahiro Yamada 					if (cnt < pty)
1191*0a9064fbSMasahiro Yamada 						sym->def[S_DEF_USER].tri = yes;
1192*0a9064fbSMasahiro Yamada 					else if (cnt < (pty+ptm))
1193*0a9064fbSMasahiro Yamada 						sym->def[S_DEF_USER].tri = mod;
1194*0a9064fbSMasahiro Yamada 				} else if (cnt < pby)
1195*0a9064fbSMasahiro Yamada 					sym->def[S_DEF_USER].tri = yes;
1196*0a9064fbSMasahiro Yamada 				break;
1197*0a9064fbSMasahiro Yamada 			default:
1198*0a9064fbSMasahiro Yamada 				continue;
1199*0a9064fbSMasahiro Yamada 			}
1200*0a9064fbSMasahiro Yamada 			if (!(sym_is_choice(sym) && mode == def_random))
1201*0a9064fbSMasahiro Yamada 				sym->flags |= SYMBOL_DEF_USER;
1202*0a9064fbSMasahiro Yamada 			break;
1203*0a9064fbSMasahiro Yamada 		default:
1204*0a9064fbSMasahiro Yamada 			break;
1205*0a9064fbSMasahiro Yamada 		}
1206*0a9064fbSMasahiro Yamada 
1207*0a9064fbSMasahiro Yamada 	}
1208*0a9064fbSMasahiro Yamada 
1209*0a9064fbSMasahiro Yamada 	sym_clear_all_valid();
1210*0a9064fbSMasahiro Yamada 
1211*0a9064fbSMasahiro Yamada 	/*
1212*0a9064fbSMasahiro Yamada 	 * We have different type of choice blocks.
1213*0a9064fbSMasahiro Yamada 	 * If curr.tri equals to mod then we can select several
1214*0a9064fbSMasahiro Yamada 	 * choice symbols in one block.
1215*0a9064fbSMasahiro Yamada 	 * In this case we do nothing.
1216*0a9064fbSMasahiro Yamada 	 * If curr.tri equals yes then only one symbol can be
1217*0a9064fbSMasahiro Yamada 	 * selected in a choice block and we set it to yes,
1218*0a9064fbSMasahiro Yamada 	 * and the rest to no.
1219*0a9064fbSMasahiro Yamada 	 */
1220*0a9064fbSMasahiro Yamada 	if (mode != def_random) {
1221*0a9064fbSMasahiro Yamada 		for_all_symbols(i, csym) {
1222*0a9064fbSMasahiro Yamada 			if ((sym_is_choice(csym) && !sym_has_value(csym)) ||
1223*0a9064fbSMasahiro Yamada 			    sym_is_choice_value(csym))
1224*0a9064fbSMasahiro Yamada 				csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;
1225*0a9064fbSMasahiro Yamada 		}
1226*0a9064fbSMasahiro Yamada 	}
1227*0a9064fbSMasahiro Yamada 
1228*0a9064fbSMasahiro Yamada 	for_all_symbols(i, csym) {
1229*0a9064fbSMasahiro Yamada 		if (sym_has_value(csym) || !sym_is_choice(csym))
1230*0a9064fbSMasahiro Yamada 			continue;
1231*0a9064fbSMasahiro Yamada 
1232*0a9064fbSMasahiro Yamada 		sym_calc_value(csym);
1233*0a9064fbSMasahiro Yamada 		if (mode == def_random)
1234*0a9064fbSMasahiro Yamada 			has_changed = randomize_choice_values(csym);
1235*0a9064fbSMasahiro Yamada 		else {
1236*0a9064fbSMasahiro Yamada 			set_all_choice_values(csym);
1237*0a9064fbSMasahiro Yamada 			has_changed = true;
1238*0a9064fbSMasahiro Yamada 		}
1239*0a9064fbSMasahiro Yamada 	}
1240*0a9064fbSMasahiro Yamada 
1241*0a9064fbSMasahiro Yamada 	return has_changed;
1242*0a9064fbSMasahiro Yamada }
1243