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