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