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