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