xref: /OK3568_Linux_fs/buildroot/support/kconfig/symbol.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3*4882a593Smuzhiyun  * Released under the terms of the GNU GPL v2.0.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <ctype.h>
7*4882a593Smuzhiyun #include <stdlib.h>
8*4882a593Smuzhiyun #include <string.h>
9*4882a593Smuzhiyun #include <regex.h>
10*4882a593Smuzhiyun #include <sys/utsname.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include "lkc.h"
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun struct symbol symbol_yes = {
15*4882a593Smuzhiyun 	.name = "y",
16*4882a593Smuzhiyun 	.curr = { "y", yes },
17*4882a593Smuzhiyun 	.flags = SYMBOL_CONST|SYMBOL_VALID,
18*4882a593Smuzhiyun }, symbol_mod = {
19*4882a593Smuzhiyun 	.name = "m",
20*4882a593Smuzhiyun 	.curr = { "m", mod },
21*4882a593Smuzhiyun 	.flags = SYMBOL_CONST|SYMBOL_VALID,
22*4882a593Smuzhiyun }, symbol_no = {
23*4882a593Smuzhiyun 	.name = "n",
24*4882a593Smuzhiyun 	.curr = { "n", no },
25*4882a593Smuzhiyun 	.flags = SYMBOL_CONST|SYMBOL_VALID,
26*4882a593Smuzhiyun }, symbol_empty = {
27*4882a593Smuzhiyun 	.name = "",
28*4882a593Smuzhiyun 	.curr = { "", no },
29*4882a593Smuzhiyun 	.flags = SYMBOL_VALID,
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun struct symbol *sym_defconfig_list;
33*4882a593Smuzhiyun struct symbol *modules_sym;
34*4882a593Smuzhiyun tristate modules_val;
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun struct expr *sym_env_list;
37*4882a593Smuzhiyun 
sym_add_default(struct symbol * sym,const char * def)38*4882a593Smuzhiyun static void sym_add_default(struct symbol *sym, const char *def)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun 	struct property *prop = prop_alloc(P_DEFAULT, sym);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun 
sym_init(void)45*4882a593Smuzhiyun void sym_init(void)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	struct symbol *sym;
48*4882a593Smuzhiyun 	struct utsname uts;
49*4882a593Smuzhiyun 	static bool inited = false;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	if (inited)
52*4882a593Smuzhiyun 		return;
53*4882a593Smuzhiyun 	inited = true;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	uname(&uts);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	sym = sym_lookup("UNAME_RELEASE", 0);
58*4882a593Smuzhiyun 	sym->type = S_STRING;
59*4882a593Smuzhiyun 	sym->flags |= SYMBOL_AUTO;
60*4882a593Smuzhiyun 	sym_add_default(sym, uts.release);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
sym_get_type(struct symbol * sym)63*4882a593Smuzhiyun enum symbol_type sym_get_type(struct symbol *sym)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	enum symbol_type type = sym->type;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	if (type == S_TRISTATE) {
68*4882a593Smuzhiyun 		if (sym_is_choice_value(sym) && sym->visible == yes)
69*4882a593Smuzhiyun 			type = S_BOOLEAN;
70*4882a593Smuzhiyun 		else if (modules_val == no)
71*4882a593Smuzhiyun 			type = S_BOOLEAN;
72*4882a593Smuzhiyun 	}
73*4882a593Smuzhiyun 	return type;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
sym_type_name(enum symbol_type type)76*4882a593Smuzhiyun const char *sym_type_name(enum symbol_type type)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	switch (type) {
79*4882a593Smuzhiyun 	case S_BOOLEAN:
80*4882a593Smuzhiyun 		return "bool";
81*4882a593Smuzhiyun 	case S_TRISTATE:
82*4882a593Smuzhiyun 		return "tristate";
83*4882a593Smuzhiyun 	case S_INT:
84*4882a593Smuzhiyun 		return "integer";
85*4882a593Smuzhiyun 	case S_HEX:
86*4882a593Smuzhiyun 		return "hex";
87*4882a593Smuzhiyun 	case S_STRING:
88*4882a593Smuzhiyun 		return "string";
89*4882a593Smuzhiyun 	case S_UNKNOWN:
90*4882a593Smuzhiyun 		return "unknown";
91*4882a593Smuzhiyun 	case S_OTHER:
92*4882a593Smuzhiyun 		break;
93*4882a593Smuzhiyun 	}
94*4882a593Smuzhiyun 	return "???";
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
sym_get_choice_prop(struct symbol * sym)97*4882a593Smuzhiyun struct property *sym_get_choice_prop(struct symbol *sym)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	struct property *prop;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	for_all_choices(sym, prop)
102*4882a593Smuzhiyun 		return prop;
103*4882a593Smuzhiyun 	return NULL;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
sym_get_env_prop(struct symbol * sym)106*4882a593Smuzhiyun struct property *sym_get_env_prop(struct symbol *sym)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	struct property *prop;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	for_all_properties(sym, prop, P_ENV)
111*4882a593Smuzhiyun 		return prop;
112*4882a593Smuzhiyun 	return NULL;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
sym_get_default_prop(struct symbol * sym)115*4882a593Smuzhiyun static struct property *sym_get_default_prop(struct symbol *sym)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	struct property *prop;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	for_all_defaults(sym, prop) {
120*4882a593Smuzhiyun 		prop->visible.tri = expr_calc_value(prop->visible.expr);
121*4882a593Smuzhiyun 		if (prop->visible.tri != no)
122*4882a593Smuzhiyun 			return prop;
123*4882a593Smuzhiyun 	}
124*4882a593Smuzhiyun 	return NULL;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
sym_get_range_prop(struct symbol * sym)127*4882a593Smuzhiyun static struct property *sym_get_range_prop(struct symbol *sym)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	struct property *prop;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	for_all_properties(sym, prop, P_RANGE) {
132*4882a593Smuzhiyun 		prop->visible.tri = expr_calc_value(prop->visible.expr);
133*4882a593Smuzhiyun 		if (prop->visible.tri != no)
134*4882a593Smuzhiyun 			return prop;
135*4882a593Smuzhiyun 	}
136*4882a593Smuzhiyun 	return NULL;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
sym_get_range_val(struct symbol * sym,int base)139*4882a593Smuzhiyun static long long sym_get_range_val(struct symbol *sym, int base)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun 	sym_calc_value(sym);
142*4882a593Smuzhiyun 	switch (sym->type) {
143*4882a593Smuzhiyun 	case S_INT:
144*4882a593Smuzhiyun 		base = 10;
145*4882a593Smuzhiyun 		break;
146*4882a593Smuzhiyun 	case S_HEX:
147*4882a593Smuzhiyun 		base = 16;
148*4882a593Smuzhiyun 		break;
149*4882a593Smuzhiyun 	default:
150*4882a593Smuzhiyun 		break;
151*4882a593Smuzhiyun 	}
152*4882a593Smuzhiyun 	return strtoll(sym->curr.val, NULL, base);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
sym_validate_range(struct symbol * sym)155*4882a593Smuzhiyun static void sym_validate_range(struct symbol *sym)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	struct property *prop;
158*4882a593Smuzhiyun 	int base;
159*4882a593Smuzhiyun 	long long val, val2;
160*4882a593Smuzhiyun 	char str[64];
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	switch (sym->type) {
163*4882a593Smuzhiyun 	case S_INT:
164*4882a593Smuzhiyun 		base = 10;
165*4882a593Smuzhiyun 		break;
166*4882a593Smuzhiyun 	case S_HEX:
167*4882a593Smuzhiyun 		base = 16;
168*4882a593Smuzhiyun 		break;
169*4882a593Smuzhiyun 	default:
170*4882a593Smuzhiyun 		return;
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 	prop = sym_get_range_prop(sym);
173*4882a593Smuzhiyun 	if (!prop)
174*4882a593Smuzhiyun 		return;
175*4882a593Smuzhiyun 	val = strtoll(sym->curr.val, NULL, base);
176*4882a593Smuzhiyun 	val2 = sym_get_range_val(prop->expr->left.sym, base);
177*4882a593Smuzhiyun 	if (val >= val2) {
178*4882a593Smuzhiyun 		val2 = sym_get_range_val(prop->expr->right.sym, base);
179*4882a593Smuzhiyun 		if (val <= val2)
180*4882a593Smuzhiyun 			return;
181*4882a593Smuzhiyun 	}
182*4882a593Smuzhiyun 	if (sym->type == S_INT)
183*4882a593Smuzhiyun 		sprintf(str, "%lld", val2);
184*4882a593Smuzhiyun 	else
185*4882a593Smuzhiyun 		sprintf(str, "0x%llx", val2);
186*4882a593Smuzhiyun 	sym->curr.val = xstrdup(str);
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
sym_set_changed(struct symbol * sym)189*4882a593Smuzhiyun static void sym_set_changed(struct symbol *sym)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	struct property *prop;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	sym->flags |= SYMBOL_CHANGED;
194*4882a593Smuzhiyun 	for (prop = sym->prop; prop; prop = prop->next) {
195*4882a593Smuzhiyun 		if (prop->menu)
196*4882a593Smuzhiyun 			prop->menu->flags |= MENU_CHANGED;
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
sym_set_all_changed(void)200*4882a593Smuzhiyun static void sym_set_all_changed(void)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	struct symbol *sym;
203*4882a593Smuzhiyun 	int i;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	for_all_symbols(i, sym)
206*4882a593Smuzhiyun 		sym_set_changed(sym);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
sym_calc_visibility(struct symbol * sym)209*4882a593Smuzhiyun static void sym_calc_visibility(struct symbol *sym)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	struct property *prop;
212*4882a593Smuzhiyun 	struct symbol *choice_sym = NULL;
213*4882a593Smuzhiyun 	tristate tri;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	/* any prompt visible? */
216*4882a593Smuzhiyun 	tri = no;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	if (sym_is_choice_value(sym))
219*4882a593Smuzhiyun 		choice_sym = prop_get_symbol(sym_get_choice_prop(sym));
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	for_all_prompts(sym, prop) {
222*4882a593Smuzhiyun 		prop->visible.tri = expr_calc_value(prop->visible.expr);
223*4882a593Smuzhiyun 		/*
224*4882a593Smuzhiyun 		 * Tristate choice_values with visibility 'mod' are
225*4882a593Smuzhiyun 		 * not visible if the corresponding choice's value is
226*4882a593Smuzhiyun 		 * 'yes'.
227*4882a593Smuzhiyun 		 */
228*4882a593Smuzhiyun 		if (choice_sym && sym->type == S_TRISTATE &&
229*4882a593Smuzhiyun 		    prop->visible.tri == mod && choice_sym->curr.tri == yes)
230*4882a593Smuzhiyun 			prop->visible.tri = no;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 		tri = EXPR_OR(tri, prop->visible.tri);
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun 	if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
235*4882a593Smuzhiyun 		tri = yes;
236*4882a593Smuzhiyun 	if (sym->visible != tri) {
237*4882a593Smuzhiyun 		sym->visible = tri;
238*4882a593Smuzhiyun 		sym_set_changed(sym);
239*4882a593Smuzhiyun 	}
240*4882a593Smuzhiyun 	if (sym_is_choice_value(sym))
241*4882a593Smuzhiyun 		return;
242*4882a593Smuzhiyun 	/* defaulting to "yes" if no explicit "depends on" are given */
243*4882a593Smuzhiyun 	tri = yes;
244*4882a593Smuzhiyun 	if (sym->dir_dep.expr)
245*4882a593Smuzhiyun 		tri = expr_calc_value(sym->dir_dep.expr);
246*4882a593Smuzhiyun 	if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
247*4882a593Smuzhiyun 		tri = yes;
248*4882a593Smuzhiyun 	if (sym->dir_dep.tri != tri) {
249*4882a593Smuzhiyun 		sym->dir_dep.tri = tri;
250*4882a593Smuzhiyun 		sym_set_changed(sym);
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 	tri = no;
253*4882a593Smuzhiyun 	if (sym->rev_dep.expr)
254*4882a593Smuzhiyun 		tri = expr_calc_value(sym->rev_dep.expr);
255*4882a593Smuzhiyun 	if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
256*4882a593Smuzhiyun 		tri = yes;
257*4882a593Smuzhiyun 	if (sym->rev_dep.tri != tri) {
258*4882a593Smuzhiyun 		sym->rev_dep.tri = tri;
259*4882a593Smuzhiyun 		sym_set_changed(sym);
260*4882a593Smuzhiyun 	}
261*4882a593Smuzhiyun 	tri = no;
262*4882a593Smuzhiyun 	if (sym->implied.expr && sym->dir_dep.tri != no)
263*4882a593Smuzhiyun 		tri = expr_calc_value(sym->implied.expr);
264*4882a593Smuzhiyun 	if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
265*4882a593Smuzhiyun 		tri = yes;
266*4882a593Smuzhiyun 	if (sym->implied.tri != tri) {
267*4882a593Smuzhiyun 		sym->implied.tri = tri;
268*4882a593Smuzhiyun 		sym_set_changed(sym);
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun /*
273*4882a593Smuzhiyun  * Find the default symbol for a choice.
274*4882a593Smuzhiyun  * First try the default values for the choice symbol
275*4882a593Smuzhiyun  * Next locate the first visible choice value
276*4882a593Smuzhiyun  * Return NULL if none was found
277*4882a593Smuzhiyun  */
sym_choice_default(struct symbol * sym)278*4882a593Smuzhiyun struct symbol *sym_choice_default(struct symbol *sym)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	struct symbol *def_sym;
281*4882a593Smuzhiyun 	struct property *prop;
282*4882a593Smuzhiyun 	struct expr *e;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	/* any of the defaults visible? */
285*4882a593Smuzhiyun 	for_all_defaults(sym, prop) {
286*4882a593Smuzhiyun 		prop->visible.tri = expr_calc_value(prop->visible.expr);
287*4882a593Smuzhiyun 		if (prop->visible.tri == no)
288*4882a593Smuzhiyun 			continue;
289*4882a593Smuzhiyun 		def_sym = prop_get_symbol(prop);
290*4882a593Smuzhiyun 		if (def_sym->visible != no)
291*4882a593Smuzhiyun 			return def_sym;
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	/* just get the first visible value */
295*4882a593Smuzhiyun 	prop = sym_get_choice_prop(sym);
296*4882a593Smuzhiyun 	expr_list_for_each_sym(prop->expr, e, def_sym)
297*4882a593Smuzhiyun 		if (def_sym->visible != no)
298*4882a593Smuzhiyun 			return def_sym;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	/* failed to locate any defaults */
301*4882a593Smuzhiyun 	return NULL;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun 
sym_calc_choice(struct symbol * sym)304*4882a593Smuzhiyun static struct symbol *sym_calc_choice(struct symbol *sym)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun 	struct symbol *def_sym;
307*4882a593Smuzhiyun 	struct property *prop;
308*4882a593Smuzhiyun 	struct expr *e;
309*4882a593Smuzhiyun 	int flags;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	/* first calculate all choice values' visibilities */
312*4882a593Smuzhiyun 	flags = sym->flags;
313*4882a593Smuzhiyun 	prop = sym_get_choice_prop(sym);
314*4882a593Smuzhiyun 	expr_list_for_each_sym(prop->expr, e, def_sym) {
315*4882a593Smuzhiyun 		sym_calc_visibility(def_sym);
316*4882a593Smuzhiyun 		if (def_sym->visible != no)
317*4882a593Smuzhiyun 			flags &= def_sym->flags;
318*4882a593Smuzhiyun 	}
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	sym->flags &= flags | ~SYMBOL_DEF_USER;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	/* is the user choice visible? */
323*4882a593Smuzhiyun 	def_sym = sym->def[S_DEF_USER].val;
324*4882a593Smuzhiyun 	if (def_sym && def_sym->visible != no)
325*4882a593Smuzhiyun 		return def_sym;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	def_sym = sym_choice_default(sym);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	if (def_sym == NULL)
330*4882a593Smuzhiyun 		/* no choice? reset tristate value */
331*4882a593Smuzhiyun 		sym->curr.tri = no;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	return def_sym;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
sym_warn_unmet_dep(struct symbol * sym)336*4882a593Smuzhiyun static void sym_warn_unmet_dep(struct symbol *sym)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	struct gstr gs = str_new();
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	str_printf(&gs,
341*4882a593Smuzhiyun 		   "\nWARNING: unmet direct dependencies detected for %s\n",
342*4882a593Smuzhiyun 		   sym->name);
343*4882a593Smuzhiyun 	str_printf(&gs,
344*4882a593Smuzhiyun 		   "  Depends on [%c]: ",
345*4882a593Smuzhiyun 		   sym->dir_dep.tri == mod ? 'm' : 'n');
346*4882a593Smuzhiyun 	expr_gstr_print(sym->dir_dep.expr, &gs);
347*4882a593Smuzhiyun 	str_printf(&gs, "\n");
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	expr_gstr_print_revdep(sym->rev_dep.expr, &gs, yes,
350*4882a593Smuzhiyun 			       "  Selected by [y]:\n");
351*4882a593Smuzhiyun 	expr_gstr_print_revdep(sym->rev_dep.expr, &gs, mod,
352*4882a593Smuzhiyun 			       "  Selected by [m]:\n");
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	fputs(str_get(&gs), stderr);
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
sym_calc_value(struct symbol * sym)357*4882a593Smuzhiyun void sym_calc_value(struct symbol *sym)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	struct symbol_value newval, oldval;
360*4882a593Smuzhiyun 	struct property *prop;
361*4882a593Smuzhiyun 	struct expr *e;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	if (!sym)
364*4882a593Smuzhiyun 		return;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	if (sym->flags & SYMBOL_VALID)
367*4882a593Smuzhiyun 		return;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	if (sym_is_choice_value(sym) &&
370*4882a593Smuzhiyun 	    sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {
371*4882a593Smuzhiyun 		sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;
372*4882a593Smuzhiyun 		prop = sym_get_choice_prop(sym);
373*4882a593Smuzhiyun 		sym_calc_value(prop_get_symbol(prop));
374*4882a593Smuzhiyun 	}
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	sym->flags |= SYMBOL_VALID;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	oldval = sym->curr;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	switch (sym->type) {
381*4882a593Smuzhiyun 	case S_INT:
382*4882a593Smuzhiyun 	case S_HEX:
383*4882a593Smuzhiyun 	case S_STRING:
384*4882a593Smuzhiyun 		newval = symbol_empty.curr;
385*4882a593Smuzhiyun 		break;
386*4882a593Smuzhiyun 	case S_BOOLEAN:
387*4882a593Smuzhiyun 	case S_TRISTATE:
388*4882a593Smuzhiyun 		newval = symbol_no.curr;
389*4882a593Smuzhiyun 		break;
390*4882a593Smuzhiyun 	default:
391*4882a593Smuzhiyun 		sym->curr.val = sym->name;
392*4882a593Smuzhiyun 		sym->curr.tri = no;
393*4882a593Smuzhiyun 		return;
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 	sym->flags &= ~SYMBOL_WRITE;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	sym_calc_visibility(sym);
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	if (sym->visible != no)
400*4882a593Smuzhiyun 		sym->flags |= SYMBOL_WRITE;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	/* set default if recursively called */
403*4882a593Smuzhiyun 	sym->curr = newval;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	switch (sym_get_type(sym)) {
406*4882a593Smuzhiyun 	case S_BOOLEAN:
407*4882a593Smuzhiyun 	case S_TRISTATE:
408*4882a593Smuzhiyun 		if (sym_is_choice_value(sym) && sym->visible == yes) {
409*4882a593Smuzhiyun 			prop = sym_get_choice_prop(sym);
410*4882a593Smuzhiyun 			newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
411*4882a593Smuzhiyun 		} else {
412*4882a593Smuzhiyun 			if (sym->visible != no) {
413*4882a593Smuzhiyun 				/* if the symbol is visible use the user value
414*4882a593Smuzhiyun 				 * if available, otherwise try the default value
415*4882a593Smuzhiyun 				 */
416*4882a593Smuzhiyun 				if (sym_has_value(sym)) {
417*4882a593Smuzhiyun 					newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
418*4882a593Smuzhiyun 							      sym->visible);
419*4882a593Smuzhiyun 					goto calc_newval;
420*4882a593Smuzhiyun 				}
421*4882a593Smuzhiyun 			}
422*4882a593Smuzhiyun 			if (sym->rev_dep.tri != no)
423*4882a593Smuzhiyun 				sym->flags |= SYMBOL_WRITE;
424*4882a593Smuzhiyun 			if (!sym_is_choice(sym)) {
425*4882a593Smuzhiyun 				prop = sym_get_default_prop(sym);
426*4882a593Smuzhiyun 				if (prop) {
427*4882a593Smuzhiyun 					newval.tri = EXPR_AND(expr_calc_value(prop->expr),
428*4882a593Smuzhiyun 							      prop->visible.tri);
429*4882a593Smuzhiyun 					if (newval.tri != no)
430*4882a593Smuzhiyun 						sym->flags |= SYMBOL_WRITE;
431*4882a593Smuzhiyun 				}
432*4882a593Smuzhiyun 				if (sym->implied.tri != no) {
433*4882a593Smuzhiyun 					sym->flags |= SYMBOL_WRITE;
434*4882a593Smuzhiyun 					newval.tri = EXPR_OR(newval.tri, sym->implied.tri);
435*4882a593Smuzhiyun 				}
436*4882a593Smuzhiyun 			}
437*4882a593Smuzhiyun 		calc_newval:
438*4882a593Smuzhiyun 			if (sym->dir_dep.tri < sym->rev_dep.tri)
439*4882a593Smuzhiyun 				sym_warn_unmet_dep(sym);
440*4882a593Smuzhiyun 			newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
441*4882a593Smuzhiyun 		}
442*4882a593Smuzhiyun 		if (newval.tri == mod &&
443*4882a593Smuzhiyun 		    (sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes))
444*4882a593Smuzhiyun 			newval.tri = yes;
445*4882a593Smuzhiyun 		break;
446*4882a593Smuzhiyun 	case S_STRING:
447*4882a593Smuzhiyun 	case S_HEX:
448*4882a593Smuzhiyun 	case S_INT:
449*4882a593Smuzhiyun 		if (sym->visible != no && sym_has_value(sym)) {
450*4882a593Smuzhiyun 			newval.val = sym->def[S_DEF_USER].val;
451*4882a593Smuzhiyun 			break;
452*4882a593Smuzhiyun 		}
453*4882a593Smuzhiyun 		prop = sym_get_default_prop(sym);
454*4882a593Smuzhiyun 		if (prop) {
455*4882a593Smuzhiyun 			struct symbol *ds = prop_get_symbol(prop);
456*4882a593Smuzhiyun 			if (ds) {
457*4882a593Smuzhiyun 				sym->flags |= SYMBOL_WRITE;
458*4882a593Smuzhiyun 				sym_calc_value(ds);
459*4882a593Smuzhiyun 				newval.val = ds->curr.val;
460*4882a593Smuzhiyun 			}
461*4882a593Smuzhiyun 		}
462*4882a593Smuzhiyun 		break;
463*4882a593Smuzhiyun 	default:
464*4882a593Smuzhiyun 		;
465*4882a593Smuzhiyun 	}
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	sym->curr = newval;
468*4882a593Smuzhiyun 	if (sym_is_choice(sym) && newval.tri == yes)
469*4882a593Smuzhiyun 		sym->curr.val = sym_calc_choice(sym);
470*4882a593Smuzhiyun 	sym_validate_range(sym);
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
473*4882a593Smuzhiyun 		sym_set_changed(sym);
474*4882a593Smuzhiyun 		if (modules_sym == sym) {
475*4882a593Smuzhiyun 			sym_set_all_changed();
476*4882a593Smuzhiyun 			modules_val = modules_sym->curr.tri;
477*4882a593Smuzhiyun 		}
478*4882a593Smuzhiyun 	}
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	if (sym_is_choice(sym)) {
481*4882a593Smuzhiyun 		struct symbol *choice_sym;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 		prop = sym_get_choice_prop(sym);
484*4882a593Smuzhiyun 		expr_list_for_each_sym(prop->expr, e, choice_sym) {
485*4882a593Smuzhiyun 			if ((sym->flags & SYMBOL_WRITE) &&
486*4882a593Smuzhiyun 			    choice_sym->visible != no)
487*4882a593Smuzhiyun 				choice_sym->flags |= SYMBOL_WRITE;
488*4882a593Smuzhiyun 			if (sym->flags & SYMBOL_CHANGED)
489*4882a593Smuzhiyun 				sym_set_changed(choice_sym);
490*4882a593Smuzhiyun 		}
491*4882a593Smuzhiyun 	}
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	if (sym->flags & SYMBOL_AUTO)
494*4882a593Smuzhiyun 		sym->flags &= ~SYMBOL_WRITE;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
497*4882a593Smuzhiyun 		set_all_choice_values(sym);
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun 
sym_clear_all_valid(void)500*4882a593Smuzhiyun void sym_clear_all_valid(void)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun 	struct symbol *sym;
503*4882a593Smuzhiyun 	int i;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	for_all_symbols(i, sym)
506*4882a593Smuzhiyun 		sym->flags &= ~SYMBOL_VALID;
507*4882a593Smuzhiyun 	sym_add_change_count(1);
508*4882a593Smuzhiyun 	sym_calc_value(modules_sym);
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun 
sym_tristate_within_range(struct symbol * sym,tristate val)511*4882a593Smuzhiyun bool sym_tristate_within_range(struct symbol *sym, tristate val)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun 	int type = sym_get_type(sym);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	if (sym->visible == no)
516*4882a593Smuzhiyun 		return false;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	if (type != S_BOOLEAN && type != S_TRISTATE)
519*4882a593Smuzhiyun 		return false;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	if (type == S_BOOLEAN && val == mod)
522*4882a593Smuzhiyun 		return false;
523*4882a593Smuzhiyun 	if (sym->visible <= sym->rev_dep.tri)
524*4882a593Smuzhiyun 		return false;
525*4882a593Smuzhiyun 	if (sym->implied.tri == yes && val == mod)
526*4882a593Smuzhiyun 		return false;
527*4882a593Smuzhiyun 	if (sym_is_choice_value(sym) && sym->visible == yes)
528*4882a593Smuzhiyun 		return val == yes;
529*4882a593Smuzhiyun 	return val >= sym->rev_dep.tri && val <= sym->visible;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun 
sym_set_tristate_value(struct symbol * sym,tristate val)532*4882a593Smuzhiyun bool sym_set_tristate_value(struct symbol *sym, tristate val)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun 	tristate oldval = sym_get_tristate_value(sym);
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	if (oldval != val && !sym_tristate_within_range(sym, val))
537*4882a593Smuzhiyun 		return false;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	if (!(sym->flags & SYMBOL_DEF_USER)) {
540*4882a593Smuzhiyun 		sym->flags |= SYMBOL_DEF_USER;
541*4882a593Smuzhiyun 		sym_set_changed(sym);
542*4882a593Smuzhiyun 	}
543*4882a593Smuzhiyun 	/*
544*4882a593Smuzhiyun 	 * setting a choice value also resets the new flag of the choice
545*4882a593Smuzhiyun 	 * symbol and all other choice values.
546*4882a593Smuzhiyun 	 */
547*4882a593Smuzhiyun 	if (sym_is_choice_value(sym) && val == yes) {
548*4882a593Smuzhiyun 		struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
549*4882a593Smuzhiyun 		struct property *prop;
550*4882a593Smuzhiyun 		struct expr *e;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 		cs->def[S_DEF_USER].val = sym;
553*4882a593Smuzhiyun 		cs->flags |= SYMBOL_DEF_USER;
554*4882a593Smuzhiyun 		prop = sym_get_choice_prop(cs);
555*4882a593Smuzhiyun 		for (e = prop->expr; e; e = e->left.expr) {
556*4882a593Smuzhiyun 			if (e->right.sym->visible != no)
557*4882a593Smuzhiyun 				e->right.sym->flags |= SYMBOL_DEF_USER;
558*4882a593Smuzhiyun 		}
559*4882a593Smuzhiyun 	}
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	sym->def[S_DEF_USER].tri = val;
562*4882a593Smuzhiyun 	if (oldval != val)
563*4882a593Smuzhiyun 		sym_clear_all_valid();
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	return true;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun 
sym_toggle_tristate_value(struct symbol * sym)568*4882a593Smuzhiyun tristate sym_toggle_tristate_value(struct symbol *sym)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun 	tristate oldval, newval;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	oldval = newval = sym_get_tristate_value(sym);
573*4882a593Smuzhiyun 	do {
574*4882a593Smuzhiyun 		switch (newval) {
575*4882a593Smuzhiyun 		case no:
576*4882a593Smuzhiyun 			newval = mod;
577*4882a593Smuzhiyun 			break;
578*4882a593Smuzhiyun 		case mod:
579*4882a593Smuzhiyun 			newval = yes;
580*4882a593Smuzhiyun 			break;
581*4882a593Smuzhiyun 		case yes:
582*4882a593Smuzhiyun 			newval = no;
583*4882a593Smuzhiyun 			break;
584*4882a593Smuzhiyun 		}
585*4882a593Smuzhiyun 		if (sym_set_tristate_value(sym, newval))
586*4882a593Smuzhiyun 			break;
587*4882a593Smuzhiyun 	} while (oldval != newval);
588*4882a593Smuzhiyun 	return newval;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun 
sym_string_valid(struct symbol * sym,const char * str)591*4882a593Smuzhiyun bool sym_string_valid(struct symbol *sym, const char *str)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun 	signed char ch;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	switch (sym->type) {
596*4882a593Smuzhiyun 	case S_STRING:
597*4882a593Smuzhiyun 		return true;
598*4882a593Smuzhiyun 	case S_INT:
599*4882a593Smuzhiyun 		ch = *str++;
600*4882a593Smuzhiyun 		if (ch == '-')
601*4882a593Smuzhiyun 			ch = *str++;
602*4882a593Smuzhiyun 		if (!isdigit(ch))
603*4882a593Smuzhiyun 			return false;
604*4882a593Smuzhiyun 		if (ch == '0' && *str != 0)
605*4882a593Smuzhiyun 			return false;
606*4882a593Smuzhiyun 		while ((ch = *str++)) {
607*4882a593Smuzhiyun 			if (!isdigit(ch))
608*4882a593Smuzhiyun 				return false;
609*4882a593Smuzhiyun 		}
610*4882a593Smuzhiyun 		return true;
611*4882a593Smuzhiyun 	case S_HEX:
612*4882a593Smuzhiyun 		if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
613*4882a593Smuzhiyun 			str += 2;
614*4882a593Smuzhiyun 		ch = *str++;
615*4882a593Smuzhiyun 		do {
616*4882a593Smuzhiyun 			if (!isxdigit(ch))
617*4882a593Smuzhiyun 				return false;
618*4882a593Smuzhiyun 		} while ((ch = *str++));
619*4882a593Smuzhiyun 		return true;
620*4882a593Smuzhiyun 	case S_BOOLEAN:
621*4882a593Smuzhiyun 	case S_TRISTATE:
622*4882a593Smuzhiyun 		switch (str[0]) {
623*4882a593Smuzhiyun 		case 'y': case 'Y':
624*4882a593Smuzhiyun 		case 'm': case 'M':
625*4882a593Smuzhiyun 		case 'n': case 'N':
626*4882a593Smuzhiyun 			return true;
627*4882a593Smuzhiyun 		}
628*4882a593Smuzhiyun 		return false;
629*4882a593Smuzhiyun 	default:
630*4882a593Smuzhiyun 		return false;
631*4882a593Smuzhiyun 	}
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun 
sym_string_within_range(struct symbol * sym,const char * str)634*4882a593Smuzhiyun bool sym_string_within_range(struct symbol *sym, const char *str)
635*4882a593Smuzhiyun {
636*4882a593Smuzhiyun 	struct property *prop;
637*4882a593Smuzhiyun 	long long val;
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	switch (sym->type) {
640*4882a593Smuzhiyun 	case S_STRING:
641*4882a593Smuzhiyun 		return sym_string_valid(sym, str);
642*4882a593Smuzhiyun 	case S_INT:
643*4882a593Smuzhiyun 		if (!sym_string_valid(sym, str))
644*4882a593Smuzhiyun 			return false;
645*4882a593Smuzhiyun 		prop = sym_get_range_prop(sym);
646*4882a593Smuzhiyun 		if (!prop)
647*4882a593Smuzhiyun 			return true;
648*4882a593Smuzhiyun 		val = strtoll(str, NULL, 10);
649*4882a593Smuzhiyun 		return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
650*4882a593Smuzhiyun 		       val <= sym_get_range_val(prop->expr->right.sym, 10);
651*4882a593Smuzhiyun 	case S_HEX:
652*4882a593Smuzhiyun 		if (!sym_string_valid(sym, str))
653*4882a593Smuzhiyun 			return false;
654*4882a593Smuzhiyun 		prop = sym_get_range_prop(sym);
655*4882a593Smuzhiyun 		if (!prop)
656*4882a593Smuzhiyun 			return true;
657*4882a593Smuzhiyun 		val = strtoll(str, NULL, 16);
658*4882a593Smuzhiyun 		return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
659*4882a593Smuzhiyun 		       val <= sym_get_range_val(prop->expr->right.sym, 16);
660*4882a593Smuzhiyun 	case S_BOOLEAN:
661*4882a593Smuzhiyun 	case S_TRISTATE:
662*4882a593Smuzhiyun 		switch (str[0]) {
663*4882a593Smuzhiyun 		case 'y': case 'Y':
664*4882a593Smuzhiyun 			return sym_tristate_within_range(sym, yes);
665*4882a593Smuzhiyun 		case 'm': case 'M':
666*4882a593Smuzhiyun 			return sym_tristate_within_range(sym, mod);
667*4882a593Smuzhiyun 		case 'n': case 'N':
668*4882a593Smuzhiyun 			return sym_tristate_within_range(sym, no);
669*4882a593Smuzhiyun 		}
670*4882a593Smuzhiyun 		return false;
671*4882a593Smuzhiyun 	default:
672*4882a593Smuzhiyun 		return false;
673*4882a593Smuzhiyun 	}
674*4882a593Smuzhiyun }
675*4882a593Smuzhiyun 
sym_set_string_value(struct symbol * sym,const char * newval)676*4882a593Smuzhiyun bool sym_set_string_value(struct symbol *sym, const char *newval)
677*4882a593Smuzhiyun {
678*4882a593Smuzhiyun 	const char *oldval;
679*4882a593Smuzhiyun 	char *val;
680*4882a593Smuzhiyun 	int size;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	switch (sym->type) {
683*4882a593Smuzhiyun 	case S_BOOLEAN:
684*4882a593Smuzhiyun 	case S_TRISTATE:
685*4882a593Smuzhiyun 		switch (newval[0]) {
686*4882a593Smuzhiyun 		case 'y': case 'Y':
687*4882a593Smuzhiyun 			return sym_set_tristate_value(sym, yes);
688*4882a593Smuzhiyun 		case 'm': case 'M':
689*4882a593Smuzhiyun 			return sym_set_tristate_value(sym, mod);
690*4882a593Smuzhiyun 		case 'n': case 'N':
691*4882a593Smuzhiyun 			return sym_set_tristate_value(sym, no);
692*4882a593Smuzhiyun 		}
693*4882a593Smuzhiyun 		return false;
694*4882a593Smuzhiyun 	default:
695*4882a593Smuzhiyun 		;
696*4882a593Smuzhiyun 	}
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	if (!sym_string_within_range(sym, newval))
699*4882a593Smuzhiyun 		return false;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	if (!(sym->flags & SYMBOL_DEF_USER)) {
702*4882a593Smuzhiyun 		sym->flags |= SYMBOL_DEF_USER;
703*4882a593Smuzhiyun 		sym_set_changed(sym);
704*4882a593Smuzhiyun 	}
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	oldval = sym->def[S_DEF_USER].val;
707*4882a593Smuzhiyun 	size = strlen(newval) + 1;
708*4882a593Smuzhiyun 	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
709*4882a593Smuzhiyun 		size += 2;
710*4882a593Smuzhiyun 		sym->def[S_DEF_USER].val = val = xmalloc(size);
711*4882a593Smuzhiyun 		*val++ = '0';
712*4882a593Smuzhiyun 		*val++ = 'x';
713*4882a593Smuzhiyun 	} else if (!oldval || strcmp(oldval, newval))
714*4882a593Smuzhiyun 		sym->def[S_DEF_USER].val = val = xmalloc(size);
715*4882a593Smuzhiyun 	else
716*4882a593Smuzhiyun 		return true;
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	strcpy(val, newval);
719*4882a593Smuzhiyun 	free((void *)oldval);
720*4882a593Smuzhiyun 	sym_clear_all_valid();
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	return true;
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun /*
726*4882a593Smuzhiyun  * Find the default value associated to a symbol.
727*4882a593Smuzhiyun  * For tristate symbol handle the modules=n case
728*4882a593Smuzhiyun  * in which case "m" becomes "y".
729*4882a593Smuzhiyun  * If the symbol does not have any default then fallback
730*4882a593Smuzhiyun  * to the fixed default values.
731*4882a593Smuzhiyun  */
sym_get_string_default(struct symbol * sym)732*4882a593Smuzhiyun const char *sym_get_string_default(struct symbol *sym)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun 	struct property *prop;
735*4882a593Smuzhiyun 	struct symbol *ds;
736*4882a593Smuzhiyun 	const char *str;
737*4882a593Smuzhiyun 	tristate val;
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	sym_calc_visibility(sym);
740*4882a593Smuzhiyun 	sym_calc_value(modules_sym);
741*4882a593Smuzhiyun 	val = symbol_no.curr.tri;
742*4882a593Smuzhiyun 	str = symbol_empty.curr.val;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	/* If symbol has a default value look it up */
745*4882a593Smuzhiyun 	prop = sym_get_default_prop(sym);
746*4882a593Smuzhiyun 	if (prop != NULL) {
747*4882a593Smuzhiyun 		switch (sym->type) {
748*4882a593Smuzhiyun 		case S_BOOLEAN:
749*4882a593Smuzhiyun 		case S_TRISTATE:
750*4882a593Smuzhiyun 			/* The visibility may limit the value from yes => mod */
751*4882a593Smuzhiyun 			val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
752*4882a593Smuzhiyun 			break;
753*4882a593Smuzhiyun 		default:
754*4882a593Smuzhiyun 			/*
755*4882a593Smuzhiyun 			 * The following fails to handle the situation
756*4882a593Smuzhiyun 			 * where a default value is further limited by
757*4882a593Smuzhiyun 			 * the valid range.
758*4882a593Smuzhiyun 			 */
759*4882a593Smuzhiyun 			ds = prop_get_symbol(prop);
760*4882a593Smuzhiyun 			if (ds != NULL) {
761*4882a593Smuzhiyun 				sym_calc_value(ds);
762*4882a593Smuzhiyun 				str = (const char *)ds->curr.val;
763*4882a593Smuzhiyun 			}
764*4882a593Smuzhiyun 		}
765*4882a593Smuzhiyun 	}
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	/* Handle select statements */
768*4882a593Smuzhiyun 	val = EXPR_OR(val, sym->rev_dep.tri);
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 	/* transpose mod to yes if modules are not enabled */
771*4882a593Smuzhiyun 	if (val == mod)
772*4882a593Smuzhiyun 		if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
773*4882a593Smuzhiyun 			val = yes;
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	/* transpose mod to yes if type is bool */
776*4882a593Smuzhiyun 	if (sym->type == S_BOOLEAN && val == mod)
777*4882a593Smuzhiyun 		val = yes;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	/* adjust the default value if this symbol is implied by another */
780*4882a593Smuzhiyun 	if (val < sym->implied.tri)
781*4882a593Smuzhiyun 		val = sym->implied.tri;
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	switch (sym->type) {
784*4882a593Smuzhiyun 	case S_BOOLEAN:
785*4882a593Smuzhiyun 	case S_TRISTATE:
786*4882a593Smuzhiyun 		switch (val) {
787*4882a593Smuzhiyun 		case no: return "n";
788*4882a593Smuzhiyun 		case mod: return "m";
789*4882a593Smuzhiyun 		case yes: return "y";
790*4882a593Smuzhiyun 		}
791*4882a593Smuzhiyun 	case S_INT:
792*4882a593Smuzhiyun 	case S_HEX:
793*4882a593Smuzhiyun 		return str;
794*4882a593Smuzhiyun 	case S_STRING:
795*4882a593Smuzhiyun 		return str;
796*4882a593Smuzhiyun 	case S_OTHER:
797*4882a593Smuzhiyun 	case S_UNKNOWN:
798*4882a593Smuzhiyun 		break;
799*4882a593Smuzhiyun 	}
800*4882a593Smuzhiyun 	return "";
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun 
sym_get_string_value(struct symbol * sym)803*4882a593Smuzhiyun const char *sym_get_string_value(struct symbol *sym)
804*4882a593Smuzhiyun {
805*4882a593Smuzhiyun 	tristate val;
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	switch (sym->type) {
808*4882a593Smuzhiyun 	case S_BOOLEAN:
809*4882a593Smuzhiyun 	case S_TRISTATE:
810*4882a593Smuzhiyun 		val = sym_get_tristate_value(sym);
811*4882a593Smuzhiyun 		switch (val) {
812*4882a593Smuzhiyun 		case no:
813*4882a593Smuzhiyun 			return "n";
814*4882a593Smuzhiyun 		case mod:
815*4882a593Smuzhiyun 			sym_calc_value(modules_sym);
816*4882a593Smuzhiyun 			return (modules_sym->curr.tri == no) ? "n" : "m";
817*4882a593Smuzhiyun 		case yes:
818*4882a593Smuzhiyun 			return "y";
819*4882a593Smuzhiyun 		}
820*4882a593Smuzhiyun 		break;
821*4882a593Smuzhiyun 	default:
822*4882a593Smuzhiyun 		;
823*4882a593Smuzhiyun 	}
824*4882a593Smuzhiyun 	return (const char *)sym->curr.val;
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun 
sym_is_changable(struct symbol * sym)827*4882a593Smuzhiyun bool sym_is_changable(struct symbol *sym)
828*4882a593Smuzhiyun {
829*4882a593Smuzhiyun 	return sym->visible > sym->rev_dep.tri;
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun 
strhash(const char * s)832*4882a593Smuzhiyun static unsigned strhash(const char *s)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun 	/* fnv32 hash */
835*4882a593Smuzhiyun 	unsigned hash = 2166136261U;
836*4882a593Smuzhiyun 	for (; *s; s++)
837*4882a593Smuzhiyun 		hash = (hash ^ *s) * 0x01000193;
838*4882a593Smuzhiyun 	return hash;
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun 
sym_lookup(const char * name,int flags)841*4882a593Smuzhiyun struct symbol *sym_lookup(const char *name, int flags)
842*4882a593Smuzhiyun {
843*4882a593Smuzhiyun 	struct symbol *symbol;
844*4882a593Smuzhiyun 	char *new_name;
845*4882a593Smuzhiyun 	int hash;
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	if (name) {
848*4882a593Smuzhiyun 		if (name[0] && !name[1]) {
849*4882a593Smuzhiyun 			switch (name[0]) {
850*4882a593Smuzhiyun 			case 'y': return &symbol_yes;
851*4882a593Smuzhiyun 			case 'm': return &symbol_mod;
852*4882a593Smuzhiyun 			case 'n': return &symbol_no;
853*4882a593Smuzhiyun 			}
854*4882a593Smuzhiyun 		}
855*4882a593Smuzhiyun 		hash = strhash(name) % SYMBOL_HASHSIZE;
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun 		for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
858*4882a593Smuzhiyun 			if (symbol->name &&
859*4882a593Smuzhiyun 			    !strcmp(symbol->name, name) &&
860*4882a593Smuzhiyun 			    (flags ? symbol->flags & flags
861*4882a593Smuzhiyun 				   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
862*4882a593Smuzhiyun 				return symbol;
863*4882a593Smuzhiyun 		}
864*4882a593Smuzhiyun 		new_name = xstrdup(name);
865*4882a593Smuzhiyun 	} else {
866*4882a593Smuzhiyun 		new_name = NULL;
867*4882a593Smuzhiyun 		hash = 0;
868*4882a593Smuzhiyun 	}
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 	symbol = xmalloc(sizeof(*symbol));
871*4882a593Smuzhiyun 	memset(symbol, 0, sizeof(*symbol));
872*4882a593Smuzhiyun 	symbol->name = new_name;
873*4882a593Smuzhiyun 	symbol->type = S_UNKNOWN;
874*4882a593Smuzhiyun 	symbol->flags |= flags;
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	symbol->next = symbol_hash[hash];
877*4882a593Smuzhiyun 	symbol_hash[hash] = symbol;
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 	return symbol;
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun 
sym_find(const char * name)882*4882a593Smuzhiyun struct symbol *sym_find(const char *name)
883*4882a593Smuzhiyun {
884*4882a593Smuzhiyun 	struct symbol *symbol = NULL;
885*4882a593Smuzhiyun 	int hash = 0;
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	if (!name)
888*4882a593Smuzhiyun 		return NULL;
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	if (name[0] && !name[1]) {
891*4882a593Smuzhiyun 		switch (name[0]) {
892*4882a593Smuzhiyun 		case 'y': return &symbol_yes;
893*4882a593Smuzhiyun 		case 'm': return &symbol_mod;
894*4882a593Smuzhiyun 		case 'n': return &symbol_no;
895*4882a593Smuzhiyun 		}
896*4882a593Smuzhiyun 	}
897*4882a593Smuzhiyun 	hash = strhash(name) % SYMBOL_HASHSIZE;
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
900*4882a593Smuzhiyun 		if (symbol->name &&
901*4882a593Smuzhiyun 		    !strcmp(symbol->name, name) &&
902*4882a593Smuzhiyun 		    !(symbol->flags & SYMBOL_CONST))
903*4882a593Smuzhiyun 				break;
904*4882a593Smuzhiyun 	}
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	return symbol;
907*4882a593Smuzhiyun }
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun /*
910*4882a593Smuzhiyun  * Expand symbol's names embedded in the string given in argument. Symbols'
911*4882a593Smuzhiyun  * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
912*4882a593Smuzhiyun  * the empty string.
913*4882a593Smuzhiyun  */
sym_expand_string_value(const char * in)914*4882a593Smuzhiyun char *sym_expand_string_value(const char *in)
915*4882a593Smuzhiyun {
916*4882a593Smuzhiyun 	const char *src;
917*4882a593Smuzhiyun 	char *res;
918*4882a593Smuzhiyun 	size_t reslen;
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 	/*
921*4882a593Smuzhiyun 	 * Note: 'in' might come from a token that's about to be
922*4882a593Smuzhiyun 	 * freed, so make sure to always allocate a new string
923*4882a593Smuzhiyun 	 */
924*4882a593Smuzhiyun 	reslen = strlen(in) + 1;
925*4882a593Smuzhiyun 	res = xmalloc(reslen);
926*4882a593Smuzhiyun 	res[0] = '\0';
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun 	while ((src = strchr(in, '$'))) {
929*4882a593Smuzhiyun 		char *p, name[SYMBOL_MAXLENGTH];
930*4882a593Smuzhiyun 		const char *symval = "";
931*4882a593Smuzhiyun 		struct symbol *sym;
932*4882a593Smuzhiyun 		size_t newlen;
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun 		strncat(res, in, src - in);
935*4882a593Smuzhiyun 		src++;
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 		p = name;
938*4882a593Smuzhiyun 		while (isalnum(*src) || *src == '_')
939*4882a593Smuzhiyun 			*p++ = *src++;
940*4882a593Smuzhiyun 		*p = '\0';
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 		sym = sym_find(name);
943*4882a593Smuzhiyun 		if (sym != NULL) {
944*4882a593Smuzhiyun 			sym_calc_value(sym);
945*4882a593Smuzhiyun 			symval = sym_get_string_value(sym);
946*4882a593Smuzhiyun 		}
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 		newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
949*4882a593Smuzhiyun 		if (newlen > reslen) {
950*4882a593Smuzhiyun 			reslen = newlen;
951*4882a593Smuzhiyun 			res = xrealloc(res, reslen);
952*4882a593Smuzhiyun 		}
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun 		strcat(res, symval);
955*4882a593Smuzhiyun 		in = src;
956*4882a593Smuzhiyun 	}
957*4882a593Smuzhiyun 	strcat(res, in);
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun 	return res;
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun 
sym_escape_string_value(const char * in)962*4882a593Smuzhiyun const char *sym_escape_string_value(const char *in)
963*4882a593Smuzhiyun {
964*4882a593Smuzhiyun 	const char *p;
965*4882a593Smuzhiyun 	size_t reslen;
966*4882a593Smuzhiyun 	char *res;
967*4882a593Smuzhiyun 	size_t l;
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	reslen = strlen(in) + strlen("\"\"") + 1;
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 	p = in;
972*4882a593Smuzhiyun 	for (;;) {
973*4882a593Smuzhiyun 		l = strcspn(p, "\"\\");
974*4882a593Smuzhiyun 		p += l;
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun 		if (p[0] == '\0')
977*4882a593Smuzhiyun 			break;
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun 		reslen++;
980*4882a593Smuzhiyun 		p++;
981*4882a593Smuzhiyun 	}
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun 	res = xmalloc(reslen);
984*4882a593Smuzhiyun 	res[0] = '\0';
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun 	strcat(res, "\"");
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 	p = in;
989*4882a593Smuzhiyun 	for (;;) {
990*4882a593Smuzhiyun 		l = strcspn(p, "\"\\");
991*4882a593Smuzhiyun 		strncat(res, p, l);
992*4882a593Smuzhiyun 		p += l;
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun 		if (p[0] == '\0')
995*4882a593Smuzhiyun 			break;
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 		strcat(res, "\\");
998*4882a593Smuzhiyun 		strncat(res, p++, 1);
999*4882a593Smuzhiyun 	}
1000*4882a593Smuzhiyun 
1001*4882a593Smuzhiyun 	strcat(res, "\"");
1002*4882a593Smuzhiyun 	return res;
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun struct sym_match {
1006*4882a593Smuzhiyun 	struct symbol	*sym;
1007*4882a593Smuzhiyun 	off_t		so, eo;
1008*4882a593Smuzhiyun };
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun /* Compare matched symbols as thus:
1011*4882a593Smuzhiyun  * - first, symbols that match exactly
1012*4882a593Smuzhiyun  * - then, alphabetical sort
1013*4882a593Smuzhiyun  */
sym_rel_comp(const void * sym1,const void * sym2)1014*4882a593Smuzhiyun static int sym_rel_comp(const void *sym1, const void *sym2)
1015*4882a593Smuzhiyun {
1016*4882a593Smuzhiyun 	const struct sym_match *s1 = sym1;
1017*4882a593Smuzhiyun 	const struct sym_match *s2 = sym2;
1018*4882a593Smuzhiyun 	int exact1, exact2;
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun 	/* Exact match:
1021*4882a593Smuzhiyun 	 * - if matched length on symbol s1 is the length of that symbol,
1022*4882a593Smuzhiyun 	 *   then this symbol should come first;
1023*4882a593Smuzhiyun 	 * - if matched length on symbol s2 is the length of that symbol,
1024*4882a593Smuzhiyun 	 *   then this symbol should come first.
1025*4882a593Smuzhiyun 	 * Note: since the search can be a regexp, both symbols may match
1026*4882a593Smuzhiyun 	 * exactly; if this is the case, we can't decide which comes first,
1027*4882a593Smuzhiyun 	 * and we fallback to sorting alphabetically.
1028*4882a593Smuzhiyun 	 */
1029*4882a593Smuzhiyun 	exact1 = (s1->eo - s1->so) == strlen(s1->sym->name);
1030*4882a593Smuzhiyun 	exact2 = (s2->eo - s2->so) == strlen(s2->sym->name);
1031*4882a593Smuzhiyun 	if (exact1 && !exact2)
1032*4882a593Smuzhiyun 		return -1;
1033*4882a593Smuzhiyun 	if (!exact1 && exact2)
1034*4882a593Smuzhiyun 		return 1;
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun 	/* As a fallback, sort symbols alphabetically */
1037*4882a593Smuzhiyun 	return strcmp(s1->sym->name, s2->sym->name);
1038*4882a593Smuzhiyun }
1039*4882a593Smuzhiyun 
sym_re_search(const char * pattern)1040*4882a593Smuzhiyun struct symbol **sym_re_search(const char *pattern)
1041*4882a593Smuzhiyun {
1042*4882a593Smuzhiyun 	struct symbol *sym, **sym_arr = NULL;
1043*4882a593Smuzhiyun 	struct sym_match *sym_match_arr = NULL;
1044*4882a593Smuzhiyun 	int i, cnt, size;
1045*4882a593Smuzhiyun 	regex_t re;
1046*4882a593Smuzhiyun 	regmatch_t match[1];
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun 	cnt = size = 0;
1049*4882a593Smuzhiyun 	/* Skip if empty */
1050*4882a593Smuzhiyun 	if (strlen(pattern) == 0)
1051*4882a593Smuzhiyun 		return NULL;
1052*4882a593Smuzhiyun 	if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
1053*4882a593Smuzhiyun 		return NULL;
1054*4882a593Smuzhiyun 
1055*4882a593Smuzhiyun 	for_all_symbols(i, sym) {
1056*4882a593Smuzhiyun 		if (sym->flags & SYMBOL_CONST || !sym->name)
1057*4882a593Smuzhiyun 			continue;
1058*4882a593Smuzhiyun 		if (regexec(&re, sym->name, 1, match, 0))
1059*4882a593Smuzhiyun 			continue;
1060*4882a593Smuzhiyun 		if (cnt >= size) {
1061*4882a593Smuzhiyun 			void *tmp;
1062*4882a593Smuzhiyun 			size += 16;
1063*4882a593Smuzhiyun 			tmp = realloc(sym_match_arr, size * sizeof(struct sym_match));
1064*4882a593Smuzhiyun 			if (!tmp)
1065*4882a593Smuzhiyun 				goto sym_re_search_free;
1066*4882a593Smuzhiyun 			sym_match_arr = tmp;
1067*4882a593Smuzhiyun 		}
1068*4882a593Smuzhiyun 		sym_calc_value(sym);
1069*4882a593Smuzhiyun 		/* As regexec returned 0, we know we have a match, so
1070*4882a593Smuzhiyun 		 * we can use match[0].rm_[se]o without further checks
1071*4882a593Smuzhiyun 		 */
1072*4882a593Smuzhiyun 		sym_match_arr[cnt].so = match[0].rm_so;
1073*4882a593Smuzhiyun 		sym_match_arr[cnt].eo = match[0].rm_eo;
1074*4882a593Smuzhiyun 		sym_match_arr[cnt++].sym = sym;
1075*4882a593Smuzhiyun 	}
1076*4882a593Smuzhiyun 	if (sym_match_arr) {
1077*4882a593Smuzhiyun 		qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp);
1078*4882a593Smuzhiyun 		sym_arr = malloc((cnt+1) * sizeof(struct symbol *));
1079*4882a593Smuzhiyun 		if (!sym_arr)
1080*4882a593Smuzhiyun 			goto sym_re_search_free;
1081*4882a593Smuzhiyun 		for (i = 0; i < cnt; i++)
1082*4882a593Smuzhiyun 			sym_arr[i] = sym_match_arr[i].sym;
1083*4882a593Smuzhiyun 		sym_arr[cnt] = NULL;
1084*4882a593Smuzhiyun 	}
1085*4882a593Smuzhiyun sym_re_search_free:
1086*4882a593Smuzhiyun 	/* sym_match_arr can be NULL if no match, but free(NULL) is OK */
1087*4882a593Smuzhiyun 	free(sym_match_arr);
1088*4882a593Smuzhiyun 	regfree(&re);
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 	return sym_arr;
1091*4882a593Smuzhiyun }
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun /*
1094*4882a593Smuzhiyun  * When we check for recursive dependencies we use a stack to save
1095*4882a593Smuzhiyun  * current state so we can print out relevant info to user.
1096*4882a593Smuzhiyun  * The entries are located on the call stack so no need to free memory.
1097*4882a593Smuzhiyun  * Note insert() remove() must always match to properly clear the stack.
1098*4882a593Smuzhiyun  */
1099*4882a593Smuzhiyun static struct dep_stack {
1100*4882a593Smuzhiyun 	struct dep_stack *prev, *next;
1101*4882a593Smuzhiyun 	struct symbol *sym;
1102*4882a593Smuzhiyun 	struct property *prop;
1103*4882a593Smuzhiyun 	struct expr *expr;
1104*4882a593Smuzhiyun } *check_top;
1105*4882a593Smuzhiyun 
dep_stack_insert(struct dep_stack * stack,struct symbol * sym)1106*4882a593Smuzhiyun static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
1107*4882a593Smuzhiyun {
1108*4882a593Smuzhiyun 	memset(stack, 0, sizeof(*stack));
1109*4882a593Smuzhiyun 	if (check_top)
1110*4882a593Smuzhiyun 		check_top->next = stack;
1111*4882a593Smuzhiyun 	stack->prev = check_top;
1112*4882a593Smuzhiyun 	stack->sym = sym;
1113*4882a593Smuzhiyun 	check_top = stack;
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun 
dep_stack_remove(void)1116*4882a593Smuzhiyun static void dep_stack_remove(void)
1117*4882a593Smuzhiyun {
1118*4882a593Smuzhiyun 	check_top = check_top->prev;
1119*4882a593Smuzhiyun 	if (check_top)
1120*4882a593Smuzhiyun 		check_top->next = NULL;
1121*4882a593Smuzhiyun }
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun /*
1124*4882a593Smuzhiyun  * Called when we have detected a recursive dependency.
1125*4882a593Smuzhiyun  * check_top point to the top of the stact so we use
1126*4882a593Smuzhiyun  * the ->prev pointer to locate the bottom of the stack.
1127*4882a593Smuzhiyun  */
sym_check_print_recursive(struct symbol * last_sym)1128*4882a593Smuzhiyun static void sym_check_print_recursive(struct symbol *last_sym)
1129*4882a593Smuzhiyun {
1130*4882a593Smuzhiyun 	struct dep_stack *stack;
1131*4882a593Smuzhiyun 	struct symbol *sym, *next_sym;
1132*4882a593Smuzhiyun 	struct menu *menu = NULL;
1133*4882a593Smuzhiyun 	struct property *prop;
1134*4882a593Smuzhiyun 	struct dep_stack cv_stack;
1135*4882a593Smuzhiyun 
1136*4882a593Smuzhiyun 	if (sym_is_choice_value(last_sym)) {
1137*4882a593Smuzhiyun 		dep_stack_insert(&cv_stack, last_sym);
1138*4882a593Smuzhiyun 		last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
1139*4882a593Smuzhiyun 	}
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun 	for (stack = check_top; stack != NULL; stack = stack->prev)
1142*4882a593Smuzhiyun 		if (stack->sym == last_sym)
1143*4882a593Smuzhiyun 			break;
1144*4882a593Smuzhiyun 	if (!stack) {
1145*4882a593Smuzhiyun 		fprintf(stderr, "unexpected recursive dependency error\n");
1146*4882a593Smuzhiyun 		return;
1147*4882a593Smuzhiyun 	}
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun 	for (; stack; stack = stack->next) {
1150*4882a593Smuzhiyun 		sym = stack->sym;
1151*4882a593Smuzhiyun 		next_sym = stack->next ? stack->next->sym : last_sym;
1152*4882a593Smuzhiyun 		prop = stack->prop;
1153*4882a593Smuzhiyun 		if (prop == NULL)
1154*4882a593Smuzhiyun 			prop = stack->sym->prop;
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun 		/* for choice values find the menu entry (used below) */
1157*4882a593Smuzhiyun 		if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
1158*4882a593Smuzhiyun 			for (prop = sym->prop; prop; prop = prop->next) {
1159*4882a593Smuzhiyun 				menu = prop->menu;
1160*4882a593Smuzhiyun 				if (prop->menu)
1161*4882a593Smuzhiyun 					break;
1162*4882a593Smuzhiyun 			}
1163*4882a593Smuzhiyun 		}
1164*4882a593Smuzhiyun 		if (stack->sym == last_sym)
1165*4882a593Smuzhiyun 			fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
1166*4882a593Smuzhiyun 				prop->file->name, prop->lineno);
1167*4882a593Smuzhiyun 
1168*4882a593Smuzhiyun 		if (stack->expr) {
1169*4882a593Smuzhiyun 			fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
1170*4882a593Smuzhiyun 				prop->file->name, prop->lineno,
1171*4882a593Smuzhiyun 				sym->name ? sym->name : "<choice>",
1172*4882a593Smuzhiyun 				prop_get_type_name(prop->type),
1173*4882a593Smuzhiyun 				next_sym->name ? next_sym->name : "<choice>");
1174*4882a593Smuzhiyun 		} else if (stack->prop) {
1175*4882a593Smuzhiyun 			fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
1176*4882a593Smuzhiyun 				prop->file->name, prop->lineno,
1177*4882a593Smuzhiyun 				sym->name ? sym->name : "<choice>",
1178*4882a593Smuzhiyun 				next_sym->name ? next_sym->name : "<choice>");
1179*4882a593Smuzhiyun 		} else if (sym_is_choice(sym)) {
1180*4882a593Smuzhiyun 			fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
1181*4882a593Smuzhiyun 				menu->file->name, menu->lineno,
1182*4882a593Smuzhiyun 				sym->name ? sym->name : "<choice>",
1183*4882a593Smuzhiyun 				next_sym->name ? next_sym->name : "<choice>");
1184*4882a593Smuzhiyun 		} else if (sym_is_choice_value(sym)) {
1185*4882a593Smuzhiyun 			fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
1186*4882a593Smuzhiyun 				menu->file->name, menu->lineno,
1187*4882a593Smuzhiyun 				sym->name ? sym->name : "<choice>",
1188*4882a593Smuzhiyun 				next_sym->name ? next_sym->name : "<choice>");
1189*4882a593Smuzhiyun 		} else {
1190*4882a593Smuzhiyun 			fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
1191*4882a593Smuzhiyun 				prop->file->name, prop->lineno,
1192*4882a593Smuzhiyun 				sym->name ? sym->name : "<choice>",
1193*4882a593Smuzhiyun 				next_sym->name ? next_sym->name : "<choice>");
1194*4882a593Smuzhiyun 		}
1195*4882a593Smuzhiyun 	}
1196*4882a593Smuzhiyun 
1197*4882a593Smuzhiyun 	fprintf(stderr,
1198*4882a593Smuzhiyun 		"For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"
1199*4882a593Smuzhiyun 		"subsection \"Kconfig recursive dependency limitations\"\n"
1200*4882a593Smuzhiyun 		"\n");
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun 	if (check_top == &cv_stack)
1203*4882a593Smuzhiyun 		dep_stack_remove();
1204*4882a593Smuzhiyun }
1205*4882a593Smuzhiyun 
sym_check_expr_deps(struct expr * e)1206*4882a593Smuzhiyun static struct symbol *sym_check_expr_deps(struct expr *e)
1207*4882a593Smuzhiyun {
1208*4882a593Smuzhiyun 	struct symbol *sym;
1209*4882a593Smuzhiyun 
1210*4882a593Smuzhiyun 	if (!e)
1211*4882a593Smuzhiyun 		return NULL;
1212*4882a593Smuzhiyun 	switch (e->type) {
1213*4882a593Smuzhiyun 	case E_OR:
1214*4882a593Smuzhiyun 	case E_AND:
1215*4882a593Smuzhiyun 		sym = sym_check_expr_deps(e->left.expr);
1216*4882a593Smuzhiyun 		if (sym)
1217*4882a593Smuzhiyun 			return sym;
1218*4882a593Smuzhiyun 		return sym_check_expr_deps(e->right.expr);
1219*4882a593Smuzhiyun 	case E_NOT:
1220*4882a593Smuzhiyun 		return sym_check_expr_deps(e->left.expr);
1221*4882a593Smuzhiyun 	case E_EQUAL:
1222*4882a593Smuzhiyun 	case E_GEQ:
1223*4882a593Smuzhiyun 	case E_GTH:
1224*4882a593Smuzhiyun 	case E_LEQ:
1225*4882a593Smuzhiyun 	case E_LTH:
1226*4882a593Smuzhiyun 	case E_UNEQUAL:
1227*4882a593Smuzhiyun 		sym = sym_check_deps(e->left.sym);
1228*4882a593Smuzhiyun 		if (sym)
1229*4882a593Smuzhiyun 			return sym;
1230*4882a593Smuzhiyun 		return sym_check_deps(e->right.sym);
1231*4882a593Smuzhiyun 	case E_SYMBOL:
1232*4882a593Smuzhiyun 		return sym_check_deps(e->left.sym);
1233*4882a593Smuzhiyun 	default:
1234*4882a593Smuzhiyun 		break;
1235*4882a593Smuzhiyun 	}
1236*4882a593Smuzhiyun 	fprintf(stderr, "Oops! How to check %d?\n", e->type);
1237*4882a593Smuzhiyun 	return NULL;
1238*4882a593Smuzhiyun }
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun /* return NULL when dependencies are OK */
sym_check_sym_deps(struct symbol * sym)1241*4882a593Smuzhiyun static struct symbol *sym_check_sym_deps(struct symbol *sym)
1242*4882a593Smuzhiyun {
1243*4882a593Smuzhiyun 	struct symbol *sym2;
1244*4882a593Smuzhiyun 	struct property *prop;
1245*4882a593Smuzhiyun 	struct dep_stack stack;
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun 	dep_stack_insert(&stack, sym);
1248*4882a593Smuzhiyun 
1249*4882a593Smuzhiyun 	sym2 = sym_check_expr_deps(sym->rev_dep.expr);
1250*4882a593Smuzhiyun 	if (sym2)
1251*4882a593Smuzhiyun 		goto out;
1252*4882a593Smuzhiyun 
1253*4882a593Smuzhiyun 	for (prop = sym->prop; prop; prop = prop->next) {
1254*4882a593Smuzhiyun 		if (prop->type == P_CHOICE || prop->type == P_SELECT)
1255*4882a593Smuzhiyun 			continue;
1256*4882a593Smuzhiyun 		stack.prop = prop;
1257*4882a593Smuzhiyun 		sym2 = sym_check_expr_deps(prop->visible.expr);
1258*4882a593Smuzhiyun 		if (sym2)
1259*4882a593Smuzhiyun 			break;
1260*4882a593Smuzhiyun 		if (prop->type != P_DEFAULT || sym_is_choice(sym))
1261*4882a593Smuzhiyun 			continue;
1262*4882a593Smuzhiyun 		stack.expr = prop->expr;
1263*4882a593Smuzhiyun 		sym2 = sym_check_expr_deps(prop->expr);
1264*4882a593Smuzhiyun 		if (sym2)
1265*4882a593Smuzhiyun 			break;
1266*4882a593Smuzhiyun 		stack.expr = NULL;
1267*4882a593Smuzhiyun 	}
1268*4882a593Smuzhiyun 
1269*4882a593Smuzhiyun out:
1270*4882a593Smuzhiyun 	dep_stack_remove();
1271*4882a593Smuzhiyun 
1272*4882a593Smuzhiyun 	return sym2;
1273*4882a593Smuzhiyun }
1274*4882a593Smuzhiyun 
sym_check_choice_deps(struct symbol * choice)1275*4882a593Smuzhiyun static struct symbol *sym_check_choice_deps(struct symbol *choice)
1276*4882a593Smuzhiyun {
1277*4882a593Smuzhiyun 	struct symbol *sym, *sym2;
1278*4882a593Smuzhiyun 	struct property *prop;
1279*4882a593Smuzhiyun 	struct expr *e;
1280*4882a593Smuzhiyun 	struct dep_stack stack;
1281*4882a593Smuzhiyun 
1282*4882a593Smuzhiyun 	dep_stack_insert(&stack, choice);
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun 	prop = sym_get_choice_prop(choice);
1285*4882a593Smuzhiyun 	expr_list_for_each_sym(prop->expr, e, sym)
1286*4882a593Smuzhiyun 		sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1287*4882a593Smuzhiyun 
1288*4882a593Smuzhiyun 	choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1289*4882a593Smuzhiyun 	sym2 = sym_check_sym_deps(choice);
1290*4882a593Smuzhiyun 	choice->flags &= ~SYMBOL_CHECK;
1291*4882a593Smuzhiyun 	if (sym2)
1292*4882a593Smuzhiyun 		goto out;
1293*4882a593Smuzhiyun 
1294*4882a593Smuzhiyun 	expr_list_for_each_sym(prop->expr, e, sym) {
1295*4882a593Smuzhiyun 		sym2 = sym_check_sym_deps(sym);
1296*4882a593Smuzhiyun 		if (sym2)
1297*4882a593Smuzhiyun 			break;
1298*4882a593Smuzhiyun 	}
1299*4882a593Smuzhiyun out:
1300*4882a593Smuzhiyun 	expr_list_for_each_sym(prop->expr, e, sym)
1301*4882a593Smuzhiyun 		sym->flags &= ~SYMBOL_CHECK;
1302*4882a593Smuzhiyun 
1303*4882a593Smuzhiyun 	if (sym2 && sym_is_choice_value(sym2) &&
1304*4882a593Smuzhiyun 	    prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
1305*4882a593Smuzhiyun 		sym2 = choice;
1306*4882a593Smuzhiyun 
1307*4882a593Smuzhiyun 	dep_stack_remove();
1308*4882a593Smuzhiyun 
1309*4882a593Smuzhiyun 	return sym2;
1310*4882a593Smuzhiyun }
1311*4882a593Smuzhiyun 
sym_check_deps(struct symbol * sym)1312*4882a593Smuzhiyun struct symbol *sym_check_deps(struct symbol *sym)
1313*4882a593Smuzhiyun {
1314*4882a593Smuzhiyun 	struct symbol *sym2;
1315*4882a593Smuzhiyun 	struct property *prop;
1316*4882a593Smuzhiyun 
1317*4882a593Smuzhiyun 	if (sym->flags & SYMBOL_CHECK) {
1318*4882a593Smuzhiyun 		sym_check_print_recursive(sym);
1319*4882a593Smuzhiyun 		return sym;
1320*4882a593Smuzhiyun 	}
1321*4882a593Smuzhiyun 	if (sym->flags & SYMBOL_CHECKED)
1322*4882a593Smuzhiyun 		return NULL;
1323*4882a593Smuzhiyun 
1324*4882a593Smuzhiyun 	if (sym_is_choice_value(sym)) {
1325*4882a593Smuzhiyun 		struct dep_stack stack;
1326*4882a593Smuzhiyun 
1327*4882a593Smuzhiyun 		/* for choice groups start the check with main choice symbol */
1328*4882a593Smuzhiyun 		dep_stack_insert(&stack, sym);
1329*4882a593Smuzhiyun 		prop = sym_get_choice_prop(sym);
1330*4882a593Smuzhiyun 		sym2 = sym_check_deps(prop_get_symbol(prop));
1331*4882a593Smuzhiyun 		dep_stack_remove();
1332*4882a593Smuzhiyun 	} else if (sym_is_choice(sym)) {
1333*4882a593Smuzhiyun 		sym2 = sym_check_choice_deps(sym);
1334*4882a593Smuzhiyun 	} else {
1335*4882a593Smuzhiyun 		sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1336*4882a593Smuzhiyun 		sym2 = sym_check_sym_deps(sym);
1337*4882a593Smuzhiyun 		sym->flags &= ~SYMBOL_CHECK;
1338*4882a593Smuzhiyun 	}
1339*4882a593Smuzhiyun 
1340*4882a593Smuzhiyun 	if (sym2 && sym2 == sym)
1341*4882a593Smuzhiyun 		sym2 = NULL;
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun 	return sym2;
1344*4882a593Smuzhiyun }
1345*4882a593Smuzhiyun 
prop_alloc(enum prop_type type,struct symbol * sym)1346*4882a593Smuzhiyun struct property *prop_alloc(enum prop_type type, struct symbol *sym)
1347*4882a593Smuzhiyun {
1348*4882a593Smuzhiyun 	struct property *prop;
1349*4882a593Smuzhiyun 	struct property **propp;
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun 	prop = xmalloc(sizeof(*prop));
1352*4882a593Smuzhiyun 	memset(prop, 0, sizeof(*prop));
1353*4882a593Smuzhiyun 	prop->type = type;
1354*4882a593Smuzhiyun 	prop->sym = sym;
1355*4882a593Smuzhiyun 	prop->file = current_file;
1356*4882a593Smuzhiyun 	prop->lineno = zconf_lineno();
1357*4882a593Smuzhiyun 
1358*4882a593Smuzhiyun 	/* append property to the prop list of symbol */
1359*4882a593Smuzhiyun 	if (sym) {
1360*4882a593Smuzhiyun 		for (propp = &sym->prop; *propp; propp = &(*propp)->next)
1361*4882a593Smuzhiyun 			;
1362*4882a593Smuzhiyun 		*propp = prop;
1363*4882a593Smuzhiyun 	}
1364*4882a593Smuzhiyun 
1365*4882a593Smuzhiyun 	return prop;
1366*4882a593Smuzhiyun }
1367*4882a593Smuzhiyun 
prop_get_symbol(struct property * prop)1368*4882a593Smuzhiyun struct symbol *prop_get_symbol(struct property *prop)
1369*4882a593Smuzhiyun {
1370*4882a593Smuzhiyun 	if (prop->expr && (prop->expr->type == E_SYMBOL ||
1371*4882a593Smuzhiyun 			   prop->expr->type == E_LIST))
1372*4882a593Smuzhiyun 		return prop->expr->left.sym;
1373*4882a593Smuzhiyun 	return NULL;
1374*4882a593Smuzhiyun }
1375*4882a593Smuzhiyun 
prop_get_type_name(enum prop_type type)1376*4882a593Smuzhiyun const char *prop_get_type_name(enum prop_type type)
1377*4882a593Smuzhiyun {
1378*4882a593Smuzhiyun 	switch (type) {
1379*4882a593Smuzhiyun 	case P_PROMPT:
1380*4882a593Smuzhiyun 		return "prompt";
1381*4882a593Smuzhiyun 	case P_ENV:
1382*4882a593Smuzhiyun 		return "env";
1383*4882a593Smuzhiyun 	case P_COMMENT:
1384*4882a593Smuzhiyun 		return "comment";
1385*4882a593Smuzhiyun 	case P_MENU:
1386*4882a593Smuzhiyun 		return "menu";
1387*4882a593Smuzhiyun 	case P_DEFAULT:
1388*4882a593Smuzhiyun 		return "default";
1389*4882a593Smuzhiyun 	case P_CHOICE:
1390*4882a593Smuzhiyun 		return "choice";
1391*4882a593Smuzhiyun 	case P_SELECT:
1392*4882a593Smuzhiyun 		return "select";
1393*4882a593Smuzhiyun 	case P_IMPLY:
1394*4882a593Smuzhiyun 		return "imply";
1395*4882a593Smuzhiyun 	case P_RANGE:
1396*4882a593Smuzhiyun 		return "range";
1397*4882a593Smuzhiyun 	case P_SYMBOL:
1398*4882a593Smuzhiyun 		return "symbol";
1399*4882a593Smuzhiyun 	case P_UNKNOWN:
1400*4882a593Smuzhiyun 		break;
1401*4882a593Smuzhiyun 	}
1402*4882a593Smuzhiyun 	return "unknown";
1403*4882a593Smuzhiyun }
1404*4882a593Smuzhiyun 
prop_add_env(const char * env)1405*4882a593Smuzhiyun static void prop_add_env(const char *env)
1406*4882a593Smuzhiyun {
1407*4882a593Smuzhiyun 	struct symbol *sym, *sym2;
1408*4882a593Smuzhiyun 	struct property *prop;
1409*4882a593Smuzhiyun 	char *p;
1410*4882a593Smuzhiyun 
1411*4882a593Smuzhiyun 	sym = current_entry->sym;
1412*4882a593Smuzhiyun 	sym->flags |= SYMBOL_AUTO;
1413*4882a593Smuzhiyun 	for_all_properties(sym, prop, P_ENV) {
1414*4882a593Smuzhiyun 		sym2 = prop_get_symbol(prop);
1415*4882a593Smuzhiyun 		if (strcmp(sym2->name, env))
1416*4882a593Smuzhiyun 			menu_warn(current_entry, "redefining environment symbol from %s",
1417*4882a593Smuzhiyun 				  sym2->name);
1418*4882a593Smuzhiyun 		return;
1419*4882a593Smuzhiyun 	}
1420*4882a593Smuzhiyun 
1421*4882a593Smuzhiyun 	prop = prop_alloc(P_ENV, sym);
1422*4882a593Smuzhiyun 	prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
1423*4882a593Smuzhiyun 
1424*4882a593Smuzhiyun 	sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
1425*4882a593Smuzhiyun 	sym_env_list->right.sym = sym;
1426*4882a593Smuzhiyun 
1427*4882a593Smuzhiyun 	p = getenv(env);
1428*4882a593Smuzhiyun 	if (p)
1429*4882a593Smuzhiyun 		sym_add_default(sym, p);
1430*4882a593Smuzhiyun 	else
1431*4882a593Smuzhiyun 		menu_warn(current_entry, "environment variable %s undefined", env);
1432*4882a593Smuzhiyun }
1433