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