xref: /openbmc/linux/scripts/kconfig/symbol.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3*1da177e4SLinus Torvalds  * Released under the terms of the GNU GPL v2.0.
4*1da177e4SLinus Torvalds  */
5*1da177e4SLinus Torvalds 
6*1da177e4SLinus Torvalds #include <ctype.h>
7*1da177e4SLinus Torvalds #include <stdlib.h>
8*1da177e4SLinus Torvalds #include <string.h>
9*1da177e4SLinus Torvalds #include <regex.h>
10*1da177e4SLinus Torvalds #include <sys/utsname.h>
11*1da177e4SLinus Torvalds 
12*1da177e4SLinus Torvalds #define LKC_DIRECT_LINK
13*1da177e4SLinus Torvalds #include "lkc.h"
14*1da177e4SLinus Torvalds 
15*1da177e4SLinus Torvalds struct symbol symbol_yes = {
16*1da177e4SLinus Torvalds 	.name = "y",
17*1da177e4SLinus Torvalds 	.curr = { "y", yes },
18*1da177e4SLinus Torvalds 	.flags = SYMBOL_YES|SYMBOL_VALID,
19*1da177e4SLinus Torvalds }, symbol_mod = {
20*1da177e4SLinus Torvalds 	.name = "m",
21*1da177e4SLinus Torvalds 	.curr = { "m", mod },
22*1da177e4SLinus Torvalds 	.flags = SYMBOL_MOD|SYMBOL_VALID,
23*1da177e4SLinus Torvalds }, symbol_no = {
24*1da177e4SLinus Torvalds 	.name = "n",
25*1da177e4SLinus Torvalds 	.curr = { "n", no },
26*1da177e4SLinus Torvalds 	.flags = SYMBOL_NO|SYMBOL_VALID,
27*1da177e4SLinus Torvalds }, symbol_empty = {
28*1da177e4SLinus Torvalds 	.name = "",
29*1da177e4SLinus Torvalds 	.curr = { "", no },
30*1da177e4SLinus Torvalds 	.flags = SYMBOL_VALID,
31*1da177e4SLinus Torvalds };
32*1da177e4SLinus Torvalds 
33*1da177e4SLinus Torvalds int sym_change_count;
34*1da177e4SLinus Torvalds struct symbol *modules_sym;
35*1da177e4SLinus Torvalds tristate modules_val;
36*1da177e4SLinus Torvalds 
37*1da177e4SLinus Torvalds void sym_add_default(struct symbol *sym, const char *def)
38*1da177e4SLinus Torvalds {
39*1da177e4SLinus Torvalds 	struct property *prop = prop_alloc(P_DEFAULT, sym);
40*1da177e4SLinus Torvalds 
41*1da177e4SLinus Torvalds 	prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
42*1da177e4SLinus Torvalds }
43*1da177e4SLinus Torvalds 
44*1da177e4SLinus Torvalds void sym_init(void)
45*1da177e4SLinus Torvalds {
46*1da177e4SLinus Torvalds 	struct symbol *sym;
47*1da177e4SLinus Torvalds 	struct utsname uts;
48*1da177e4SLinus Torvalds 	char *p;
49*1da177e4SLinus Torvalds 	static bool inited = false;
50*1da177e4SLinus Torvalds 
51*1da177e4SLinus Torvalds 	if (inited)
52*1da177e4SLinus Torvalds 		return;
53*1da177e4SLinus Torvalds 	inited = true;
54*1da177e4SLinus Torvalds 
55*1da177e4SLinus Torvalds 	uname(&uts);
56*1da177e4SLinus Torvalds 
57*1da177e4SLinus Torvalds 	sym = sym_lookup("ARCH", 0);
58*1da177e4SLinus Torvalds 	sym->type = S_STRING;
59*1da177e4SLinus Torvalds 	sym->flags |= SYMBOL_AUTO;
60*1da177e4SLinus Torvalds 	p = getenv("ARCH");
61*1da177e4SLinus Torvalds 	if (p)
62*1da177e4SLinus Torvalds 		sym_add_default(sym, p);
63*1da177e4SLinus Torvalds 
64*1da177e4SLinus Torvalds 	sym = sym_lookup("KERNELRELEASE", 0);
65*1da177e4SLinus Torvalds 	sym->type = S_STRING;
66*1da177e4SLinus Torvalds 	sym->flags |= SYMBOL_AUTO;
67*1da177e4SLinus Torvalds 	p = getenv("KERNELRELEASE");
68*1da177e4SLinus Torvalds 	if (p)
69*1da177e4SLinus Torvalds 		sym_add_default(sym, p);
70*1da177e4SLinus Torvalds 
71*1da177e4SLinus Torvalds 	sym = sym_lookup("UNAME_RELEASE", 0);
72*1da177e4SLinus Torvalds 	sym->type = S_STRING;
73*1da177e4SLinus Torvalds 	sym->flags |= SYMBOL_AUTO;
74*1da177e4SLinus Torvalds 	sym_add_default(sym, uts.release);
75*1da177e4SLinus Torvalds }
76*1da177e4SLinus Torvalds 
77*1da177e4SLinus Torvalds enum symbol_type sym_get_type(struct symbol *sym)
78*1da177e4SLinus Torvalds {
79*1da177e4SLinus Torvalds 	enum symbol_type type = sym->type;
80*1da177e4SLinus Torvalds 
81*1da177e4SLinus Torvalds 	if (type == S_TRISTATE) {
82*1da177e4SLinus Torvalds 		if (sym_is_choice_value(sym) && sym->visible == yes)
83*1da177e4SLinus Torvalds 			type = S_BOOLEAN;
84*1da177e4SLinus Torvalds 		else if (modules_val == no)
85*1da177e4SLinus Torvalds 			type = S_BOOLEAN;
86*1da177e4SLinus Torvalds 	}
87*1da177e4SLinus Torvalds 	return type;
88*1da177e4SLinus Torvalds }
89*1da177e4SLinus Torvalds 
90*1da177e4SLinus Torvalds const char *sym_type_name(enum symbol_type type)
91*1da177e4SLinus Torvalds {
92*1da177e4SLinus Torvalds 	switch (type) {
93*1da177e4SLinus Torvalds 	case S_BOOLEAN:
94*1da177e4SLinus Torvalds 		return "boolean";
95*1da177e4SLinus Torvalds 	case S_TRISTATE:
96*1da177e4SLinus Torvalds 		return "tristate";
97*1da177e4SLinus Torvalds 	case S_INT:
98*1da177e4SLinus Torvalds 		return "integer";
99*1da177e4SLinus Torvalds 	case S_HEX:
100*1da177e4SLinus Torvalds 		return "hex";
101*1da177e4SLinus Torvalds 	case S_STRING:
102*1da177e4SLinus Torvalds 		return "string";
103*1da177e4SLinus Torvalds 	case S_UNKNOWN:
104*1da177e4SLinus Torvalds 		return "unknown";
105*1da177e4SLinus Torvalds 	case S_OTHER:
106*1da177e4SLinus Torvalds 		break;
107*1da177e4SLinus Torvalds 	}
108*1da177e4SLinus Torvalds 	return "???";
109*1da177e4SLinus Torvalds }
110*1da177e4SLinus Torvalds 
111*1da177e4SLinus Torvalds struct property *sym_get_choice_prop(struct symbol *sym)
112*1da177e4SLinus Torvalds {
113*1da177e4SLinus Torvalds 	struct property *prop;
114*1da177e4SLinus Torvalds 
115*1da177e4SLinus Torvalds 	for_all_choices(sym, prop)
116*1da177e4SLinus Torvalds 		return prop;
117*1da177e4SLinus Torvalds 	return NULL;
118*1da177e4SLinus Torvalds }
119*1da177e4SLinus Torvalds 
120*1da177e4SLinus Torvalds struct property *sym_get_default_prop(struct symbol *sym)
121*1da177e4SLinus Torvalds {
122*1da177e4SLinus Torvalds 	struct property *prop;
123*1da177e4SLinus Torvalds 
124*1da177e4SLinus Torvalds 	for_all_defaults(sym, prop) {
125*1da177e4SLinus Torvalds 		prop->visible.tri = expr_calc_value(prop->visible.expr);
126*1da177e4SLinus Torvalds 		if (prop->visible.tri != no)
127*1da177e4SLinus Torvalds 			return prop;
128*1da177e4SLinus Torvalds 	}
129*1da177e4SLinus Torvalds 	return NULL;
130*1da177e4SLinus Torvalds }
131*1da177e4SLinus Torvalds 
132*1da177e4SLinus Torvalds struct property *sym_get_range_prop(struct symbol *sym)
133*1da177e4SLinus Torvalds {
134*1da177e4SLinus Torvalds 	struct property *prop;
135*1da177e4SLinus Torvalds 
136*1da177e4SLinus Torvalds 	for_all_properties(sym, prop, P_RANGE) {
137*1da177e4SLinus Torvalds 		prop->visible.tri = expr_calc_value(prop->visible.expr);
138*1da177e4SLinus Torvalds 		if (prop->visible.tri != no)
139*1da177e4SLinus Torvalds 			return prop;
140*1da177e4SLinus Torvalds 	}
141*1da177e4SLinus Torvalds 	return NULL;
142*1da177e4SLinus Torvalds }
143*1da177e4SLinus Torvalds 
144*1da177e4SLinus Torvalds static void sym_calc_visibility(struct symbol *sym)
145*1da177e4SLinus Torvalds {
146*1da177e4SLinus Torvalds 	struct property *prop;
147*1da177e4SLinus Torvalds 	tristate tri;
148*1da177e4SLinus Torvalds 
149*1da177e4SLinus Torvalds 	/* any prompt visible? */
150*1da177e4SLinus Torvalds 	tri = no;
151*1da177e4SLinus Torvalds 	for_all_prompts(sym, prop) {
152*1da177e4SLinus Torvalds 		prop->visible.tri = expr_calc_value(prop->visible.expr);
153*1da177e4SLinus Torvalds 		tri = E_OR(tri, prop->visible.tri);
154*1da177e4SLinus Torvalds 	}
155*1da177e4SLinus Torvalds 	if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
156*1da177e4SLinus Torvalds 		tri = yes;
157*1da177e4SLinus Torvalds 	if (sym->visible != tri) {
158*1da177e4SLinus Torvalds 		sym->visible = tri;
159*1da177e4SLinus Torvalds 		sym_set_changed(sym);
160*1da177e4SLinus Torvalds 	}
161*1da177e4SLinus Torvalds 	if (sym_is_choice_value(sym))
162*1da177e4SLinus Torvalds 		return;
163*1da177e4SLinus Torvalds 	tri = no;
164*1da177e4SLinus Torvalds 	if (sym->rev_dep.expr)
165*1da177e4SLinus Torvalds 		tri = expr_calc_value(sym->rev_dep.expr);
166*1da177e4SLinus Torvalds 	if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
167*1da177e4SLinus Torvalds 		tri = yes;
168*1da177e4SLinus Torvalds 	if (sym->rev_dep.tri != tri) {
169*1da177e4SLinus Torvalds 		sym->rev_dep.tri = tri;
170*1da177e4SLinus Torvalds 		sym_set_changed(sym);
171*1da177e4SLinus Torvalds 	}
172*1da177e4SLinus Torvalds }
173*1da177e4SLinus Torvalds 
174*1da177e4SLinus Torvalds static struct symbol *sym_calc_choice(struct symbol *sym)
175*1da177e4SLinus Torvalds {
176*1da177e4SLinus Torvalds 	struct symbol *def_sym;
177*1da177e4SLinus Torvalds 	struct property *prop;
178*1da177e4SLinus Torvalds 	struct expr *e;
179*1da177e4SLinus Torvalds 
180*1da177e4SLinus Torvalds 	/* is the user choice visible? */
181*1da177e4SLinus Torvalds 	def_sym = sym->user.val;
182*1da177e4SLinus Torvalds 	if (def_sym) {
183*1da177e4SLinus Torvalds 		sym_calc_visibility(def_sym);
184*1da177e4SLinus Torvalds 		if (def_sym->visible != no)
185*1da177e4SLinus Torvalds 			return def_sym;
186*1da177e4SLinus Torvalds 	}
187*1da177e4SLinus Torvalds 
188*1da177e4SLinus Torvalds 	/* any of the defaults visible? */
189*1da177e4SLinus Torvalds 	for_all_defaults(sym, prop) {
190*1da177e4SLinus Torvalds 		prop->visible.tri = expr_calc_value(prop->visible.expr);
191*1da177e4SLinus Torvalds 		if (prop->visible.tri == no)
192*1da177e4SLinus Torvalds 			continue;
193*1da177e4SLinus Torvalds 		def_sym = prop_get_symbol(prop);
194*1da177e4SLinus Torvalds 		sym_calc_visibility(def_sym);
195*1da177e4SLinus Torvalds 		if (def_sym->visible != no)
196*1da177e4SLinus Torvalds 			return def_sym;
197*1da177e4SLinus Torvalds 	}
198*1da177e4SLinus Torvalds 
199*1da177e4SLinus Torvalds 	/* just get the first visible value */
200*1da177e4SLinus Torvalds 	prop = sym_get_choice_prop(sym);
201*1da177e4SLinus Torvalds 	for (e = prop->expr; e; e = e->left.expr) {
202*1da177e4SLinus Torvalds 		def_sym = e->right.sym;
203*1da177e4SLinus Torvalds 		sym_calc_visibility(def_sym);
204*1da177e4SLinus Torvalds 		if (def_sym->visible != no)
205*1da177e4SLinus Torvalds 			return def_sym;
206*1da177e4SLinus Torvalds 	}
207*1da177e4SLinus Torvalds 
208*1da177e4SLinus Torvalds 	/* no choice? reset tristate value */
209*1da177e4SLinus Torvalds 	sym->curr.tri = no;
210*1da177e4SLinus Torvalds 	return NULL;
211*1da177e4SLinus Torvalds }
212*1da177e4SLinus Torvalds 
213*1da177e4SLinus Torvalds void sym_calc_value(struct symbol *sym)
214*1da177e4SLinus Torvalds {
215*1da177e4SLinus Torvalds 	struct symbol_value newval, oldval;
216*1da177e4SLinus Torvalds 	struct property *prop;
217*1da177e4SLinus Torvalds 	struct expr *e;
218*1da177e4SLinus Torvalds 
219*1da177e4SLinus Torvalds 	if (!sym)
220*1da177e4SLinus Torvalds 		return;
221*1da177e4SLinus Torvalds 
222*1da177e4SLinus Torvalds 	if (sym->flags & SYMBOL_VALID)
223*1da177e4SLinus Torvalds 		return;
224*1da177e4SLinus Torvalds 	sym->flags |= SYMBOL_VALID;
225*1da177e4SLinus Torvalds 
226*1da177e4SLinus Torvalds 	oldval = sym->curr;
227*1da177e4SLinus Torvalds 
228*1da177e4SLinus Torvalds 	switch (sym->type) {
229*1da177e4SLinus Torvalds 	case S_INT:
230*1da177e4SLinus Torvalds 	case S_HEX:
231*1da177e4SLinus Torvalds 	case S_STRING:
232*1da177e4SLinus Torvalds 		newval = symbol_empty.curr;
233*1da177e4SLinus Torvalds 		break;
234*1da177e4SLinus Torvalds 	case S_BOOLEAN:
235*1da177e4SLinus Torvalds 	case S_TRISTATE:
236*1da177e4SLinus Torvalds 		newval = symbol_no.curr;
237*1da177e4SLinus Torvalds 		break;
238*1da177e4SLinus Torvalds 	default:
239*1da177e4SLinus Torvalds 		sym->curr.val = sym->name;
240*1da177e4SLinus Torvalds 		sym->curr.tri = no;
241*1da177e4SLinus Torvalds 		return;
242*1da177e4SLinus Torvalds 	}
243*1da177e4SLinus Torvalds 	if (!sym_is_choice_value(sym))
244*1da177e4SLinus Torvalds 		sym->flags &= ~SYMBOL_WRITE;
245*1da177e4SLinus Torvalds 
246*1da177e4SLinus Torvalds 	sym_calc_visibility(sym);
247*1da177e4SLinus Torvalds 
248*1da177e4SLinus Torvalds 	/* set default if recursively called */
249*1da177e4SLinus Torvalds 	sym->curr = newval;
250*1da177e4SLinus Torvalds 
251*1da177e4SLinus Torvalds 	switch (sym_get_type(sym)) {
252*1da177e4SLinus Torvalds 	case S_BOOLEAN:
253*1da177e4SLinus Torvalds 	case S_TRISTATE:
254*1da177e4SLinus Torvalds 		if (sym_is_choice_value(sym) && sym->visible == yes) {
255*1da177e4SLinus Torvalds 			prop = sym_get_choice_prop(sym);
256*1da177e4SLinus Torvalds 			newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
257*1da177e4SLinus Torvalds 		} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
258*1da177e4SLinus Torvalds 			sym->flags |= SYMBOL_WRITE;
259*1da177e4SLinus Torvalds 			if (sym_has_value(sym))
260*1da177e4SLinus Torvalds 				newval.tri = sym->user.tri;
261*1da177e4SLinus Torvalds 			else if (!sym_is_choice(sym)) {
262*1da177e4SLinus Torvalds 				prop = sym_get_default_prop(sym);
263*1da177e4SLinus Torvalds 				if (prop)
264*1da177e4SLinus Torvalds 					newval.tri = expr_calc_value(prop->expr);
265*1da177e4SLinus Torvalds 			}
266*1da177e4SLinus Torvalds 			newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
267*1da177e4SLinus Torvalds 		} else if (!sym_is_choice(sym)) {
268*1da177e4SLinus Torvalds 			prop = sym_get_default_prop(sym);
269*1da177e4SLinus Torvalds 			if (prop) {
270*1da177e4SLinus Torvalds 				sym->flags |= SYMBOL_WRITE;
271*1da177e4SLinus Torvalds 				newval.tri = expr_calc_value(prop->expr);
272*1da177e4SLinus Torvalds 			}
273*1da177e4SLinus Torvalds 		}
274*1da177e4SLinus Torvalds 		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
275*1da177e4SLinus Torvalds 			newval.tri = yes;
276*1da177e4SLinus Torvalds 		break;
277*1da177e4SLinus Torvalds 	case S_STRING:
278*1da177e4SLinus Torvalds 	case S_HEX:
279*1da177e4SLinus Torvalds 	case S_INT:
280*1da177e4SLinus Torvalds 		if (sym->visible != no) {
281*1da177e4SLinus Torvalds 			sym->flags |= SYMBOL_WRITE;
282*1da177e4SLinus Torvalds 			if (sym_has_value(sym)) {
283*1da177e4SLinus Torvalds 				newval.val = sym->user.val;
284*1da177e4SLinus Torvalds 				break;
285*1da177e4SLinus Torvalds 			}
286*1da177e4SLinus Torvalds 		}
287*1da177e4SLinus Torvalds 		prop = sym_get_default_prop(sym);
288*1da177e4SLinus Torvalds 		if (prop) {
289*1da177e4SLinus Torvalds 			struct symbol *ds = prop_get_symbol(prop);
290*1da177e4SLinus Torvalds 			if (ds) {
291*1da177e4SLinus Torvalds 				sym->flags |= SYMBOL_WRITE;
292*1da177e4SLinus Torvalds 				sym_calc_value(ds);
293*1da177e4SLinus Torvalds 				newval.val = ds->curr.val;
294*1da177e4SLinus Torvalds 			}
295*1da177e4SLinus Torvalds 		}
296*1da177e4SLinus Torvalds 		break;
297*1da177e4SLinus Torvalds 	default:
298*1da177e4SLinus Torvalds 		;
299*1da177e4SLinus Torvalds 	}
300*1da177e4SLinus Torvalds 
301*1da177e4SLinus Torvalds 	sym->curr = newval;
302*1da177e4SLinus Torvalds 	if (sym_is_choice(sym) && newval.tri == yes)
303*1da177e4SLinus Torvalds 		sym->curr.val = sym_calc_choice(sym);
304*1da177e4SLinus Torvalds 
305*1da177e4SLinus Torvalds 	if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
306*1da177e4SLinus Torvalds 		sym_set_changed(sym);
307*1da177e4SLinus Torvalds 	if (modules_sym == sym)
308*1da177e4SLinus Torvalds 		modules_val = modules_sym->curr.tri;
309*1da177e4SLinus Torvalds 
310*1da177e4SLinus Torvalds 	if (sym_is_choice(sym)) {
311*1da177e4SLinus Torvalds 		int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
312*1da177e4SLinus Torvalds 		prop = sym_get_choice_prop(sym);
313*1da177e4SLinus Torvalds 		for (e = prop->expr; e; e = e->left.expr) {
314*1da177e4SLinus Torvalds 			e->right.sym->flags |= flags;
315*1da177e4SLinus Torvalds 			if (flags & SYMBOL_CHANGED)
316*1da177e4SLinus Torvalds 				sym_set_changed(e->right.sym);
317*1da177e4SLinus Torvalds 		}
318*1da177e4SLinus Torvalds 	}
319*1da177e4SLinus Torvalds }
320*1da177e4SLinus Torvalds 
321*1da177e4SLinus Torvalds void sym_clear_all_valid(void)
322*1da177e4SLinus Torvalds {
323*1da177e4SLinus Torvalds 	struct symbol *sym;
324*1da177e4SLinus Torvalds 	int i;
325*1da177e4SLinus Torvalds 
326*1da177e4SLinus Torvalds 	for_all_symbols(i, sym)
327*1da177e4SLinus Torvalds 		sym->flags &= ~SYMBOL_VALID;
328*1da177e4SLinus Torvalds 	sym_change_count++;
329*1da177e4SLinus Torvalds 	if (modules_sym)
330*1da177e4SLinus Torvalds 		sym_calc_value(modules_sym);
331*1da177e4SLinus Torvalds }
332*1da177e4SLinus Torvalds 
333*1da177e4SLinus Torvalds void sym_set_changed(struct symbol *sym)
334*1da177e4SLinus Torvalds {
335*1da177e4SLinus Torvalds 	struct property *prop;
336*1da177e4SLinus Torvalds 
337*1da177e4SLinus Torvalds 	sym->flags |= SYMBOL_CHANGED;
338*1da177e4SLinus Torvalds 	for (prop = sym->prop; prop; prop = prop->next) {
339*1da177e4SLinus Torvalds 		if (prop->menu)
340*1da177e4SLinus Torvalds 			prop->menu->flags |= MENU_CHANGED;
341*1da177e4SLinus Torvalds 	}
342*1da177e4SLinus Torvalds }
343*1da177e4SLinus Torvalds 
344*1da177e4SLinus Torvalds void sym_set_all_changed(void)
345*1da177e4SLinus Torvalds {
346*1da177e4SLinus Torvalds 	struct symbol *sym;
347*1da177e4SLinus Torvalds 	int i;
348*1da177e4SLinus Torvalds 
349*1da177e4SLinus Torvalds 	for_all_symbols(i, sym)
350*1da177e4SLinus Torvalds 		sym_set_changed(sym);
351*1da177e4SLinus Torvalds }
352*1da177e4SLinus Torvalds 
353*1da177e4SLinus Torvalds bool sym_tristate_within_range(struct symbol *sym, tristate val)
354*1da177e4SLinus Torvalds {
355*1da177e4SLinus Torvalds 	int type = sym_get_type(sym);
356*1da177e4SLinus Torvalds 
357*1da177e4SLinus Torvalds 	if (sym->visible == no)
358*1da177e4SLinus Torvalds 		return false;
359*1da177e4SLinus Torvalds 
360*1da177e4SLinus Torvalds 	if (type != S_BOOLEAN && type != S_TRISTATE)
361*1da177e4SLinus Torvalds 		return false;
362*1da177e4SLinus Torvalds 
363*1da177e4SLinus Torvalds 	if (type == S_BOOLEAN && val == mod)
364*1da177e4SLinus Torvalds 		return false;
365*1da177e4SLinus Torvalds 	if (sym->visible <= sym->rev_dep.tri)
366*1da177e4SLinus Torvalds 		return false;
367*1da177e4SLinus Torvalds 	if (sym_is_choice_value(sym) && sym->visible == yes)
368*1da177e4SLinus Torvalds 		return val == yes;
369*1da177e4SLinus Torvalds 	return val >= sym->rev_dep.tri && val <= sym->visible;
370*1da177e4SLinus Torvalds }
371*1da177e4SLinus Torvalds 
372*1da177e4SLinus Torvalds bool sym_set_tristate_value(struct symbol *sym, tristate val)
373*1da177e4SLinus Torvalds {
374*1da177e4SLinus Torvalds 	tristate oldval = sym_get_tristate_value(sym);
375*1da177e4SLinus Torvalds 
376*1da177e4SLinus Torvalds 	if (oldval != val && !sym_tristate_within_range(sym, val))
377*1da177e4SLinus Torvalds 		return false;
378*1da177e4SLinus Torvalds 
379*1da177e4SLinus Torvalds 	if (sym->flags & SYMBOL_NEW) {
380*1da177e4SLinus Torvalds 		sym->flags &= ~SYMBOL_NEW;
381*1da177e4SLinus Torvalds 		sym_set_changed(sym);
382*1da177e4SLinus Torvalds 	}
383*1da177e4SLinus Torvalds 	if (sym_is_choice_value(sym) && val == yes) {
384*1da177e4SLinus Torvalds 		struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
385*1da177e4SLinus Torvalds 
386*1da177e4SLinus Torvalds 		cs->user.val = sym;
387*1da177e4SLinus Torvalds 		cs->flags &= ~SYMBOL_NEW;
388*1da177e4SLinus Torvalds 	}
389*1da177e4SLinus Torvalds 
390*1da177e4SLinus Torvalds 	sym->user.tri = val;
391*1da177e4SLinus Torvalds 	if (oldval != val) {
392*1da177e4SLinus Torvalds 		sym_clear_all_valid();
393*1da177e4SLinus Torvalds 		if (sym == modules_sym)
394*1da177e4SLinus Torvalds 			sym_set_all_changed();
395*1da177e4SLinus Torvalds 	}
396*1da177e4SLinus Torvalds 
397*1da177e4SLinus Torvalds 	return true;
398*1da177e4SLinus Torvalds }
399*1da177e4SLinus Torvalds 
400*1da177e4SLinus Torvalds tristate sym_toggle_tristate_value(struct symbol *sym)
401*1da177e4SLinus Torvalds {
402*1da177e4SLinus Torvalds 	tristate oldval, newval;
403*1da177e4SLinus Torvalds 
404*1da177e4SLinus Torvalds 	oldval = newval = sym_get_tristate_value(sym);
405*1da177e4SLinus Torvalds 	do {
406*1da177e4SLinus Torvalds 		switch (newval) {
407*1da177e4SLinus Torvalds 		case no:
408*1da177e4SLinus Torvalds 			newval = mod;
409*1da177e4SLinus Torvalds 			break;
410*1da177e4SLinus Torvalds 		case mod:
411*1da177e4SLinus Torvalds 			newval = yes;
412*1da177e4SLinus Torvalds 			break;
413*1da177e4SLinus Torvalds 		case yes:
414*1da177e4SLinus Torvalds 			newval = no;
415*1da177e4SLinus Torvalds 			break;
416*1da177e4SLinus Torvalds 		}
417*1da177e4SLinus Torvalds 		if (sym_set_tristate_value(sym, newval))
418*1da177e4SLinus Torvalds 			break;
419*1da177e4SLinus Torvalds 	} while (oldval != newval);
420*1da177e4SLinus Torvalds 	return newval;
421*1da177e4SLinus Torvalds }
422*1da177e4SLinus Torvalds 
423*1da177e4SLinus Torvalds bool sym_string_valid(struct symbol *sym, const char *str)
424*1da177e4SLinus Torvalds {
425*1da177e4SLinus Torvalds 	signed char ch;
426*1da177e4SLinus Torvalds 
427*1da177e4SLinus Torvalds 	switch (sym->type) {
428*1da177e4SLinus Torvalds 	case S_STRING:
429*1da177e4SLinus Torvalds 		return true;
430*1da177e4SLinus Torvalds 	case S_INT:
431*1da177e4SLinus Torvalds 		ch = *str++;
432*1da177e4SLinus Torvalds 		if (ch == '-')
433*1da177e4SLinus Torvalds 			ch = *str++;
434*1da177e4SLinus Torvalds 		if (!isdigit(ch))
435*1da177e4SLinus Torvalds 			return false;
436*1da177e4SLinus Torvalds 		if (ch == '0' && *str != 0)
437*1da177e4SLinus Torvalds 			return false;
438*1da177e4SLinus Torvalds 		while ((ch = *str++)) {
439*1da177e4SLinus Torvalds 			if (!isdigit(ch))
440*1da177e4SLinus Torvalds 				return false;
441*1da177e4SLinus Torvalds 		}
442*1da177e4SLinus Torvalds 		return true;
443*1da177e4SLinus Torvalds 	case S_HEX:
444*1da177e4SLinus Torvalds 		if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
445*1da177e4SLinus Torvalds 			str += 2;
446*1da177e4SLinus Torvalds 		ch = *str++;
447*1da177e4SLinus Torvalds 		do {
448*1da177e4SLinus Torvalds 			if (!isxdigit(ch))
449*1da177e4SLinus Torvalds 				return false;
450*1da177e4SLinus Torvalds 		} while ((ch = *str++));
451*1da177e4SLinus Torvalds 		return true;
452*1da177e4SLinus Torvalds 	case S_BOOLEAN:
453*1da177e4SLinus Torvalds 	case S_TRISTATE:
454*1da177e4SLinus Torvalds 		switch (str[0]) {
455*1da177e4SLinus Torvalds 		case 'y': case 'Y':
456*1da177e4SLinus Torvalds 		case 'm': case 'M':
457*1da177e4SLinus Torvalds 		case 'n': case 'N':
458*1da177e4SLinus Torvalds 			return true;
459*1da177e4SLinus Torvalds 		}
460*1da177e4SLinus Torvalds 		return false;
461*1da177e4SLinus Torvalds 	default:
462*1da177e4SLinus Torvalds 		return false;
463*1da177e4SLinus Torvalds 	}
464*1da177e4SLinus Torvalds }
465*1da177e4SLinus Torvalds 
466*1da177e4SLinus Torvalds bool sym_string_within_range(struct symbol *sym, const char *str)
467*1da177e4SLinus Torvalds {
468*1da177e4SLinus Torvalds 	struct property *prop;
469*1da177e4SLinus Torvalds 	int val;
470*1da177e4SLinus Torvalds 
471*1da177e4SLinus Torvalds 	switch (sym->type) {
472*1da177e4SLinus Torvalds 	case S_STRING:
473*1da177e4SLinus Torvalds 		return sym_string_valid(sym, str);
474*1da177e4SLinus Torvalds 	case S_INT:
475*1da177e4SLinus Torvalds 		if (!sym_string_valid(sym, str))
476*1da177e4SLinus Torvalds 			return false;
477*1da177e4SLinus Torvalds 		prop = sym_get_range_prop(sym);
478*1da177e4SLinus Torvalds 		if (!prop)
479*1da177e4SLinus Torvalds 			return true;
480*1da177e4SLinus Torvalds 		val = strtol(str, NULL, 10);
481*1da177e4SLinus Torvalds 		return val >= strtol(prop->expr->left.sym->name, NULL, 10) &&
482*1da177e4SLinus Torvalds 		       val <= strtol(prop->expr->right.sym->name, NULL, 10);
483*1da177e4SLinus Torvalds 	case S_HEX:
484*1da177e4SLinus Torvalds 		if (!sym_string_valid(sym, str))
485*1da177e4SLinus Torvalds 			return false;
486*1da177e4SLinus Torvalds 		prop = sym_get_range_prop(sym);
487*1da177e4SLinus Torvalds 		if (!prop)
488*1da177e4SLinus Torvalds 			return true;
489*1da177e4SLinus Torvalds 		val = strtol(str, NULL, 16);
490*1da177e4SLinus Torvalds 		return val >= strtol(prop->expr->left.sym->name, NULL, 16) &&
491*1da177e4SLinus Torvalds 		       val <= strtol(prop->expr->right.sym->name, NULL, 16);
492*1da177e4SLinus Torvalds 	case S_BOOLEAN:
493*1da177e4SLinus Torvalds 	case S_TRISTATE:
494*1da177e4SLinus Torvalds 		switch (str[0]) {
495*1da177e4SLinus Torvalds 		case 'y': case 'Y':
496*1da177e4SLinus Torvalds 			return sym_tristate_within_range(sym, yes);
497*1da177e4SLinus Torvalds 		case 'm': case 'M':
498*1da177e4SLinus Torvalds 			return sym_tristate_within_range(sym, mod);
499*1da177e4SLinus Torvalds 		case 'n': case 'N':
500*1da177e4SLinus Torvalds 			return sym_tristate_within_range(sym, no);
501*1da177e4SLinus Torvalds 		}
502*1da177e4SLinus Torvalds 		return false;
503*1da177e4SLinus Torvalds 	default:
504*1da177e4SLinus Torvalds 		return false;
505*1da177e4SLinus Torvalds 	}
506*1da177e4SLinus Torvalds }
507*1da177e4SLinus Torvalds 
508*1da177e4SLinus Torvalds bool sym_set_string_value(struct symbol *sym, const char *newval)
509*1da177e4SLinus Torvalds {
510*1da177e4SLinus Torvalds 	const char *oldval;
511*1da177e4SLinus Torvalds 	char *val;
512*1da177e4SLinus Torvalds 	int size;
513*1da177e4SLinus Torvalds 
514*1da177e4SLinus Torvalds 	switch (sym->type) {
515*1da177e4SLinus Torvalds 	case S_BOOLEAN:
516*1da177e4SLinus Torvalds 	case S_TRISTATE:
517*1da177e4SLinus Torvalds 		switch (newval[0]) {
518*1da177e4SLinus Torvalds 		case 'y': case 'Y':
519*1da177e4SLinus Torvalds 			return sym_set_tristate_value(sym, yes);
520*1da177e4SLinus Torvalds 		case 'm': case 'M':
521*1da177e4SLinus Torvalds 			return sym_set_tristate_value(sym, mod);
522*1da177e4SLinus Torvalds 		case 'n': case 'N':
523*1da177e4SLinus Torvalds 			return sym_set_tristate_value(sym, no);
524*1da177e4SLinus Torvalds 		}
525*1da177e4SLinus Torvalds 		return false;
526*1da177e4SLinus Torvalds 	default:
527*1da177e4SLinus Torvalds 		;
528*1da177e4SLinus Torvalds 	}
529*1da177e4SLinus Torvalds 
530*1da177e4SLinus Torvalds 	if (!sym_string_within_range(sym, newval))
531*1da177e4SLinus Torvalds 		return false;
532*1da177e4SLinus Torvalds 
533*1da177e4SLinus Torvalds 	if (sym->flags & SYMBOL_NEW) {
534*1da177e4SLinus Torvalds 		sym->flags &= ~SYMBOL_NEW;
535*1da177e4SLinus Torvalds 		sym_set_changed(sym);
536*1da177e4SLinus Torvalds 	}
537*1da177e4SLinus Torvalds 
538*1da177e4SLinus Torvalds 	oldval = sym->user.val;
539*1da177e4SLinus Torvalds 	size = strlen(newval) + 1;
540*1da177e4SLinus Torvalds 	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
541*1da177e4SLinus Torvalds 		size += 2;
542*1da177e4SLinus Torvalds 		sym->user.val = val = malloc(size);
543*1da177e4SLinus Torvalds 		*val++ = '0';
544*1da177e4SLinus Torvalds 		*val++ = 'x';
545*1da177e4SLinus Torvalds 	} else if (!oldval || strcmp(oldval, newval))
546*1da177e4SLinus Torvalds 		sym->user.val = val = malloc(size);
547*1da177e4SLinus Torvalds 	else
548*1da177e4SLinus Torvalds 		return true;
549*1da177e4SLinus Torvalds 
550*1da177e4SLinus Torvalds 	strcpy(val, newval);
551*1da177e4SLinus Torvalds 	free((void *)oldval);
552*1da177e4SLinus Torvalds 	sym_clear_all_valid();
553*1da177e4SLinus Torvalds 
554*1da177e4SLinus Torvalds 	return true;
555*1da177e4SLinus Torvalds }
556*1da177e4SLinus Torvalds 
557*1da177e4SLinus Torvalds const char *sym_get_string_value(struct symbol *sym)
558*1da177e4SLinus Torvalds {
559*1da177e4SLinus Torvalds 	tristate val;
560*1da177e4SLinus Torvalds 
561*1da177e4SLinus Torvalds 	switch (sym->type) {
562*1da177e4SLinus Torvalds 	case S_BOOLEAN:
563*1da177e4SLinus Torvalds 	case S_TRISTATE:
564*1da177e4SLinus Torvalds 		val = sym_get_tristate_value(sym);
565*1da177e4SLinus Torvalds 		switch (val) {
566*1da177e4SLinus Torvalds 		case no:
567*1da177e4SLinus Torvalds 			return "n";
568*1da177e4SLinus Torvalds 		case mod:
569*1da177e4SLinus Torvalds 			return "m";
570*1da177e4SLinus Torvalds 		case yes:
571*1da177e4SLinus Torvalds 			return "y";
572*1da177e4SLinus Torvalds 		}
573*1da177e4SLinus Torvalds 		break;
574*1da177e4SLinus Torvalds 	default:
575*1da177e4SLinus Torvalds 		;
576*1da177e4SLinus Torvalds 	}
577*1da177e4SLinus Torvalds 	return (const char *)sym->curr.val;
578*1da177e4SLinus Torvalds }
579*1da177e4SLinus Torvalds 
580*1da177e4SLinus Torvalds bool sym_is_changable(struct symbol *sym)
581*1da177e4SLinus Torvalds {
582*1da177e4SLinus Torvalds 	return sym->visible > sym->rev_dep.tri;
583*1da177e4SLinus Torvalds }
584*1da177e4SLinus Torvalds 
585*1da177e4SLinus Torvalds struct symbol *sym_lookup(const char *name, int isconst)
586*1da177e4SLinus Torvalds {
587*1da177e4SLinus Torvalds 	struct symbol *symbol;
588*1da177e4SLinus Torvalds 	const char *ptr;
589*1da177e4SLinus Torvalds 	char *new_name;
590*1da177e4SLinus Torvalds 	int hash = 0;
591*1da177e4SLinus Torvalds 
592*1da177e4SLinus Torvalds 	if (name) {
593*1da177e4SLinus Torvalds 		if (name[0] && !name[1]) {
594*1da177e4SLinus Torvalds 			switch (name[0]) {
595*1da177e4SLinus Torvalds 			case 'y': return &symbol_yes;
596*1da177e4SLinus Torvalds 			case 'm': return &symbol_mod;
597*1da177e4SLinus Torvalds 			case 'n': return &symbol_no;
598*1da177e4SLinus Torvalds 			}
599*1da177e4SLinus Torvalds 		}
600*1da177e4SLinus Torvalds 		for (ptr = name; *ptr; ptr++)
601*1da177e4SLinus Torvalds 			hash += *ptr;
602*1da177e4SLinus Torvalds 		hash &= 0xff;
603*1da177e4SLinus Torvalds 
604*1da177e4SLinus Torvalds 		for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
605*1da177e4SLinus Torvalds 			if (!strcmp(symbol->name, name)) {
606*1da177e4SLinus Torvalds 				if ((isconst && symbol->flags & SYMBOL_CONST) ||
607*1da177e4SLinus Torvalds 				    (!isconst && !(symbol->flags & SYMBOL_CONST)))
608*1da177e4SLinus Torvalds 					return symbol;
609*1da177e4SLinus Torvalds 			}
610*1da177e4SLinus Torvalds 		}
611*1da177e4SLinus Torvalds 		new_name = strdup(name);
612*1da177e4SLinus Torvalds 	} else {
613*1da177e4SLinus Torvalds 		new_name = NULL;
614*1da177e4SLinus Torvalds 		hash = 256;
615*1da177e4SLinus Torvalds 	}
616*1da177e4SLinus Torvalds 
617*1da177e4SLinus Torvalds 	symbol = malloc(sizeof(*symbol));
618*1da177e4SLinus Torvalds 	memset(symbol, 0, sizeof(*symbol));
619*1da177e4SLinus Torvalds 	symbol->name = new_name;
620*1da177e4SLinus Torvalds 	symbol->type = S_UNKNOWN;
621*1da177e4SLinus Torvalds 	symbol->flags = SYMBOL_NEW;
622*1da177e4SLinus Torvalds 	if (isconst)
623*1da177e4SLinus Torvalds 		symbol->flags |= SYMBOL_CONST;
624*1da177e4SLinus Torvalds 
625*1da177e4SLinus Torvalds 	symbol->next = symbol_hash[hash];
626*1da177e4SLinus Torvalds 	symbol_hash[hash] = symbol;
627*1da177e4SLinus Torvalds 
628*1da177e4SLinus Torvalds 	return symbol;
629*1da177e4SLinus Torvalds }
630*1da177e4SLinus Torvalds 
631*1da177e4SLinus Torvalds struct symbol *sym_find(const char *name)
632*1da177e4SLinus Torvalds {
633*1da177e4SLinus Torvalds 	struct symbol *symbol = NULL;
634*1da177e4SLinus Torvalds 	const char *ptr;
635*1da177e4SLinus Torvalds 	int hash = 0;
636*1da177e4SLinus Torvalds 
637*1da177e4SLinus Torvalds 	if (!name)
638*1da177e4SLinus Torvalds 		return NULL;
639*1da177e4SLinus Torvalds 
640*1da177e4SLinus Torvalds 	if (name[0] && !name[1]) {
641*1da177e4SLinus Torvalds 		switch (name[0]) {
642*1da177e4SLinus Torvalds 		case 'y': return &symbol_yes;
643*1da177e4SLinus Torvalds 		case 'm': return &symbol_mod;
644*1da177e4SLinus Torvalds 		case 'n': return &symbol_no;
645*1da177e4SLinus Torvalds 		}
646*1da177e4SLinus Torvalds 	}
647*1da177e4SLinus Torvalds 	for (ptr = name; *ptr; ptr++)
648*1da177e4SLinus Torvalds 		hash += *ptr;
649*1da177e4SLinus Torvalds 	hash &= 0xff;
650*1da177e4SLinus Torvalds 
651*1da177e4SLinus Torvalds 	for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
652*1da177e4SLinus Torvalds 		if (!strcmp(symbol->name, name) &&
653*1da177e4SLinus Torvalds 		    !(symbol->flags & SYMBOL_CONST))
654*1da177e4SLinus Torvalds 				break;
655*1da177e4SLinus Torvalds 	}
656*1da177e4SLinus Torvalds 
657*1da177e4SLinus Torvalds 	return symbol;
658*1da177e4SLinus Torvalds }
659*1da177e4SLinus Torvalds 
660*1da177e4SLinus Torvalds struct symbol **sym_re_search(const char *pattern)
661*1da177e4SLinus Torvalds {
662*1da177e4SLinus Torvalds 	struct symbol *sym, **sym_arr = NULL;
663*1da177e4SLinus Torvalds 	int i, cnt, size;
664*1da177e4SLinus Torvalds 	regex_t re;
665*1da177e4SLinus Torvalds 
666*1da177e4SLinus Torvalds 	cnt = size = 0;
667*1da177e4SLinus Torvalds 	/* Skip if empty */
668*1da177e4SLinus Torvalds 	if (strlen(pattern) == 0)
669*1da177e4SLinus Torvalds 		return NULL;
670*1da177e4SLinus Torvalds 	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
671*1da177e4SLinus Torvalds 		return NULL;
672*1da177e4SLinus Torvalds 
673*1da177e4SLinus Torvalds 	for_all_symbols(i, sym) {
674*1da177e4SLinus Torvalds 		if (sym->flags & SYMBOL_CONST || !sym->name)
675*1da177e4SLinus Torvalds 			continue;
676*1da177e4SLinus Torvalds 		if (regexec(&re, sym->name, 0, NULL, 0))
677*1da177e4SLinus Torvalds 			continue;
678*1da177e4SLinus Torvalds 		if (cnt + 1 >= size) {
679*1da177e4SLinus Torvalds 			void *tmp = sym_arr;
680*1da177e4SLinus Torvalds 			size += 16;
681*1da177e4SLinus Torvalds 			sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
682*1da177e4SLinus Torvalds 			if (!sym_arr) {
683*1da177e4SLinus Torvalds 				free(tmp);
684*1da177e4SLinus Torvalds 				return NULL;
685*1da177e4SLinus Torvalds 			}
686*1da177e4SLinus Torvalds 		}
687*1da177e4SLinus Torvalds 		sym_arr[cnt++] = sym;
688*1da177e4SLinus Torvalds 	}
689*1da177e4SLinus Torvalds 	if (sym_arr)
690*1da177e4SLinus Torvalds 		sym_arr[cnt] = NULL;
691*1da177e4SLinus Torvalds 	regfree(&re);
692*1da177e4SLinus Torvalds 
693*1da177e4SLinus Torvalds 	return sym_arr;
694*1da177e4SLinus Torvalds }
695*1da177e4SLinus Torvalds 
696*1da177e4SLinus Torvalds 
697*1da177e4SLinus Torvalds struct symbol *sym_check_deps(struct symbol *sym);
698*1da177e4SLinus Torvalds 
699*1da177e4SLinus Torvalds static struct symbol *sym_check_expr_deps(struct expr *e)
700*1da177e4SLinus Torvalds {
701*1da177e4SLinus Torvalds 	struct symbol *sym;
702*1da177e4SLinus Torvalds 
703*1da177e4SLinus Torvalds 	if (!e)
704*1da177e4SLinus Torvalds 		return NULL;
705*1da177e4SLinus Torvalds 	switch (e->type) {
706*1da177e4SLinus Torvalds 	case E_OR:
707*1da177e4SLinus Torvalds 	case E_AND:
708*1da177e4SLinus Torvalds 		sym = sym_check_expr_deps(e->left.expr);
709*1da177e4SLinus Torvalds 		if (sym)
710*1da177e4SLinus Torvalds 			return sym;
711*1da177e4SLinus Torvalds 		return sym_check_expr_deps(e->right.expr);
712*1da177e4SLinus Torvalds 	case E_NOT:
713*1da177e4SLinus Torvalds 		return sym_check_expr_deps(e->left.expr);
714*1da177e4SLinus Torvalds 	case E_EQUAL:
715*1da177e4SLinus Torvalds 	case E_UNEQUAL:
716*1da177e4SLinus Torvalds 		sym = sym_check_deps(e->left.sym);
717*1da177e4SLinus Torvalds 		if (sym)
718*1da177e4SLinus Torvalds 			return sym;
719*1da177e4SLinus Torvalds 		return sym_check_deps(e->right.sym);
720*1da177e4SLinus Torvalds 	case E_SYMBOL:
721*1da177e4SLinus Torvalds 		return sym_check_deps(e->left.sym);
722*1da177e4SLinus Torvalds 	default:
723*1da177e4SLinus Torvalds 		break;
724*1da177e4SLinus Torvalds 	}
725*1da177e4SLinus Torvalds 	printf("Oops! How to check %d?\n", e->type);
726*1da177e4SLinus Torvalds 	return NULL;
727*1da177e4SLinus Torvalds }
728*1da177e4SLinus Torvalds 
729*1da177e4SLinus Torvalds struct symbol *sym_check_deps(struct symbol *sym)
730*1da177e4SLinus Torvalds {
731*1da177e4SLinus Torvalds 	struct symbol *sym2;
732*1da177e4SLinus Torvalds 	struct property *prop;
733*1da177e4SLinus Torvalds 
734*1da177e4SLinus Torvalds 	if (sym->flags & SYMBOL_CHECK_DONE)
735*1da177e4SLinus Torvalds 		return NULL;
736*1da177e4SLinus Torvalds 	if (sym->flags & SYMBOL_CHECK) {
737*1da177e4SLinus Torvalds 		printf("Warning! Found recursive dependency: %s", sym->name);
738*1da177e4SLinus Torvalds 		return sym;
739*1da177e4SLinus Torvalds 	}
740*1da177e4SLinus Torvalds 
741*1da177e4SLinus Torvalds 	sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
742*1da177e4SLinus Torvalds 	sym2 = sym_check_expr_deps(sym->rev_dep.expr);
743*1da177e4SLinus Torvalds 	if (sym2)
744*1da177e4SLinus Torvalds 		goto out;
745*1da177e4SLinus Torvalds 
746*1da177e4SLinus Torvalds 	for (prop = sym->prop; prop; prop = prop->next) {
747*1da177e4SLinus Torvalds 		if (prop->type == P_CHOICE || prop->type == P_SELECT)
748*1da177e4SLinus Torvalds 			continue;
749*1da177e4SLinus Torvalds 		sym2 = sym_check_expr_deps(prop->visible.expr);
750*1da177e4SLinus Torvalds 		if (sym2)
751*1da177e4SLinus Torvalds 			goto out;
752*1da177e4SLinus Torvalds 		if (prop->type != P_DEFAULT || sym_is_choice(sym))
753*1da177e4SLinus Torvalds 			continue;
754*1da177e4SLinus Torvalds 		sym2 = sym_check_expr_deps(prop->expr);
755*1da177e4SLinus Torvalds 		if (sym2)
756*1da177e4SLinus Torvalds 			goto out;
757*1da177e4SLinus Torvalds 	}
758*1da177e4SLinus Torvalds out:
759*1da177e4SLinus Torvalds 	if (sym2)
760*1da177e4SLinus Torvalds 		printf(" %s", sym->name);
761*1da177e4SLinus Torvalds 	sym->flags &= ~SYMBOL_CHECK;
762*1da177e4SLinus Torvalds 	return sym2;
763*1da177e4SLinus Torvalds }
764*1da177e4SLinus Torvalds 
765*1da177e4SLinus Torvalds struct property *prop_alloc(enum prop_type type, struct symbol *sym)
766*1da177e4SLinus Torvalds {
767*1da177e4SLinus Torvalds 	struct property *prop;
768*1da177e4SLinus Torvalds 	struct property **propp;
769*1da177e4SLinus Torvalds 
770*1da177e4SLinus Torvalds 	prop = malloc(sizeof(*prop));
771*1da177e4SLinus Torvalds 	memset(prop, 0, sizeof(*prop));
772*1da177e4SLinus Torvalds 	prop->type = type;
773*1da177e4SLinus Torvalds 	prop->sym = sym;
774*1da177e4SLinus Torvalds 	prop->file = current_file;
775*1da177e4SLinus Torvalds 	prop->lineno = zconf_lineno();
776*1da177e4SLinus Torvalds 
777*1da177e4SLinus Torvalds 	/* append property to the prop list of symbol */
778*1da177e4SLinus Torvalds 	if (sym) {
779*1da177e4SLinus Torvalds 		for (propp = &sym->prop; *propp; propp = &(*propp)->next)
780*1da177e4SLinus Torvalds 			;
781*1da177e4SLinus Torvalds 		*propp = prop;
782*1da177e4SLinus Torvalds 	}
783*1da177e4SLinus Torvalds 
784*1da177e4SLinus Torvalds 	return prop;
785*1da177e4SLinus Torvalds }
786*1da177e4SLinus Torvalds 
787*1da177e4SLinus Torvalds struct symbol *prop_get_symbol(struct property *prop)
788*1da177e4SLinus Torvalds {
789*1da177e4SLinus Torvalds 	if (prop->expr && (prop->expr->type == E_SYMBOL ||
790*1da177e4SLinus Torvalds 			   prop->expr->type == E_CHOICE))
791*1da177e4SLinus Torvalds 		return prop->expr->left.sym;
792*1da177e4SLinus Torvalds 	return NULL;
793*1da177e4SLinus Torvalds }
794*1da177e4SLinus Torvalds 
795*1da177e4SLinus Torvalds const char *prop_get_type_name(enum prop_type type)
796*1da177e4SLinus Torvalds {
797*1da177e4SLinus Torvalds 	switch (type) {
798*1da177e4SLinus Torvalds 	case P_PROMPT:
799*1da177e4SLinus Torvalds 		return "prompt";
800*1da177e4SLinus Torvalds 	case P_COMMENT:
801*1da177e4SLinus Torvalds 		return "comment";
802*1da177e4SLinus Torvalds 	case P_MENU:
803*1da177e4SLinus Torvalds 		return "menu";
804*1da177e4SLinus Torvalds 	case P_DEFAULT:
805*1da177e4SLinus Torvalds 		return "default";
806*1da177e4SLinus Torvalds 	case P_CHOICE:
807*1da177e4SLinus Torvalds 		return "choice";
808*1da177e4SLinus Torvalds 	case P_SELECT:
809*1da177e4SLinus Torvalds 		return "select";
810*1da177e4SLinus Torvalds 	case P_RANGE:
811*1da177e4SLinus Torvalds 		return "range";
812*1da177e4SLinus Torvalds 	case P_UNKNOWN:
813*1da177e4SLinus Torvalds 		break;
814*1da177e4SLinus Torvalds 	}
815*1da177e4SLinus Torvalds 	return "unknown";
816*1da177e4SLinus Torvalds }
817