xref: /aosp_15_r20/external/toybox/kconfig/confdata.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /*
2*cf5a6c84SAndroid Build Coastguard Worker  * Copyright (C) 2002 Roman Zippel <[email protected]>
3*cf5a6c84SAndroid Build Coastguard Worker  * Released under the terms of the GNU GPL v2.0.
4*cf5a6c84SAndroid Build Coastguard Worker  */
5*cf5a6c84SAndroid Build Coastguard Worker 
6*cf5a6c84SAndroid Build Coastguard Worker #include <sys/stat.h>
7*cf5a6c84SAndroid Build Coastguard Worker #include <ctype.h>
8*cf5a6c84SAndroid Build Coastguard Worker #include <errno.h>
9*cf5a6c84SAndroid Build Coastguard Worker #include <fcntl.h>
10*cf5a6c84SAndroid Build Coastguard Worker #include <limits.h>
11*cf5a6c84SAndroid Build Coastguard Worker #include <stdio.h>
12*cf5a6c84SAndroid Build Coastguard Worker #include <stdlib.h>
13*cf5a6c84SAndroid Build Coastguard Worker #include <string.h>
14*cf5a6c84SAndroid Build Coastguard Worker #include <time.h>
15*cf5a6c84SAndroid Build Coastguard Worker #include <unistd.h>
16*cf5a6c84SAndroid Build Coastguard Worker 
17*cf5a6c84SAndroid Build Coastguard Worker #define LKC_DIRECT_LINK
18*cf5a6c84SAndroid Build Coastguard Worker #include "lkc.h"
19*cf5a6c84SAndroid Build Coastguard Worker 
20*cf5a6c84SAndroid Build Coastguard Worker static void conf_warning(const char *fmt, ...)
21*cf5a6c84SAndroid Build Coastguard Worker 	__attribute__ ((format (printf, 1, 2)));
22*cf5a6c84SAndroid Build Coastguard Worker 
23*cf5a6c84SAndroid Build Coastguard Worker static const char *conf_filename;
24*cf5a6c84SAndroid Build Coastguard Worker static int conf_lineno, conf_warnings, conf_unsaved;
25*cf5a6c84SAndroid Build Coastguard Worker 
26*cf5a6c84SAndroid Build Coastguard Worker #ifndef conf_defname
27*cf5a6c84SAndroid Build Coastguard Worker const char conf_defname[] = "arch/$ARCH/defconfig";
28*cf5a6c84SAndroid Build Coastguard Worker #endif
29*cf5a6c84SAndroid Build Coastguard Worker 
30*cf5a6c84SAndroid Build Coastguard Worker #ifndef CONFIG_PREFIX
31*cf5a6c84SAndroid Build Coastguard Worker #define CONFIG_PREFIX "CONFIG_"
32*cf5a6c84SAndroid Build Coastguard Worker #endif
33*cf5a6c84SAndroid Build Coastguard Worker 
conf_warning(const char * fmt,...)34*cf5a6c84SAndroid Build Coastguard Worker static void conf_warning(const char *fmt, ...)
35*cf5a6c84SAndroid Build Coastguard Worker {
36*cf5a6c84SAndroid Build Coastguard Worker 	va_list ap;
37*cf5a6c84SAndroid Build Coastguard Worker 	va_start(ap, fmt);
38*cf5a6c84SAndroid Build Coastguard Worker 	fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
39*cf5a6c84SAndroid Build Coastguard Worker 	vfprintf(stderr, fmt, ap);
40*cf5a6c84SAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
41*cf5a6c84SAndroid Build Coastguard Worker 	va_end(ap);
42*cf5a6c84SAndroid Build Coastguard Worker 	conf_warnings++;
43*cf5a6c84SAndroid Build Coastguard Worker }
44*cf5a6c84SAndroid Build Coastguard Worker 
conf_get_configname(void)45*cf5a6c84SAndroid Build Coastguard Worker const char *conf_get_configname(void)
46*cf5a6c84SAndroid Build Coastguard Worker {
47*cf5a6c84SAndroid Build Coastguard Worker 	char *name = getenv("KCONFIG_CONFIG");
48*cf5a6c84SAndroid Build Coastguard Worker 
49*cf5a6c84SAndroid Build Coastguard Worker 	return name ? name : ".config";
50*cf5a6c84SAndroid Build Coastguard Worker }
51*cf5a6c84SAndroid Build Coastguard Worker 
conf_expand_value(const char * in)52*cf5a6c84SAndroid Build Coastguard Worker static char *conf_expand_value(const char *in)
53*cf5a6c84SAndroid Build Coastguard Worker {
54*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym;
55*cf5a6c84SAndroid Build Coastguard Worker 	const char *src;
56*cf5a6c84SAndroid Build Coastguard Worker 	static char res_value[SYMBOL_MAXLENGTH];
57*cf5a6c84SAndroid Build Coastguard Worker 	char *dst, name[SYMBOL_MAXLENGTH];
58*cf5a6c84SAndroid Build Coastguard Worker 
59*cf5a6c84SAndroid Build Coastguard Worker 	res_value[0] = 0;
60*cf5a6c84SAndroid Build Coastguard Worker 	dst = name;
61*cf5a6c84SAndroid Build Coastguard Worker 	while ((src = strchr(in, '$'))) {
62*cf5a6c84SAndroid Build Coastguard Worker 		strncat(res_value, in, src - in);
63*cf5a6c84SAndroid Build Coastguard Worker 		src++;
64*cf5a6c84SAndroid Build Coastguard Worker 		dst = name;
65*cf5a6c84SAndroid Build Coastguard Worker 		while (isalnum(*src) || *src == '_')
66*cf5a6c84SAndroid Build Coastguard Worker 			*dst++ = *src++;
67*cf5a6c84SAndroid Build Coastguard Worker 		*dst = 0;
68*cf5a6c84SAndroid Build Coastguard Worker 		sym = sym_lookup(name, 0);
69*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(sym);
70*cf5a6c84SAndroid Build Coastguard Worker 		strcat(res_value, sym_get_string_value(sym));
71*cf5a6c84SAndroid Build Coastguard Worker 		in = src;
72*cf5a6c84SAndroid Build Coastguard Worker 	}
73*cf5a6c84SAndroid Build Coastguard Worker 	strcat(res_value, in);
74*cf5a6c84SAndroid Build Coastguard Worker 
75*cf5a6c84SAndroid Build Coastguard Worker 	return res_value;
76*cf5a6c84SAndroid Build Coastguard Worker }
77*cf5a6c84SAndroid Build Coastguard Worker 
conf_get_default_confname(void)78*cf5a6c84SAndroid Build Coastguard Worker char *conf_get_default_confname(void)
79*cf5a6c84SAndroid Build Coastguard Worker {
80*cf5a6c84SAndroid Build Coastguard Worker 	struct stat buf;
81*cf5a6c84SAndroid Build Coastguard Worker 	static char fullname[PATH_MAX+1];
82*cf5a6c84SAndroid Build Coastguard Worker 	char *env, *name;
83*cf5a6c84SAndroid Build Coastguard Worker 
84*cf5a6c84SAndroid Build Coastguard Worker 	name = conf_expand_value(conf_defname);
85*cf5a6c84SAndroid Build Coastguard Worker 	env = getenv(SRCTREE);
86*cf5a6c84SAndroid Build Coastguard Worker 	if (env) {
87*cf5a6c84SAndroid Build Coastguard Worker 		sprintf(fullname, "%s/%s", env, name);
88*cf5a6c84SAndroid Build Coastguard Worker 		if (!stat(fullname, &buf))
89*cf5a6c84SAndroid Build Coastguard Worker 			return fullname;
90*cf5a6c84SAndroid Build Coastguard Worker 	}
91*cf5a6c84SAndroid Build Coastguard Worker 	return name;
92*cf5a6c84SAndroid Build Coastguard Worker }
93*cf5a6c84SAndroid Build Coastguard Worker 
conf_read_simple(const char * name,int def)94*cf5a6c84SAndroid Build Coastguard Worker int conf_read_simple(const char *name, int def)
95*cf5a6c84SAndroid Build Coastguard Worker {
96*cf5a6c84SAndroid Build Coastguard Worker 	FILE *in = NULL;
97*cf5a6c84SAndroid Build Coastguard Worker 	char line[1024];
98*cf5a6c84SAndroid Build Coastguard Worker 	char *p, *p2;
99*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym;
100*cf5a6c84SAndroid Build Coastguard Worker 	int i, def_flags;
101*cf5a6c84SAndroid Build Coastguard Worker 
102*cf5a6c84SAndroid Build Coastguard Worker 	if (name) {
103*cf5a6c84SAndroid Build Coastguard Worker 		in = zconf_fopen(name);
104*cf5a6c84SAndroid Build Coastguard Worker 	} else {
105*cf5a6c84SAndroid Build Coastguard Worker 		struct property *prop;
106*cf5a6c84SAndroid Build Coastguard Worker 
107*cf5a6c84SAndroid Build Coastguard Worker 		name = conf_get_configname();
108*cf5a6c84SAndroid Build Coastguard Worker 		in = zconf_fopen(name);
109*cf5a6c84SAndroid Build Coastguard Worker 		if (in)
110*cf5a6c84SAndroid Build Coastguard Worker 			goto load;
111*cf5a6c84SAndroid Build Coastguard Worker 		sym_change_count++;
112*cf5a6c84SAndroid Build Coastguard Worker 		if (!sym_defconfig_list)
113*cf5a6c84SAndroid Build Coastguard Worker 			return 1;
114*cf5a6c84SAndroid Build Coastguard Worker 
115*cf5a6c84SAndroid Build Coastguard Worker 		for_all_defaults(sym_defconfig_list, prop) {
116*cf5a6c84SAndroid Build Coastguard Worker 			if (expr_calc_value(prop->visible.expr) == no ||
117*cf5a6c84SAndroid Build Coastguard Worker 			    prop->expr->type != E_SYMBOL)
118*cf5a6c84SAndroid Build Coastguard Worker 				continue;
119*cf5a6c84SAndroid Build Coastguard Worker 			name = conf_expand_value(prop->expr->left.sym->name);
120*cf5a6c84SAndroid Build Coastguard Worker 			in = zconf_fopen(name);
121*cf5a6c84SAndroid Build Coastguard Worker 			if (in) {
122*cf5a6c84SAndroid Build Coastguard Worker 				printf(_("#\n"
123*cf5a6c84SAndroid Build Coastguard Worker 					 "# using defaults found in %s\n"
124*cf5a6c84SAndroid Build Coastguard Worker 					 "#\n"), name);
125*cf5a6c84SAndroid Build Coastguard Worker 				goto load;
126*cf5a6c84SAndroid Build Coastguard Worker 			}
127*cf5a6c84SAndroid Build Coastguard Worker 		}
128*cf5a6c84SAndroid Build Coastguard Worker 	}
129*cf5a6c84SAndroid Build Coastguard Worker 	if (!in)
130*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
131*cf5a6c84SAndroid Build Coastguard Worker 
132*cf5a6c84SAndroid Build Coastguard Worker load:
133*cf5a6c84SAndroid Build Coastguard Worker 	conf_filename = name;
134*cf5a6c84SAndroid Build Coastguard Worker 	conf_lineno = 0;
135*cf5a6c84SAndroid Build Coastguard Worker 	conf_warnings = 0;
136*cf5a6c84SAndroid Build Coastguard Worker 	conf_unsaved = 0;
137*cf5a6c84SAndroid Build Coastguard Worker 
138*cf5a6c84SAndroid Build Coastguard Worker 	def_flags = SYMBOL_DEF << def;
139*cf5a6c84SAndroid Build Coastguard Worker 	for_all_symbols(i, sym) {
140*cf5a6c84SAndroid Build Coastguard Worker 		sym->flags |= SYMBOL_CHANGED;
141*cf5a6c84SAndroid Build Coastguard Worker 		sym->flags &= ~(def_flags|SYMBOL_VALID);
142*cf5a6c84SAndroid Build Coastguard Worker 		if (sym_is_choice(sym))
143*cf5a6c84SAndroid Build Coastguard Worker 			sym->flags |= def_flags;
144*cf5a6c84SAndroid Build Coastguard Worker 		switch (sym->type) {
145*cf5a6c84SAndroid Build Coastguard Worker 		case S_INT:
146*cf5a6c84SAndroid Build Coastguard Worker 		case S_HEX:
147*cf5a6c84SAndroid Build Coastguard Worker 		case S_STRING:
148*cf5a6c84SAndroid Build Coastguard Worker 			if (sym->def[def].val)
149*cf5a6c84SAndroid Build Coastguard Worker 				free(sym->def[def].val);
150*cf5a6c84SAndroid Build Coastguard Worker 		default:
151*cf5a6c84SAndroid Build Coastguard Worker 			sym->def[def].val = NULL;
152*cf5a6c84SAndroid Build Coastguard Worker 			sym->def[def].tri = no;
153*cf5a6c84SAndroid Build Coastguard Worker 		}
154*cf5a6c84SAndroid Build Coastguard Worker 	}
155*cf5a6c84SAndroid Build Coastguard Worker 
156*cf5a6c84SAndroid Build Coastguard Worker 	while (fgets(line, sizeof(line), in)) {
157*cf5a6c84SAndroid Build Coastguard Worker 		conf_lineno++;
158*cf5a6c84SAndroid Build Coastguard Worker 		sym = NULL;
159*cf5a6c84SAndroid Build Coastguard Worker 		switch (line[0]) {
160*cf5a6c84SAndroid Build Coastguard Worker 		case '#':
161*cf5a6c84SAndroid Build Coastguard Worker 			if (line[1]!=' ' || memcmp(line + 2, CONFIG_PREFIX,
162*cf5a6c84SAndroid Build Coastguard Worker 					       	strlen(CONFIG_PREFIX))) {
163*cf5a6c84SAndroid Build Coastguard Worker 				continue;
164*cf5a6c84SAndroid Build Coastguard Worker 			}
165*cf5a6c84SAndroid Build Coastguard Worker 			p = strchr(line + 2 + strlen(CONFIG_PREFIX), ' ');
166*cf5a6c84SAndroid Build Coastguard Worker 			if (!p)
167*cf5a6c84SAndroid Build Coastguard Worker 				continue;
168*cf5a6c84SAndroid Build Coastguard Worker 			*p++ = 0;
169*cf5a6c84SAndroid Build Coastguard Worker 			if (strncmp(p, "is not set", 10))
170*cf5a6c84SAndroid Build Coastguard Worker 				continue;
171*cf5a6c84SAndroid Build Coastguard Worker 			if (def == S_DEF_USER) {
172*cf5a6c84SAndroid Build Coastguard Worker 				sym = sym_find(line + 2 + strlen(CONFIG_PREFIX));
173*cf5a6c84SAndroid Build Coastguard Worker 				if (!sym) {
174*cf5a6c84SAndroid Build Coastguard Worker 					conf_warning("trying to assign nonexistent symbol %s", line + 2 + strlen(CONFIG_PREFIX));
175*cf5a6c84SAndroid Build Coastguard Worker 					break;
176*cf5a6c84SAndroid Build Coastguard Worker 				}
177*cf5a6c84SAndroid Build Coastguard Worker 			} else {
178*cf5a6c84SAndroid Build Coastguard Worker 				sym = sym_lookup(line + 9, 0);
179*cf5a6c84SAndroid Build Coastguard Worker 				if (sym->type == S_UNKNOWN)
180*cf5a6c84SAndroid Build Coastguard Worker 					sym->type = S_BOOLEAN;
181*cf5a6c84SAndroid Build Coastguard Worker 			}
182*cf5a6c84SAndroid Build Coastguard Worker 			if (sym->flags & def_flags) {
183*cf5a6c84SAndroid Build Coastguard Worker 				conf_warning("trying to reassign symbol %s", sym->name);
184*cf5a6c84SAndroid Build Coastguard Worker 				break;
185*cf5a6c84SAndroid Build Coastguard Worker 			}
186*cf5a6c84SAndroid Build Coastguard Worker 			switch (sym->type) {
187*cf5a6c84SAndroid Build Coastguard Worker 			case S_BOOLEAN:
188*cf5a6c84SAndroid Build Coastguard Worker 			case S_TRISTATE:
189*cf5a6c84SAndroid Build Coastguard Worker 				sym->def[def].tri = no;
190*cf5a6c84SAndroid Build Coastguard Worker 				sym->flags |= def_flags;
191*cf5a6c84SAndroid Build Coastguard Worker 				break;
192*cf5a6c84SAndroid Build Coastguard Worker 			default:
193*cf5a6c84SAndroid Build Coastguard Worker 				;
194*cf5a6c84SAndroid Build Coastguard Worker 			}
195*cf5a6c84SAndroid Build Coastguard Worker 			break;
196*cf5a6c84SAndroid Build Coastguard Worker 		case 'A' ... 'Z':
197*cf5a6c84SAndroid Build Coastguard Worker 			if (memcmp(line, CONFIG_PREFIX, strlen(CONFIG_PREFIX))) {
198*cf5a6c84SAndroid Build Coastguard Worker 				conf_warning("unexpected data");
199*cf5a6c84SAndroid Build Coastguard Worker 				continue;
200*cf5a6c84SAndroid Build Coastguard Worker 			}
201*cf5a6c84SAndroid Build Coastguard Worker 			p = strchr(line + strlen(CONFIG_PREFIX), '=');
202*cf5a6c84SAndroid Build Coastguard Worker 			if (!p)
203*cf5a6c84SAndroid Build Coastguard Worker 				continue;
204*cf5a6c84SAndroid Build Coastguard Worker 			*p++ = 0;
205*cf5a6c84SAndroid Build Coastguard Worker 			p2 = strchr(p, '\n');
206*cf5a6c84SAndroid Build Coastguard Worker 			if (p2) {
207*cf5a6c84SAndroid Build Coastguard Worker 				*p2-- = 0;
208*cf5a6c84SAndroid Build Coastguard Worker 				if (*p2 == '\r')
209*cf5a6c84SAndroid Build Coastguard Worker 					*p2 = 0;
210*cf5a6c84SAndroid Build Coastguard Worker 			}
211*cf5a6c84SAndroid Build Coastguard Worker 			if (def == S_DEF_USER) {
212*cf5a6c84SAndroid Build Coastguard Worker 				sym = sym_find(line + strlen(CONFIG_PREFIX));
213*cf5a6c84SAndroid Build Coastguard Worker 				if (!sym) {
214*cf5a6c84SAndroid Build Coastguard Worker 					conf_warning("trying to assign nonexistent symbol %s", line + 7);
215*cf5a6c84SAndroid Build Coastguard Worker 					break;
216*cf5a6c84SAndroid Build Coastguard Worker 				}
217*cf5a6c84SAndroid Build Coastguard Worker 			} else {
218*cf5a6c84SAndroid Build Coastguard Worker 				sym = sym_lookup(line + strlen(CONFIG_PREFIX), 0);
219*cf5a6c84SAndroid Build Coastguard Worker 				if (sym->type == S_UNKNOWN)
220*cf5a6c84SAndroid Build Coastguard Worker 					sym->type = S_OTHER;
221*cf5a6c84SAndroid Build Coastguard Worker 			}
222*cf5a6c84SAndroid Build Coastguard Worker 			if (sym->flags & def_flags) {
223*cf5a6c84SAndroid Build Coastguard Worker 				conf_warning("trying to reassign symbol %s", sym->name);
224*cf5a6c84SAndroid Build Coastguard Worker 				break;
225*cf5a6c84SAndroid Build Coastguard Worker 			}
226*cf5a6c84SAndroid Build Coastguard Worker 			switch (sym->type) {
227*cf5a6c84SAndroid Build Coastguard Worker 			case S_TRISTATE:
228*cf5a6c84SAndroid Build Coastguard Worker 				if (p[0] == 'm') {
229*cf5a6c84SAndroid Build Coastguard Worker 					sym->def[def].tri = mod;
230*cf5a6c84SAndroid Build Coastguard Worker 					sym->flags |= def_flags;
231*cf5a6c84SAndroid Build Coastguard Worker 					break;
232*cf5a6c84SAndroid Build Coastguard Worker 				}
233*cf5a6c84SAndroid Build Coastguard Worker 			case S_BOOLEAN:
234*cf5a6c84SAndroid Build Coastguard Worker 				if (p[0] == 'y') {
235*cf5a6c84SAndroid Build Coastguard Worker 					sym->def[def].tri = yes;
236*cf5a6c84SAndroid Build Coastguard Worker 					sym->flags |= def_flags;
237*cf5a6c84SAndroid Build Coastguard Worker 					break;
238*cf5a6c84SAndroid Build Coastguard Worker 				}
239*cf5a6c84SAndroid Build Coastguard Worker 				if (p[0] == 'n') {
240*cf5a6c84SAndroid Build Coastguard Worker 					sym->def[def].tri = no;
241*cf5a6c84SAndroid Build Coastguard Worker 					sym->flags |= def_flags;
242*cf5a6c84SAndroid Build Coastguard Worker 					break;
243*cf5a6c84SAndroid Build Coastguard Worker 				}
244*cf5a6c84SAndroid Build Coastguard Worker 				conf_warning("symbol value '%s' invalid for %s", p, sym->name);
245*cf5a6c84SAndroid Build Coastguard Worker 				break;
246*cf5a6c84SAndroid Build Coastguard Worker 			case S_OTHER:
247*cf5a6c84SAndroid Build Coastguard Worker 				if (*p != '"') {
248*cf5a6c84SAndroid Build Coastguard Worker 					for (p2 = p; *p2 && !isspace(*p2); p2++)
249*cf5a6c84SAndroid Build Coastguard Worker 						;
250*cf5a6c84SAndroid Build Coastguard Worker 					sym->type = S_STRING;
251*cf5a6c84SAndroid Build Coastguard Worker 					goto done;
252*cf5a6c84SAndroid Build Coastguard Worker 				}
253*cf5a6c84SAndroid Build Coastguard Worker 			case S_STRING:
254*cf5a6c84SAndroid Build Coastguard Worker 				if (*p++ != '"')
255*cf5a6c84SAndroid Build Coastguard Worker 					break;
256*cf5a6c84SAndroid Build Coastguard Worker 				for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
257*cf5a6c84SAndroid Build Coastguard Worker 					if (*p2 == '"') {
258*cf5a6c84SAndroid Build Coastguard Worker 						*p2 = 0;
259*cf5a6c84SAndroid Build Coastguard Worker 						break;
260*cf5a6c84SAndroid Build Coastguard Worker 					}
261*cf5a6c84SAndroid Build Coastguard Worker 					memmove(p2, p2 + 1, strlen(p2));
262*cf5a6c84SAndroid Build Coastguard Worker 				}
263*cf5a6c84SAndroid Build Coastguard Worker 				if (!p2) {
264*cf5a6c84SAndroid Build Coastguard Worker 					conf_warning("invalid string found");
265*cf5a6c84SAndroid Build Coastguard Worker 					continue;
266*cf5a6c84SAndroid Build Coastguard Worker 				}
267*cf5a6c84SAndroid Build Coastguard Worker 			case S_INT:
268*cf5a6c84SAndroid Build Coastguard Worker 			case S_HEX:
269*cf5a6c84SAndroid Build Coastguard Worker 			done:
270*cf5a6c84SAndroid Build Coastguard Worker 				if (sym_string_valid(sym, p)) {
271*cf5a6c84SAndroid Build Coastguard Worker 					sym->def[def].val = strdup(p);
272*cf5a6c84SAndroid Build Coastguard Worker 					sym->flags |= def_flags;
273*cf5a6c84SAndroid Build Coastguard Worker 				} else {
274*cf5a6c84SAndroid Build Coastguard Worker 					conf_warning("symbol value '%s' invalid for %s", p, sym->name);
275*cf5a6c84SAndroid Build Coastguard Worker 					continue;
276*cf5a6c84SAndroid Build Coastguard Worker 				}
277*cf5a6c84SAndroid Build Coastguard Worker 				break;
278*cf5a6c84SAndroid Build Coastguard Worker 			default:
279*cf5a6c84SAndroid Build Coastguard Worker 				;
280*cf5a6c84SAndroid Build Coastguard Worker 			}
281*cf5a6c84SAndroid Build Coastguard Worker 			break;
282*cf5a6c84SAndroid Build Coastguard Worker 		case '\r':
283*cf5a6c84SAndroid Build Coastguard Worker 		case '\n':
284*cf5a6c84SAndroid Build Coastguard Worker 			break;
285*cf5a6c84SAndroid Build Coastguard Worker 		default:
286*cf5a6c84SAndroid Build Coastguard Worker 			conf_warning("unexpected data");
287*cf5a6c84SAndroid Build Coastguard Worker 			continue;
288*cf5a6c84SAndroid Build Coastguard Worker 		}
289*cf5a6c84SAndroid Build Coastguard Worker 		if (sym && sym_is_choice_value(sym)) {
290*cf5a6c84SAndroid Build Coastguard Worker 			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
291*cf5a6c84SAndroid Build Coastguard Worker 			switch (sym->def[def].tri) {
292*cf5a6c84SAndroid Build Coastguard Worker 			case no:
293*cf5a6c84SAndroid Build Coastguard Worker 				break;
294*cf5a6c84SAndroid Build Coastguard Worker 			case mod:
295*cf5a6c84SAndroid Build Coastguard Worker 				if (cs->def[def].tri == yes) {
296*cf5a6c84SAndroid Build Coastguard Worker 					conf_warning("%s creates inconsistent choice state", sym->name);
297*cf5a6c84SAndroid Build Coastguard Worker 					cs->flags &= ~def_flags;
298*cf5a6c84SAndroid Build Coastguard Worker 				}
299*cf5a6c84SAndroid Build Coastguard Worker 				break;
300*cf5a6c84SAndroid Build Coastguard Worker 			case yes:
301*cf5a6c84SAndroid Build Coastguard Worker 				if (cs->def[def].tri != no) {
302*cf5a6c84SAndroid Build Coastguard Worker 					conf_warning("%s creates inconsistent choice state", sym->name);
303*cf5a6c84SAndroid Build Coastguard Worker 					cs->flags &= ~def_flags;
304*cf5a6c84SAndroid Build Coastguard Worker 				} else
305*cf5a6c84SAndroid Build Coastguard Worker 					cs->def[def].val = sym;
306*cf5a6c84SAndroid Build Coastguard Worker 				break;
307*cf5a6c84SAndroid Build Coastguard Worker 			}
308*cf5a6c84SAndroid Build Coastguard Worker 			cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri);
309*cf5a6c84SAndroid Build Coastguard Worker 		}
310*cf5a6c84SAndroid Build Coastguard Worker 	}
311*cf5a6c84SAndroid Build Coastguard Worker 	fclose(in);
312*cf5a6c84SAndroid Build Coastguard Worker 
313*cf5a6c84SAndroid Build Coastguard Worker 	if (modules_sym)
314*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(modules_sym);
315*cf5a6c84SAndroid Build Coastguard Worker 	return 0;
316*cf5a6c84SAndroid Build Coastguard Worker }
317*cf5a6c84SAndroid Build Coastguard Worker 
conf_read(const char * name)318*cf5a6c84SAndroid Build Coastguard Worker int conf_read(const char *name)
319*cf5a6c84SAndroid Build Coastguard Worker {
320*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym;
321*cf5a6c84SAndroid Build Coastguard Worker 	struct property *prop;
322*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *e;
323*cf5a6c84SAndroid Build Coastguard Worker 	int i, flags;
324*cf5a6c84SAndroid Build Coastguard Worker 
325*cf5a6c84SAndroid Build Coastguard Worker 	sym_change_count = 0;
326*cf5a6c84SAndroid Build Coastguard Worker 
327*cf5a6c84SAndroid Build Coastguard Worker 	if (conf_read_simple(name, S_DEF_USER))
328*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
329*cf5a6c84SAndroid Build Coastguard Worker 
330*cf5a6c84SAndroid Build Coastguard Worker 	for_all_symbols(i, sym) {
331*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(sym);
332*cf5a6c84SAndroid Build Coastguard Worker 		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
333*cf5a6c84SAndroid Build Coastguard Worker 			goto sym_ok;
334*cf5a6c84SAndroid Build Coastguard Worker 		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
335*cf5a6c84SAndroid Build Coastguard Worker 			/* check that calculated value agrees with saved value */
336*cf5a6c84SAndroid Build Coastguard Worker 			switch (sym->type) {
337*cf5a6c84SAndroid Build Coastguard Worker 			case S_BOOLEAN:
338*cf5a6c84SAndroid Build Coastguard Worker 			case S_TRISTATE:
339*cf5a6c84SAndroid Build Coastguard Worker 				if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
340*cf5a6c84SAndroid Build Coastguard Worker 					break;
341*cf5a6c84SAndroid Build Coastguard Worker 				if (!sym_is_choice(sym))
342*cf5a6c84SAndroid Build Coastguard Worker 					goto sym_ok;
343*cf5a6c84SAndroid Build Coastguard Worker 			default:
344*cf5a6c84SAndroid Build Coastguard Worker 				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
345*cf5a6c84SAndroid Build Coastguard Worker 					goto sym_ok;
346*cf5a6c84SAndroid Build Coastguard Worker 				break;
347*cf5a6c84SAndroid Build Coastguard Worker 			}
348*cf5a6c84SAndroid Build Coastguard Worker 		} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
349*cf5a6c84SAndroid Build Coastguard Worker 			/* no previous value and not saved */
350*cf5a6c84SAndroid Build Coastguard Worker 			goto sym_ok;
351*cf5a6c84SAndroid Build Coastguard Worker 		conf_unsaved++;
352*cf5a6c84SAndroid Build Coastguard Worker 		/* maybe print value in verbose mode... */
353*cf5a6c84SAndroid Build Coastguard Worker 	sym_ok:
354*cf5a6c84SAndroid Build Coastguard Worker 		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
355*cf5a6c84SAndroid Build Coastguard Worker 			if (sym->visible == no)
356*cf5a6c84SAndroid Build Coastguard Worker 				sym->flags &= ~SYMBOL_DEF_USER;
357*cf5a6c84SAndroid Build Coastguard Worker 			switch (sym->type) {
358*cf5a6c84SAndroid Build Coastguard Worker 			case S_STRING:
359*cf5a6c84SAndroid Build Coastguard Worker 			case S_INT:
360*cf5a6c84SAndroid Build Coastguard Worker 			case S_HEX:
361*cf5a6c84SAndroid Build Coastguard Worker 				if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val))
362*cf5a6c84SAndroid Build Coastguard Worker 					sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
363*cf5a6c84SAndroid Build Coastguard Worker 			default:
364*cf5a6c84SAndroid Build Coastguard Worker 				break;
365*cf5a6c84SAndroid Build Coastguard Worker 			}
366*cf5a6c84SAndroid Build Coastguard Worker 		}
367*cf5a6c84SAndroid Build Coastguard Worker 		if (!sym_is_choice(sym))
368*cf5a6c84SAndroid Build Coastguard Worker 			continue;
369*cf5a6c84SAndroid Build Coastguard Worker 		prop = sym_get_choice_prop(sym);
370*cf5a6c84SAndroid Build Coastguard Worker 		flags = sym->flags;
371*cf5a6c84SAndroid Build Coastguard Worker 		for (e = prop->expr; e; e = e->left.expr)
372*cf5a6c84SAndroid Build Coastguard Worker 			if (e->right.sym->visible != no)
373*cf5a6c84SAndroid Build Coastguard Worker 				flags &= e->right.sym->flags;
374*cf5a6c84SAndroid Build Coastguard Worker 		sym->flags &= flags | ~SYMBOL_DEF_USER;
375*cf5a6c84SAndroid Build Coastguard Worker 	}
376*cf5a6c84SAndroid Build Coastguard Worker 
377*cf5a6c84SAndroid Build Coastguard Worker 	sym_change_count += conf_warnings || conf_unsaved;
378*cf5a6c84SAndroid Build Coastguard Worker 
379*cf5a6c84SAndroid Build Coastguard Worker 	return 0;
380*cf5a6c84SAndroid Build Coastguard Worker }
381*cf5a6c84SAndroid Build Coastguard Worker 
next_menu(struct menu * menu)382*cf5a6c84SAndroid Build Coastguard Worker struct menu *next_menu(struct menu *menu)
383*cf5a6c84SAndroid Build Coastguard Worker {
384*cf5a6c84SAndroid Build Coastguard Worker 	if (menu->list) return menu->list;
385*cf5a6c84SAndroid Build Coastguard Worker 	do {
386*cf5a6c84SAndroid Build Coastguard Worker 		if (menu->next) {
387*cf5a6c84SAndroid Build Coastguard Worker 			menu = menu->next;
388*cf5a6c84SAndroid Build Coastguard Worker 			break;
389*cf5a6c84SAndroid Build Coastguard Worker 		}
390*cf5a6c84SAndroid Build Coastguard Worker 	} while ((menu = menu->parent));
391*cf5a6c84SAndroid Build Coastguard Worker 
392*cf5a6c84SAndroid Build Coastguard Worker 	return menu;
393*cf5a6c84SAndroid Build Coastguard Worker }
394*cf5a6c84SAndroid Build Coastguard Worker 
395*cf5a6c84SAndroid Build Coastguard Worker #define SYMBOL_FORCEWRITE (1<<31)
396*cf5a6c84SAndroid Build Coastguard Worker 
conf_write(const char * name)397*cf5a6c84SAndroid Build Coastguard Worker int conf_write(const char *name)
398*cf5a6c84SAndroid Build Coastguard Worker {
399*cf5a6c84SAndroid Build Coastguard Worker 	FILE *out;
400*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym;
401*cf5a6c84SAndroid Build Coastguard Worker 	struct menu *menu;
402*cf5a6c84SAndroid Build Coastguard Worker 	const char *basename;
403*cf5a6c84SAndroid Build Coastguard Worker 	char dirname[128], tmpname[128], newname[128];
404*cf5a6c84SAndroid Build Coastguard Worker 	int type, l, writetype;
405*cf5a6c84SAndroid Build Coastguard Worker 	const char *str;
406*cf5a6c84SAndroid Build Coastguard Worker 	time_t now;
407*cf5a6c84SAndroid Build Coastguard Worker 	int use_timestamp = 1;
408*cf5a6c84SAndroid Build Coastguard Worker 	char *env;
409*cf5a6c84SAndroid Build Coastguard Worker 
410*cf5a6c84SAndroid Build Coastguard Worker 	dirname[0] = 0;
411*cf5a6c84SAndroid Build Coastguard Worker 	if (name && name[0]) {
412*cf5a6c84SAndroid Build Coastguard Worker 		struct stat st;
413*cf5a6c84SAndroid Build Coastguard Worker 		char *slash;
414*cf5a6c84SAndroid Build Coastguard Worker 
415*cf5a6c84SAndroid Build Coastguard Worker 		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
416*cf5a6c84SAndroid Build Coastguard Worker 			strcpy(dirname, name);
417*cf5a6c84SAndroid Build Coastguard Worker 			strcat(dirname, "/");
418*cf5a6c84SAndroid Build Coastguard Worker 			basename = conf_get_configname();
419*cf5a6c84SAndroid Build Coastguard Worker 		} else if ((slash = strrchr(name, '/'))) {
420*cf5a6c84SAndroid Build Coastguard Worker 			int size = slash - name + 1;
421*cf5a6c84SAndroid Build Coastguard Worker 			memcpy(dirname, name, size);
422*cf5a6c84SAndroid Build Coastguard Worker 			dirname[size] = 0;
423*cf5a6c84SAndroid Build Coastguard Worker 			if (slash[1])
424*cf5a6c84SAndroid Build Coastguard Worker 				basename = slash + 1;
425*cf5a6c84SAndroid Build Coastguard Worker 			else
426*cf5a6c84SAndroid Build Coastguard Worker 				basename = conf_get_configname();
427*cf5a6c84SAndroid Build Coastguard Worker 		} else
428*cf5a6c84SAndroid Build Coastguard Worker 			basename = name;
429*cf5a6c84SAndroid Build Coastguard Worker 	} else
430*cf5a6c84SAndroid Build Coastguard Worker 		basename = conf_get_configname();
431*cf5a6c84SAndroid Build Coastguard Worker 
432*cf5a6c84SAndroid Build Coastguard Worker 	sprintf(newname, "%s%s", dirname, basename);
433*cf5a6c84SAndroid Build Coastguard Worker 	env = getenv("KCONFIG_OVERWRITECONFIG");
434*cf5a6c84SAndroid Build Coastguard Worker 	if (!env || !*env) {
435*cf5a6c84SAndroid Build Coastguard Worker 		sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
436*cf5a6c84SAndroid Build Coastguard Worker 		out = fopen(tmpname, "w");
437*cf5a6c84SAndroid Build Coastguard Worker 	} else {
438*cf5a6c84SAndroid Build Coastguard Worker 		*tmpname = 0;
439*cf5a6c84SAndroid Build Coastguard Worker 		out = fopen(newname, "w");
440*cf5a6c84SAndroid Build Coastguard Worker 	}
441*cf5a6c84SAndroid Build Coastguard Worker 	if (!out)
442*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
443*cf5a6c84SAndroid Build Coastguard Worker 
444*cf5a6c84SAndroid Build Coastguard Worker 	sym = sym_lookup("KCONFIG_VERSION", 0);
445*cf5a6c84SAndroid Build Coastguard Worker 	sym_calc_value(sym);
446*cf5a6c84SAndroid Build Coastguard Worker 	time(&now);
447*cf5a6c84SAndroid Build Coastguard Worker 	env = getenv("KCONFIG_NOTIMESTAMP");
448*cf5a6c84SAndroid Build Coastguard Worker 	if (env && *env)
449*cf5a6c84SAndroid Build Coastguard Worker 		use_timestamp = 0;
450*cf5a6c84SAndroid Build Coastguard Worker 
451*cf5a6c84SAndroid Build Coastguard Worker 	fprintf(out, _("#\n"
452*cf5a6c84SAndroid Build Coastguard Worker 		       "# Automatically generated make config: don't edit\n"
453*cf5a6c84SAndroid Build Coastguard Worker 		       "# "PROJECT_NAME" version: %s\n"
454*cf5a6c84SAndroid Build Coastguard Worker 		       "%s%s"
455*cf5a6c84SAndroid Build Coastguard Worker 		       "#\n"),
456*cf5a6c84SAndroid Build Coastguard Worker 		     sym_get_string_value(sym),
457*cf5a6c84SAndroid Build Coastguard Worker 		     use_timestamp ? "# " : "",
458*cf5a6c84SAndroid Build Coastguard Worker 		     use_timestamp ? ctime(&now) : "");
459*cf5a6c84SAndroid Build Coastguard Worker 
460*cf5a6c84SAndroid Build Coastguard Worker 	if (!sym_change_count)
461*cf5a6c84SAndroid Build Coastguard Worker 		sym_clear_all_valid();
462*cf5a6c84SAndroid Build Coastguard Worker 
463*cf5a6c84SAndroid Build Coastguard Worker 	// Write out all symbols (even in closed sub-menus).
464*cf5a6c84SAndroid Build Coastguard Worker 	if (1) {
465*cf5a6c84SAndroid Build Coastguard Worker 		for (menu = rootmenu.list; menu; menu = next_menu(menu))
466*cf5a6c84SAndroid Build Coastguard Worker 			if (menu->sym) menu->sym->flags |= SYMBOL_FORCEWRITE;
467*cf5a6c84SAndroid Build Coastguard Worker 		writetype = SYMBOL_FORCEWRITE;
468*cf5a6c84SAndroid Build Coastguard Worker 
469*cf5a6c84SAndroid Build Coastguard Worker 	// Don't write  out symbols in closed menus.
470*cf5a6c84SAndroid Build Coastguard Worker 
471*cf5a6c84SAndroid Build Coastguard Worker 	} else writetype = SYMBOL_WRITE;
472*cf5a6c84SAndroid Build Coastguard Worker 
473*cf5a6c84SAndroid Build Coastguard Worker 
474*cf5a6c84SAndroid Build Coastguard Worker 	menu = rootmenu.list;
475*cf5a6c84SAndroid Build Coastguard Worker 	while (menu) {
476*cf5a6c84SAndroid Build Coastguard Worker 		sym = menu->sym;
477*cf5a6c84SAndroid Build Coastguard Worker 		if (!sym) {
478*cf5a6c84SAndroid Build Coastguard Worker 			if (!menu_is_visible(menu))
479*cf5a6c84SAndroid Build Coastguard Worker 				goto next;
480*cf5a6c84SAndroid Build Coastguard Worker 			str = menu_get_prompt(menu);
481*cf5a6c84SAndroid Build Coastguard Worker 			fprintf(out, "\n"
482*cf5a6c84SAndroid Build Coastguard Worker 				     "#\n"
483*cf5a6c84SAndroid Build Coastguard Worker 				     "# %s\n"
484*cf5a6c84SAndroid Build Coastguard Worker 				     "#\n", str);
485*cf5a6c84SAndroid Build Coastguard Worker 		} else if (!(sym->flags & SYMBOL_CHOICE)) {
486*cf5a6c84SAndroid Build Coastguard Worker 			sym_calc_value(sym);
487*cf5a6c84SAndroid Build Coastguard Worker 			if (!(sym->flags & writetype))
488*cf5a6c84SAndroid Build Coastguard Worker 				goto next;
489*cf5a6c84SAndroid Build Coastguard Worker 			sym->flags &= ~writetype;
490*cf5a6c84SAndroid Build Coastguard Worker 			type = sym->type;
491*cf5a6c84SAndroid Build Coastguard Worker 			if (type == S_TRISTATE) {
492*cf5a6c84SAndroid Build Coastguard Worker 				sym_calc_value(modules_sym);
493*cf5a6c84SAndroid Build Coastguard Worker 				if (modules_sym->curr.tri == no)
494*cf5a6c84SAndroid Build Coastguard Worker 					type = S_BOOLEAN;
495*cf5a6c84SAndroid Build Coastguard Worker 			}
496*cf5a6c84SAndroid Build Coastguard Worker 			switch (type) {
497*cf5a6c84SAndroid Build Coastguard Worker 			case S_BOOLEAN:
498*cf5a6c84SAndroid Build Coastguard Worker 			case S_TRISTATE:
499*cf5a6c84SAndroid Build Coastguard Worker 				switch (sym_get_tristate_value(sym)) {
500*cf5a6c84SAndroid Build Coastguard Worker 				case no:
501*cf5a6c84SAndroid Build Coastguard Worker 					fprintf(out, "# "CONFIG_PREFIX"%s is not set\n", sym->name);
502*cf5a6c84SAndroid Build Coastguard Worker 					break;
503*cf5a6c84SAndroid Build Coastguard Worker 				case mod:
504*cf5a6c84SAndroid Build Coastguard Worker 					fprintf(out, CONFIG_PREFIX"%s=m\n", sym->name);
505*cf5a6c84SAndroid Build Coastguard Worker 					break;
506*cf5a6c84SAndroid Build Coastguard Worker 				case yes:
507*cf5a6c84SAndroid Build Coastguard Worker 					fprintf(out, CONFIG_PREFIX"%s=y\n", sym->name);
508*cf5a6c84SAndroid Build Coastguard Worker 					break;
509*cf5a6c84SAndroid Build Coastguard Worker 				}
510*cf5a6c84SAndroid Build Coastguard Worker 				break;
511*cf5a6c84SAndroid Build Coastguard Worker 			case S_STRING:
512*cf5a6c84SAndroid Build Coastguard Worker 				str = sym_get_string_value(sym);
513*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out, CONFIG_PREFIX"%s=\"", sym->name);
514*cf5a6c84SAndroid Build Coastguard Worker 				while (1) {
515*cf5a6c84SAndroid Build Coastguard Worker 					l = strcspn(str, "\"\\");
516*cf5a6c84SAndroid Build Coastguard Worker 					if (l) {
517*cf5a6c84SAndroid Build Coastguard Worker 						fwrite(str, l, 1, out);
518*cf5a6c84SAndroid Build Coastguard Worker 						str += l;
519*cf5a6c84SAndroid Build Coastguard Worker 					}
520*cf5a6c84SAndroid Build Coastguard Worker 					if (!*str)
521*cf5a6c84SAndroid Build Coastguard Worker 						break;
522*cf5a6c84SAndroid Build Coastguard Worker 					fprintf(out, "\\%c", *str++);
523*cf5a6c84SAndroid Build Coastguard Worker 				}
524*cf5a6c84SAndroid Build Coastguard Worker 				fputs("\"\n", out);
525*cf5a6c84SAndroid Build Coastguard Worker 				break;
526*cf5a6c84SAndroid Build Coastguard Worker 			case S_HEX:
527*cf5a6c84SAndroid Build Coastguard Worker 				str = sym_get_string_value(sym);
528*cf5a6c84SAndroid Build Coastguard Worker 				if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
529*cf5a6c84SAndroid Build Coastguard Worker 					fprintf(out, CONFIG_PREFIX"%s=%s\n", sym->name, *str ? str : "0");
530*cf5a6c84SAndroid Build Coastguard Worker 					break;
531*cf5a6c84SAndroid Build Coastguard Worker 				}
532*cf5a6c84SAndroid Build Coastguard Worker 			case S_INT:
533*cf5a6c84SAndroid Build Coastguard Worker 				str = sym_get_string_value(sym);
534*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out, CONFIG_PREFIX"%s=%s\n", sym->name, *str ? str : "0");
535*cf5a6c84SAndroid Build Coastguard Worker 				break;
536*cf5a6c84SAndroid Build Coastguard Worker 			}
537*cf5a6c84SAndroid Build Coastguard Worker 		}
538*cf5a6c84SAndroid Build Coastguard Worker 
539*cf5a6c84SAndroid Build Coastguard Worker 	next:
540*cf5a6c84SAndroid Build Coastguard Worker 		if (writetype == SYMBOL_WRITE) {
541*cf5a6c84SAndroid Build Coastguard Worker 			if (menu->list) {
542*cf5a6c84SAndroid Build Coastguard Worker 				menu = menu->list;
543*cf5a6c84SAndroid Build Coastguard Worker 				continue;
544*cf5a6c84SAndroid Build Coastguard Worker 			}
545*cf5a6c84SAndroid Build Coastguard Worker 			if (menu->next)
546*cf5a6c84SAndroid Build Coastguard Worker 				menu = menu->next;
547*cf5a6c84SAndroid Build Coastguard Worker 			else while ((menu = menu->parent)) {
548*cf5a6c84SAndroid Build Coastguard Worker 				if (menu->next) {
549*cf5a6c84SAndroid Build Coastguard Worker 					menu = menu->next;
550*cf5a6c84SAndroid Build Coastguard Worker 					break;
551*cf5a6c84SAndroid Build Coastguard Worker 				}
552*cf5a6c84SAndroid Build Coastguard Worker 			}
553*cf5a6c84SAndroid Build Coastguard Worker 		} else
554*cf5a6c84SAndroid Build Coastguard Worker 			menu = next_menu(menu);
555*cf5a6c84SAndroid Build Coastguard Worker 	}
556*cf5a6c84SAndroid Build Coastguard Worker 	fclose(out);
557*cf5a6c84SAndroid Build Coastguard Worker 
558*cf5a6c84SAndroid Build Coastguard Worker 	if (*tmpname) {
559*cf5a6c84SAndroid Build Coastguard Worker 		strcat(dirname, basename);
560*cf5a6c84SAndroid Build Coastguard Worker 		strcat(dirname, ".old");
561*cf5a6c84SAndroid Build Coastguard Worker 		rename(newname, dirname);
562*cf5a6c84SAndroid Build Coastguard Worker 		if (rename(tmpname, newname))
563*cf5a6c84SAndroid Build Coastguard Worker 			return 1;
564*cf5a6c84SAndroid Build Coastguard Worker 	}
565*cf5a6c84SAndroid Build Coastguard Worker 
566*cf5a6c84SAndroid Build Coastguard Worker 	printf(_("#\n"
567*cf5a6c84SAndroid Build Coastguard Worker 		 "# configuration written to %s\n"
568*cf5a6c84SAndroid Build Coastguard Worker 		 "#\n"), newname);
569*cf5a6c84SAndroid Build Coastguard Worker 
570*cf5a6c84SAndroid Build Coastguard Worker 	sym_change_count = 0;
571*cf5a6c84SAndroid Build Coastguard Worker 
572*cf5a6c84SAndroid Build Coastguard Worker 	return 0;
573*cf5a6c84SAndroid Build Coastguard Worker }
574*cf5a6c84SAndroid Build Coastguard Worker 
conf_split_config(void)575*cf5a6c84SAndroid Build Coastguard Worker int conf_split_config(void)
576*cf5a6c84SAndroid Build Coastguard Worker {
577*cf5a6c84SAndroid Build Coastguard Worker 	char *name, path[128];
578*cf5a6c84SAndroid Build Coastguard Worker 	char *s, *d, c;
579*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym;
580*cf5a6c84SAndroid Build Coastguard Worker 	struct stat sb;
581*cf5a6c84SAndroid Build Coastguard Worker 	int res, i, fd;
582*cf5a6c84SAndroid Build Coastguard Worker 
583*cf5a6c84SAndroid Build Coastguard Worker 	name = getenv("KCONFIG_AUTOCONFIG");
584*cf5a6c84SAndroid Build Coastguard Worker 	if (!name)
585*cf5a6c84SAndroid Build Coastguard Worker 		name = "include/config/auto.conf";
586*cf5a6c84SAndroid Build Coastguard Worker 	conf_read_simple(name, S_DEF_AUTO);
587*cf5a6c84SAndroid Build Coastguard Worker 
588*cf5a6c84SAndroid Build Coastguard Worker 	if (chdir("include/config"))
589*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
590*cf5a6c84SAndroid Build Coastguard Worker 
591*cf5a6c84SAndroid Build Coastguard Worker 	res = 0;
592*cf5a6c84SAndroid Build Coastguard Worker 	for_all_symbols(i, sym) {
593*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(sym);
594*cf5a6c84SAndroid Build Coastguard Worker 		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
595*cf5a6c84SAndroid Build Coastguard Worker 			continue;
596*cf5a6c84SAndroid Build Coastguard Worker 		if (sym->flags & SYMBOL_WRITE) {
597*cf5a6c84SAndroid Build Coastguard Worker 			if (sym->flags & SYMBOL_DEF_AUTO) {
598*cf5a6c84SAndroid Build Coastguard Worker 				/*
599*cf5a6c84SAndroid Build Coastguard Worker 				 * symbol has old and new value,
600*cf5a6c84SAndroid Build Coastguard Worker 				 * so compare them...
601*cf5a6c84SAndroid Build Coastguard Worker 				 */
602*cf5a6c84SAndroid Build Coastguard Worker 				switch (sym->type) {
603*cf5a6c84SAndroid Build Coastguard Worker 				case S_BOOLEAN:
604*cf5a6c84SAndroid Build Coastguard Worker 				case S_TRISTATE:
605*cf5a6c84SAndroid Build Coastguard Worker 					if (sym_get_tristate_value(sym) ==
606*cf5a6c84SAndroid Build Coastguard Worker 					    sym->def[S_DEF_AUTO].tri)
607*cf5a6c84SAndroid Build Coastguard Worker 						continue;
608*cf5a6c84SAndroid Build Coastguard Worker 					break;
609*cf5a6c84SAndroid Build Coastguard Worker 				case S_STRING:
610*cf5a6c84SAndroid Build Coastguard Worker 				case S_HEX:
611*cf5a6c84SAndroid Build Coastguard Worker 				case S_INT:
612*cf5a6c84SAndroid Build Coastguard Worker 					if (!strcmp(sym_get_string_value(sym),
613*cf5a6c84SAndroid Build Coastguard Worker 						    sym->def[S_DEF_AUTO].val))
614*cf5a6c84SAndroid Build Coastguard Worker 						continue;
615*cf5a6c84SAndroid Build Coastguard Worker 					break;
616*cf5a6c84SAndroid Build Coastguard Worker 				default:
617*cf5a6c84SAndroid Build Coastguard Worker 					break;
618*cf5a6c84SAndroid Build Coastguard Worker 				}
619*cf5a6c84SAndroid Build Coastguard Worker 			} else {
620*cf5a6c84SAndroid Build Coastguard Worker 				/*
621*cf5a6c84SAndroid Build Coastguard Worker 				 * If there is no old value, only 'no' (unset)
622*cf5a6c84SAndroid Build Coastguard Worker 				 * is allowed as new value.
623*cf5a6c84SAndroid Build Coastguard Worker 				 */
624*cf5a6c84SAndroid Build Coastguard Worker 				switch (sym->type) {
625*cf5a6c84SAndroid Build Coastguard Worker 				case S_BOOLEAN:
626*cf5a6c84SAndroid Build Coastguard Worker 				case S_TRISTATE:
627*cf5a6c84SAndroid Build Coastguard Worker 					if (sym_get_tristate_value(sym) == no)
628*cf5a6c84SAndroid Build Coastguard Worker 						continue;
629*cf5a6c84SAndroid Build Coastguard Worker 					break;
630*cf5a6c84SAndroid Build Coastguard Worker 				default:
631*cf5a6c84SAndroid Build Coastguard Worker 					break;
632*cf5a6c84SAndroid Build Coastguard Worker 				}
633*cf5a6c84SAndroid Build Coastguard Worker 			}
634*cf5a6c84SAndroid Build Coastguard Worker 		} else if (!(sym->flags & SYMBOL_DEF_AUTO))
635*cf5a6c84SAndroid Build Coastguard Worker 			/* There is neither an old nor a new value. */
636*cf5a6c84SAndroid Build Coastguard Worker 			continue;
637*cf5a6c84SAndroid Build Coastguard Worker 		/* else
638*cf5a6c84SAndroid Build Coastguard Worker 		 *	There is an old value, but no new value ('no' (unset)
639*cf5a6c84SAndroid Build Coastguard Worker 		 *	isn't saved in auto.conf, so the old value is always
640*cf5a6c84SAndroid Build Coastguard Worker 		 *	different from 'no').
641*cf5a6c84SAndroid Build Coastguard Worker 		 */
642*cf5a6c84SAndroid Build Coastguard Worker 
643*cf5a6c84SAndroid Build Coastguard Worker 		/* Replace all '_' and append ".h" */
644*cf5a6c84SAndroid Build Coastguard Worker 		s = sym->name;
645*cf5a6c84SAndroid Build Coastguard Worker 		d = path;
646*cf5a6c84SAndroid Build Coastguard Worker 		while ((c = *s++)) {
647*cf5a6c84SAndroid Build Coastguard Worker 			c = tolower(c);
648*cf5a6c84SAndroid Build Coastguard Worker 			*d++ = (c == '_') ? '/' : c;
649*cf5a6c84SAndroid Build Coastguard Worker 		}
650*cf5a6c84SAndroid Build Coastguard Worker 		strcpy(d, ".h");
651*cf5a6c84SAndroid Build Coastguard Worker 
652*cf5a6c84SAndroid Build Coastguard Worker 		/* Assume directory path already exists. */
653*cf5a6c84SAndroid Build Coastguard Worker 		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
654*cf5a6c84SAndroid Build Coastguard Worker 		if (fd == -1) {
655*cf5a6c84SAndroid Build Coastguard Worker 			if (errno != ENOENT) {
656*cf5a6c84SAndroid Build Coastguard Worker 				res = 1;
657*cf5a6c84SAndroid Build Coastguard Worker 				break;
658*cf5a6c84SAndroid Build Coastguard Worker 			}
659*cf5a6c84SAndroid Build Coastguard Worker 			/*
660*cf5a6c84SAndroid Build Coastguard Worker 			 * Create directory components,
661*cf5a6c84SAndroid Build Coastguard Worker 			 * unless they exist already.
662*cf5a6c84SAndroid Build Coastguard Worker 			 */
663*cf5a6c84SAndroid Build Coastguard Worker 			d = path;
664*cf5a6c84SAndroid Build Coastguard Worker 			while ((d = strchr(d, '/'))) {
665*cf5a6c84SAndroid Build Coastguard Worker 				*d = 0;
666*cf5a6c84SAndroid Build Coastguard Worker 				if (stat(path, &sb) && mkdir(path, 0755)) {
667*cf5a6c84SAndroid Build Coastguard Worker 					res = 1;
668*cf5a6c84SAndroid Build Coastguard Worker 					goto out;
669*cf5a6c84SAndroid Build Coastguard Worker 				}
670*cf5a6c84SAndroid Build Coastguard Worker 				*d++ = '/';
671*cf5a6c84SAndroid Build Coastguard Worker 			}
672*cf5a6c84SAndroid Build Coastguard Worker 			/* Try it again. */
673*cf5a6c84SAndroid Build Coastguard Worker 			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
674*cf5a6c84SAndroid Build Coastguard Worker 			if (fd == -1) {
675*cf5a6c84SAndroid Build Coastguard Worker 				res = 1;
676*cf5a6c84SAndroid Build Coastguard Worker 				break;
677*cf5a6c84SAndroid Build Coastguard Worker 			}
678*cf5a6c84SAndroid Build Coastguard Worker 		}
679*cf5a6c84SAndroid Build Coastguard Worker 		close(fd);
680*cf5a6c84SAndroid Build Coastguard Worker 	}
681*cf5a6c84SAndroid Build Coastguard Worker out:
682*cf5a6c84SAndroid Build Coastguard Worker 	if (chdir("../.."))
683*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
684*cf5a6c84SAndroid Build Coastguard Worker 
685*cf5a6c84SAndroid Build Coastguard Worker 	return res;
686*cf5a6c84SAndroid Build Coastguard Worker }
687*cf5a6c84SAndroid Build Coastguard Worker 
conf_write_autoconf(void)688*cf5a6c84SAndroid Build Coastguard Worker int conf_write_autoconf(void)
689*cf5a6c84SAndroid Build Coastguard Worker {
690*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym;
691*cf5a6c84SAndroid Build Coastguard Worker 	const char *str;
692*cf5a6c84SAndroid Build Coastguard Worker 	char *name;
693*cf5a6c84SAndroid Build Coastguard Worker 	FILE *out, *out_h;
694*cf5a6c84SAndroid Build Coastguard Worker 	time_t now;
695*cf5a6c84SAndroid Build Coastguard Worker 	int i, l;
696*cf5a6c84SAndroid Build Coastguard Worker 
697*cf5a6c84SAndroid Build Coastguard Worker 	sym_clear_all_valid();
698*cf5a6c84SAndroid Build Coastguard Worker 
699*cf5a6c84SAndroid Build Coastguard Worker 	file_write_dep("include/config/auto.conf.cmd");
700*cf5a6c84SAndroid Build Coastguard Worker 
701*cf5a6c84SAndroid Build Coastguard Worker 	if (conf_split_config())
702*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
703*cf5a6c84SAndroid Build Coastguard Worker 
704*cf5a6c84SAndroid Build Coastguard Worker 	out = fopen(".tmpconfig", "w");
705*cf5a6c84SAndroid Build Coastguard Worker 	if (!out)
706*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
707*cf5a6c84SAndroid Build Coastguard Worker 
708*cf5a6c84SAndroid Build Coastguard Worker 	out_h = fopen(".tmpconfig.h", "w");
709*cf5a6c84SAndroid Build Coastguard Worker 	if (!out_h) {
710*cf5a6c84SAndroid Build Coastguard Worker 		fclose(out);
711*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
712*cf5a6c84SAndroid Build Coastguard Worker 	}
713*cf5a6c84SAndroid Build Coastguard Worker 
714*cf5a6c84SAndroid Build Coastguard Worker 	sym = sym_lookup("KCONFIG_VERSION", 0);
715*cf5a6c84SAndroid Build Coastguard Worker 	sym_calc_value(sym);
716*cf5a6c84SAndroid Build Coastguard Worker 	time(&now);
717*cf5a6c84SAndroid Build Coastguard Worker 	fprintf(out, "#\n"
718*cf5a6c84SAndroid Build Coastguard Worker 		     "# Automatically generated make config: don't edit\n"
719*cf5a6c84SAndroid Build Coastguard Worker 		     "# "PROJECT_NAME" version: %s\n"
720*cf5a6c84SAndroid Build Coastguard Worker 		     "# %s"
721*cf5a6c84SAndroid Build Coastguard Worker 		     "#\n",
722*cf5a6c84SAndroid Build Coastguard Worker 		     sym_get_string_value(sym), ctime(&now));
723*cf5a6c84SAndroid Build Coastguard Worker 	fprintf(out_h, "/*\n"
724*cf5a6c84SAndroid Build Coastguard Worker 		       " * Automatically generated C config: don't edit\n"
725*cf5a6c84SAndroid Build Coastguard Worker 		       " * "PROJECT_NAME" version: %s\n"
726*cf5a6c84SAndroid Build Coastguard Worker 		       " * %s"
727*cf5a6c84SAndroid Build Coastguard Worker 		       " */\n"
728*cf5a6c84SAndroid Build Coastguard Worker 		       // "#define AUTOCONF_INCLUDED\n"
729*cf5a6c84SAndroid Build Coastguard Worker 		       , sym_get_string_value(sym), ctime(&now));
730*cf5a6c84SAndroid Build Coastguard Worker 
731*cf5a6c84SAndroid Build Coastguard Worker 	for_all_symbols(i, sym) {
732*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(sym);
733*cf5a6c84SAndroid Build Coastguard Worker 		if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
734*cf5a6c84SAndroid Build Coastguard Worker 			continue;
735*cf5a6c84SAndroid Build Coastguard Worker 		switch (sym->type) {
736*cf5a6c84SAndroid Build Coastguard Worker 		case S_BOOLEAN:
737*cf5a6c84SAndroid Build Coastguard Worker 		case S_TRISTATE:
738*cf5a6c84SAndroid Build Coastguard Worker 			switch (sym_get_tristate_value(sym)) {
739*cf5a6c84SAndroid Build Coastguard Worker 			case no:
740*cf5a6c84SAndroid Build Coastguard Worker 				break;
741*cf5a6c84SAndroid Build Coastguard Worker 			case mod:
742*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out, CONFIG_PREFIX"%s=m\n", sym->name);
743*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
744*cf5a6c84SAndroid Build Coastguard Worker 				break;
745*cf5a6c84SAndroid Build Coastguard Worker 			case yes:
746*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out, CONFIG_PREFIX"%s=y\n", sym->name);
747*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out_h, "#define "CONFIG_PREFIX"%s 1\n", sym->name);
748*cf5a6c84SAndroid Build Coastguard Worker 				break;
749*cf5a6c84SAndroid Build Coastguard Worker 			}
750*cf5a6c84SAndroid Build Coastguard Worker 			break;
751*cf5a6c84SAndroid Build Coastguard Worker 		case S_STRING:
752*cf5a6c84SAndroid Build Coastguard Worker 			str = sym_get_string_value(sym);
753*cf5a6c84SAndroid Build Coastguard Worker 			fprintf(out, CONFIG_PREFIX"%s=\"", sym->name);
754*cf5a6c84SAndroid Build Coastguard Worker 			fprintf(out_h, "#define "CONFIG_PREFIX"%s \"", sym->name);
755*cf5a6c84SAndroid Build Coastguard Worker 			while (1) {
756*cf5a6c84SAndroid Build Coastguard Worker 				l = strcspn(str, "\"\\");
757*cf5a6c84SAndroid Build Coastguard Worker 				if (l) {
758*cf5a6c84SAndroid Build Coastguard Worker 					fwrite(str, l, 1, out);
759*cf5a6c84SAndroid Build Coastguard Worker 					fwrite(str, l, 1, out_h);
760*cf5a6c84SAndroid Build Coastguard Worker 					str += l;
761*cf5a6c84SAndroid Build Coastguard Worker 				}
762*cf5a6c84SAndroid Build Coastguard Worker 				if (!*str)
763*cf5a6c84SAndroid Build Coastguard Worker 					break;
764*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out, "\\%c", *str);
765*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out_h, "\\%c", *str);
766*cf5a6c84SAndroid Build Coastguard Worker 				str++;
767*cf5a6c84SAndroid Build Coastguard Worker 			}
768*cf5a6c84SAndroid Build Coastguard Worker 			fputs("\"\n", out);
769*cf5a6c84SAndroid Build Coastguard Worker 			fputs("\"\n", out_h);
770*cf5a6c84SAndroid Build Coastguard Worker 			break;
771*cf5a6c84SAndroid Build Coastguard Worker 		case S_HEX:
772*cf5a6c84SAndroid Build Coastguard Worker 			str = sym_get_string_value(sym);
773*cf5a6c84SAndroid Build Coastguard Worker 			if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
774*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out, CONFIG_PREFIX"%s=%s\n", sym->name, str);
775*cf5a6c84SAndroid Build Coastguard Worker 				fprintf(out_h, "#define "CONFIG_PREFIX"%s 0x%s\n", sym->name, str);
776*cf5a6c84SAndroid Build Coastguard Worker 				break;
777*cf5a6c84SAndroid Build Coastguard Worker 			}
778*cf5a6c84SAndroid Build Coastguard Worker 		case S_INT:
779*cf5a6c84SAndroid Build Coastguard Worker 			str = sym_get_string_value(sym);
780*cf5a6c84SAndroid Build Coastguard Worker 			fprintf(out, CONFIG_PREFIX"%s=%s\n", sym->name, str);
781*cf5a6c84SAndroid Build Coastguard Worker 			fprintf(out_h, "#define "CONFIG_PREFIX"%s %s\n", sym->name, str);
782*cf5a6c84SAndroid Build Coastguard Worker 			break;
783*cf5a6c84SAndroid Build Coastguard Worker 		default:
784*cf5a6c84SAndroid Build Coastguard Worker 			break;
785*cf5a6c84SAndroid Build Coastguard Worker 		}
786*cf5a6c84SAndroid Build Coastguard Worker 	}
787*cf5a6c84SAndroid Build Coastguard Worker 	fclose(out);
788*cf5a6c84SAndroid Build Coastguard Worker 	fclose(out_h);
789*cf5a6c84SAndroid Build Coastguard Worker 
790*cf5a6c84SAndroid Build Coastguard Worker 	name = getenv("KCONFIG_AUTOHEADER");
791*cf5a6c84SAndroid Build Coastguard Worker 	if (!name)
792*cf5a6c84SAndroid Build Coastguard Worker 		name = "include/linux/autoconf.h";
793*cf5a6c84SAndroid Build Coastguard Worker 	if (rename(".tmpconfig.h", name))
794*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
795*cf5a6c84SAndroid Build Coastguard Worker 	name = getenv("KCONFIG_AUTOCONFIG");
796*cf5a6c84SAndroid Build Coastguard Worker 	if (!name)
797*cf5a6c84SAndroid Build Coastguard Worker 		name = "include/config/auto.conf";
798*cf5a6c84SAndroid Build Coastguard Worker 	/*
799*cf5a6c84SAndroid Build Coastguard Worker 	 * This must be the last step, kbuild has a dependency on auto.conf
800*cf5a6c84SAndroid Build Coastguard Worker 	 * and this marks the successful completion of the previous steps.
801*cf5a6c84SAndroid Build Coastguard Worker 	 */
802*cf5a6c84SAndroid Build Coastguard Worker 	if (rename(".tmpconfig", name))
803*cf5a6c84SAndroid Build Coastguard Worker 		return 1;
804*cf5a6c84SAndroid Build Coastguard Worker 
805*cf5a6c84SAndroid Build Coastguard Worker 	return 0;
806*cf5a6c84SAndroid Build Coastguard Worker }
807