frosted: add support for stm32f429-discovery
[openadk.git] / adk / config / symbol.c
blob685a1ab148988d131f396cd5ecac06083a278bd5
1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
6 #include <ctype.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <regex.h>
10 #include <sys/utsname.h>
12 #include "lkc.h"
14 struct symbol symbol_yes = {
15 .name = "y",
16 .curr = { "y", yes },
17 .flags = SYMBOL_CONST|SYMBOL_VALID,
18 }, symbol_mod = {
19 .name = "m",
20 .curr = { "m", mod },
21 .flags = SYMBOL_CONST|SYMBOL_VALID,
22 }, symbol_no = {
23 .name = "n",
24 .curr = { "n", no },
25 .flags = SYMBOL_CONST|SYMBOL_VALID,
26 }, symbol_empty = {
27 .name = "",
28 .curr = { "", no },
29 .flags = SYMBOL_VALID,
32 struct symbol *sym_defconfig_list;
33 struct symbol *modules_sym;
34 tristate modules_val;
36 struct expr *sym_env_list;
38 static void sym_add_default(struct symbol *sym, const char *def)
40 struct property *prop = prop_alloc(P_DEFAULT, sym);
42 prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
45 void sym_init(void)
47 struct symbol *sym;
48 struct utsname uts;
49 static bool inited = false;
51 if (inited)
52 return;
53 inited = true;
55 uname(&uts);
57 sym = sym_lookup("UNAME_RELEASE", 0);
58 sym->type = S_STRING;
59 sym->flags |= SYMBOL_AUTO;
60 sym_add_default(sym, uts.release);
63 enum symbol_type sym_get_type(struct symbol *sym)
65 enum symbol_type type = sym->type;
67 if (type == S_TRISTATE) {
68 if (sym_is_choice_value(sym) && sym->visible == yes)
69 type = S_BOOLEAN;
70 else if (modules_val == no)
71 type = S_BOOLEAN;
73 return type;
76 const char *sym_type_name(enum symbol_type type)
78 switch (type) {
79 case S_BOOLEAN:
80 return "boolean";
81 case S_TRISTATE:
82 return "tristate";
83 case S_INT:
84 return "integer";
85 case S_HEX:
86 return "hex";
87 case S_STRING:
88 return "string";
89 case S_UNKNOWN:
90 return "unknown";
91 case S_OTHER:
92 break;
94 return "???";
97 struct property *sym_get_choice_prop(struct symbol *sym)
99 struct property *prop;
101 for_all_choices(sym, prop)
102 return prop;
103 return NULL;
106 struct property *sym_get_env_prop(struct symbol *sym)
108 struct property *prop;
110 for_all_properties(sym, prop, P_ENV)
111 return prop;
112 return NULL;
115 struct property *sym_get_default_prop(struct symbol *sym)
117 struct property *prop;
119 for_all_defaults(sym, prop) {
120 prop->visible.tri = expr_calc_value(prop->visible.expr);
121 if (prop->visible.tri != no)
122 return prop;
124 return NULL;
127 static struct property *sym_get_range_prop(struct symbol *sym)
129 struct property *prop;
131 for_all_properties(sym, prop, P_RANGE) {
132 prop->visible.tri = expr_calc_value(prop->visible.expr);
133 if (prop->visible.tri != no)
134 return prop;
136 return NULL;
139 static long long sym_get_range_val(struct symbol *sym, int base)
141 sym_calc_value(sym);
142 switch (sym->type) {
143 case S_INT:
144 base = 10;
145 break;
146 case S_HEX:
147 base = 16;
148 break;
149 default:
150 break;
152 return strtoll(sym->curr.val, NULL, base);
155 static void sym_validate_range(struct symbol *sym)
157 struct property *prop;
158 int base;
159 long long val, val2;
160 char str[64];
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;
172 prop = sym_get_range_prop(sym);
173 if (!prop)
174 return;
175 val = strtoll(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;
182 if (sym->type == S_INT)
183 sprintf(str, "%lld", val2);
184 else
185 sprintf(str, "0x%llx", val2);
186 sym->curr.val = strdup(str);
189 static void sym_calc_visibility(struct symbol *sym)
191 struct property *prop;
192 tristate tri;
193 struct expr_select_value *esv;
195 /* any prompt visible? */
196 tri = no;
197 for_all_prompts(sym, prop) {
198 prop->visible.tri = expr_calc_value(prop->visible.expr);
199 tri = EXPR_OR(tri, prop->visible.tri);
201 if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
202 tri = yes;
203 if (sym->visible != tri) {
204 sym->visible = tri;
205 sym_set_changed(sym);
207 /* defaulting to "yes" if no explicit "depends on" are given */
208 tri = yes;
209 if (sym->dir_dep.expr)
210 tri = expr_calc_value(sym->dir_dep.expr);
211 if (tri == mod)
212 tri = yes;
213 if (sym->dir_dep.tri != tri) {
214 sym->dir_dep.tri = tri;
215 sym_set_changed(sym);
217 tri = no;
218 if (sym->rev_dep.expr)
219 tri = expr_calc_value(sym->rev_dep.expr);
220 if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
221 tri = yes;
222 if (sym->rev_dep.tri != tri) {
223 sym->rev_dep.tri = tri;
224 sym_set_changed(sym);
226 for (esv = sym->val_dep; esv; esv = esv->next) {
227 tri = expr_calc_value(esv->expr);
228 if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
229 tri = yes;
230 if (esv->tri != tri) {
231 esv->tri = tri;
232 sym_set_changed(sym);
238 * Find the default symbol for a choice.
239 * First try the default values for the choice symbol
240 * Next locate the first visible choice value
241 * Return NULL if none was found
243 struct symbol *sym_choice_default(struct symbol *sym)
245 struct symbol *def_sym;
246 struct symbol *ret = NULL;
247 struct property *prop;
248 struct expr *e;
250 /* check to see if any are selected */
251 prop = sym_get_choice_prop(sym);
252 expr_list_for_each_sym(prop->expr, e, def_sym)
253 if (def_sym->rev_dep.tri != no) {
254 if (ret)
255 fprintf(stderr, "warning: conflicting selects "
256 "on choice block: %s\n", sym->name);
257 else
258 ret = def_sym;
260 if (ret)
261 return ret;
263 /* any of the defaults visible? */
264 for_all_defaults(sym, prop) {
265 prop->visible.tri = expr_calc_value(prop->visible.expr);
266 if (prop->visible.tri == no)
267 continue;
268 def_sym = prop_get_symbol(prop);
269 if (def_sym->visible != no)
270 return def_sym;
273 /* just get the first visible value */
274 prop = sym_get_choice_prop(sym);
275 expr_list_for_each_sym(prop->expr, e, def_sym)
276 if (def_sym->visible != no)
277 return def_sym;
279 /* failed to locate any defaults */
280 return NULL;
283 static struct symbol *sym_calc_choice(struct symbol *sym)
285 struct symbol *def_sym;
286 struct property *prop;
287 struct expr *e;
288 int flags;
290 /* first calculate all choice values' visibilities */
291 flags = sym->flags;
292 prop = sym_get_choice_prop(sym);
293 expr_list_for_each_sym(prop->expr, e, def_sym) {
294 sym_calc_visibility(def_sym);
295 if (def_sym->visible != no)
296 flags &= def_sym->flags;
299 sym->flags &= flags | ~SYMBOL_DEF_USER;
301 /* is the user choice visible? */
302 def_sym = sym->def[S_DEF_USER].val;
303 if (def_sym && def_sym->visible != no)
304 return def_sym;
306 def_sym = sym_choice_default(sym);
308 if (def_sym == NULL)
309 /* no choice? reset tristate value */
310 sym->curr.tri = no;
312 return def_sym;
315 void sym_calc_value(struct symbol *sym)
317 struct symbol_value newval, oldval;
318 struct property *prop;
319 struct expr *e;
320 struct expr_select_value *esv;
321 int got_sel_val;
323 if (!sym)
324 return;
326 if (sym->flags & SYMBOL_VALID)
327 return;
329 if (sym_is_choice_value(sym) &&
330 sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {
331 sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;
332 prop = sym_get_choice_prop(sym);
333 sym_calc_value(prop_get_symbol(prop));
336 sym->flags |= SYMBOL_VALID;
338 oldval = sym->curr;
340 switch (sym->type) {
341 case S_INT:
342 case S_HEX:
343 case S_STRING:
344 newval = symbol_empty.curr;
345 break;
346 case S_BOOLEAN:
347 case S_TRISTATE:
348 newval = symbol_no.curr;
349 break;
350 default:
351 sym->curr.val = sym->name;
352 sym->curr.tri = no;
353 return;
355 if (!sym_is_choice_value(sym))
356 sym->flags &= ~SYMBOL_WRITE;
358 sym_calc_visibility(sym);
360 /* set default if recursively called */
361 sym->curr = newval;
363 switch (sym_get_type(sym)) {
364 case S_BOOLEAN:
365 case S_TRISTATE:
366 if (sym_is_choice_value(sym) && sym->visible == yes) {
367 prop = sym_get_choice_prop(sym);
368 newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
369 } else {
370 if (sym->visible != no) {
371 /* if the symbol is visible use the user value
372 * if available, otherwise try the default value
374 sym->flags |= SYMBOL_WRITE;
375 if (sym_has_value(sym)) {
376 newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
377 sym->visible);
378 goto calc_newval;
381 if (sym->rev_dep.tri != no)
382 sym->flags |= SYMBOL_WRITE;
383 for (esv = sym->val_dep; esv; esv = esv->next)
384 if (esv->tri != no)
385 sym->flags |= SYMBOL_WRITE;
386 if (!sym_is_choice(sym)) {
387 prop = sym_get_default_prop(sym);
388 if (prop) {
389 sym->flags |= SYMBOL_WRITE;
390 newval.tri = EXPR_AND(expr_calc_value(prop->expr),
391 prop->visible.tri);
394 calc_newval:
395 if (sym->dir_dep.tri == no) {
397 if (sym->rev_dep.tri != no) {
398 fprintf(stderr, "warning: (");
399 expr_fprint(sym->rev_dep.expr, stderr);
400 fprintf(stderr, ") selects %s which has unmet direct dependencies (",
401 sym->name);
402 expr_fprint(sym->dir_dep.expr, stderr);
403 fprintf(stderr, ")\n");
406 for (esv = sym->val_dep; esv; esv = esv->next) {
407 if ((esv->tri != no) &&
408 (expr_calc_value(esv->value) != no)) {
409 fprintf(stderr, "warning: (");
410 expr_fprint(esv->expr, stderr);
411 fprintf(stderr, ") selects %s (with value ",
412 sym->name);
413 expr_fprint(esv->value, stderr);
414 fprintf(stderr, ") which has unmet direct dependencies (");
415 expr_fprint(sym->dir_dep.expr, stderr);
416 fprintf(stderr, ")\n");
420 newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
421 for (esv = sym->val_dep; esv; esv = esv->next)
422 if (esv->tri != no)
423 newval.tri = EXPR_OR(newval.tri,
424 expr_calc_value(esv->value));
426 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
427 newval.tri = yes;
428 break;
429 case S_STRING:
430 case S_HEX:
431 case S_INT:
432 if (sym->visible != no) {
433 sym->flags |= SYMBOL_WRITE;
434 if (sym_has_value(sym)) {
435 newval.val = sym->def[S_DEF_USER].val;
436 break;
439 got_sel_val = 0;
440 for (esv = sym->val_dep; esv; esv = esv->next) {
441 if (esv->tri != no) {
442 struct symbol *ss = esv->value->left.sym;
444 if (got_sel_val) {
445 /* warn of more than one value selected */
446 } else {
447 sym->flags |= SYMBOL_WRITE;
448 sym_calc_value(ss);
449 newval.val = ss->curr.val;
450 got_sel_val = 1;
454 if (got_sel_val)
455 break;
456 prop = sym_get_default_prop(sym);
457 if (prop) {
458 struct symbol *ds = prop_get_symbol(prop);
459 if (ds) {
460 sym->flags |= SYMBOL_WRITE;
461 sym_calc_value(ds);
462 newval.val = ds->curr.val;
465 break;
466 default:
470 sym->curr = newval;
471 if (sym_is_choice(sym) && newval.tri == yes)
472 sym->curr.val = sym_calc_choice(sym);
473 sym_validate_range(sym);
475 if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
476 sym_set_changed(sym);
477 if (modules_sym == sym) {
478 sym_set_all_changed();
479 modules_val = modules_sym->curr.tri;
483 if (sym_is_choice(sym)) {
484 struct symbol *choice_sym;
486 prop = sym_get_choice_prop(sym);
487 expr_list_for_each_sym(prop->expr, e, choice_sym) {
488 if ((sym->flags & SYMBOL_WRITE) &&
489 choice_sym->visible != no)
490 choice_sym->flags |= SYMBOL_WRITE;
491 if (sym->flags & SYMBOL_CHANGED)
492 sym_set_changed(choice_sym);
496 if (sym->flags & SYMBOL_AUTO)
497 sym->flags &= ~SYMBOL_WRITE;
499 if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
500 set_all_choice_values(sym);
503 void sym_clear_all_valid(void)
505 struct symbol *sym;
506 int i;
508 for_all_symbols(i, sym)
509 sym->flags &= ~SYMBOL_VALID;
510 sym_add_change_count(1);
511 if (modules_sym)
512 sym_calc_value(modules_sym);
515 void sym_set_changed(struct symbol *sym)
517 struct property *prop;
519 sym->flags |= SYMBOL_CHANGED;
520 for (prop = sym->prop; prop; prop = prop->next) {
521 if (prop->menu)
522 prop->menu->flags |= MENU_CHANGED;
526 void sym_set_all_changed(void)
528 struct symbol *sym;
529 int i;
531 for_all_symbols(i, sym)
532 sym_set_changed(sym);
535 bool sym_tristate_within_range(struct symbol *sym, tristate val)
537 int type = sym_get_type(sym);
538 struct expr_select_value *esv;
539 tristate tri;
541 if (sym->visible == no)
542 return false;
544 if (type != S_BOOLEAN && type != S_TRISTATE)
545 return false;
547 if (type == S_BOOLEAN && val == mod)
548 return false;
549 tri = sym->rev_dep.tri;
550 for (esv = sym->val_dep; esv; esv = esv->next)
551 tri = EXPR_OR(tri, esv->tri);
552 if (sym->visible <= tri)
553 return false;
554 if (sym_is_choice_value(sym) && sym->visible == yes)
555 return val == yes;
556 return val >= tri && val <= sym->visible;
559 bool sym_set_tristate_value(struct symbol *sym, tristate val)
561 tristate oldval = sym_get_tristate_value(sym);
563 if (oldval != val && !sym_tristate_within_range(sym, val))
564 return false;
566 if (!(sym->flags & SYMBOL_DEF_USER)) {
567 sym->flags |= SYMBOL_DEF_USER;
568 sym_set_changed(sym);
571 * setting a choice value also resets the new flag of the choice
572 * symbol and all other choice values.
574 if (sym_is_choice_value(sym) && val == yes) {
575 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
576 struct property *prop;
577 struct expr *e;
579 cs->def[S_DEF_USER].val = sym;
580 cs->flags |= SYMBOL_DEF_USER;
581 prop = sym_get_choice_prop(cs);
582 for (e = prop->expr; e; e = e->left.expr) {
583 if (e->right.sym->visible != no)
584 e->right.sym->flags |= SYMBOL_DEF_USER;
588 sym->def[S_DEF_USER].tri = val;
589 if (oldval != val)
590 sym_clear_all_valid();
592 return true;
595 tristate sym_toggle_tristate_value(struct symbol *sym)
597 tristate oldval, newval;
599 oldval = newval = sym_get_tristate_value(sym);
600 do {
601 switch (newval) {
602 case no:
603 newval = mod;
604 break;
605 case mod:
606 newval = yes;
607 break;
608 case yes:
609 newval = no;
610 break;
612 if (sym_set_tristate_value(sym, newval))
613 break;
614 } while (oldval != newval);
615 return newval;
618 bool sym_string_valid(struct symbol *sym, const char *str)
620 signed char ch;
622 switch (sym->type) {
623 case S_STRING:
624 return true;
625 case S_INT:
626 ch = *str++;
627 if (ch == '-')
628 ch = *str++;
629 if (!isdigit(ch))
630 return false;
631 if (ch == '0' && *str != 0)
632 return false;
633 while ((ch = *str++)) {
634 if (!isdigit(ch))
635 return false;
637 return true;
638 case S_HEX:
639 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
640 str += 2;
641 ch = *str++;
642 do {
643 if (!isxdigit(ch))
644 return false;
645 } while ((ch = *str++));
646 return true;
647 case S_BOOLEAN:
648 case S_TRISTATE:
649 switch (str[0]) {
650 case 'y': case 'Y':
651 case 'm': case 'M':
652 case 'n': case 'N':
653 return true;
655 return false;
656 default:
657 return false;
661 bool sym_string_within_range(struct symbol *sym, const char *str)
663 struct property *prop;
664 long long val;
666 switch (sym->type) {
667 case S_STRING:
668 return sym_string_valid(sym, str);
669 case S_INT:
670 if (!sym_string_valid(sym, str))
671 return false;
672 prop = sym_get_range_prop(sym);
673 if (!prop)
674 return true;
675 val = strtoll(str, NULL, 10);
676 return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
677 val <= sym_get_range_val(prop->expr->right.sym, 10);
678 case S_HEX:
679 if (!sym_string_valid(sym, str))
680 return false;
681 prop = sym_get_range_prop(sym);
682 if (!prop)
683 return true;
684 val = strtoll(str, NULL, 16);
685 return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
686 val <= sym_get_range_val(prop->expr->right.sym, 16);
687 case S_BOOLEAN:
688 case S_TRISTATE:
689 switch (str[0]) {
690 case 'y': case 'Y':
691 return sym_tristate_within_range(sym, yes);
692 case 'm': case 'M':
693 return sym_tristate_within_range(sym, mod);
694 case 'n': case 'N':
695 return sym_tristate_within_range(sym, no);
697 return false;
698 default:
699 return false;
703 bool sym_set_string_value(struct symbol *sym, const char *newval)
705 const char *oldval;
706 char *val;
707 int size;
709 switch (sym->type) {
710 case S_BOOLEAN:
711 case S_TRISTATE:
712 switch (newval[0]) {
713 case 'y': case 'Y':
714 return sym_set_tristate_value(sym, yes);
715 case 'm': case 'M':
716 return sym_set_tristate_value(sym, mod);
717 case 'n': case 'N':
718 return sym_set_tristate_value(sym, no);
720 return false;
721 default:
725 if (!sym_string_within_range(sym, newval))
726 return false;
728 if (!(sym->flags & SYMBOL_DEF_USER)) {
729 sym->flags |= SYMBOL_DEF_USER;
730 sym_set_changed(sym);
733 oldval = sym->def[S_DEF_USER].val;
734 size = strlen(newval) + 1;
735 if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
736 size += 2;
737 sym->def[S_DEF_USER].val = val = xmalloc(size);
738 *val++ = '0';
739 *val++ = 'x';
740 } else if (!oldval || strcmp(oldval, newval))
741 sym->def[S_DEF_USER].val = val = xmalloc(size);
742 else
743 return true;
745 strcpy(val, newval);
746 free((void *)oldval);
747 sym_clear_all_valid();
749 return true;
753 * Find the default value associated to a symbol.
754 * For tristate symbol handle the modules=n case
755 * in which case "m" becomes "y".
756 * If the symbol does not have any default then fallback
757 * to the fixed default values.
759 const char *sym_get_string_default(struct symbol *sym)
761 struct property *prop;
762 struct symbol *ds;
763 const char *str;
764 tristate val;
766 sym_calc_visibility(sym);
767 sym_calc_value(modules_sym);
768 val = symbol_no.curr.tri;
769 str = symbol_empty.curr.val;
771 /* If symbol has a default value look it up */
772 prop = sym_get_default_prop(sym);
773 if (prop != NULL) {
774 switch (sym->type) {
775 case S_BOOLEAN:
776 case S_TRISTATE:
777 /* The visibility may limit the value from yes => mod */
778 val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
779 break;
780 default:
782 * The following fails to handle the situation
783 * where a default value is further limited by
784 * the valid range.
786 ds = prop_get_symbol(prop);
787 if (ds != NULL) {
788 sym_calc_value(ds);
789 str = (const char *)ds->curr.val;
794 /* Handle select statements */
795 val = EXPR_OR(val, sym->rev_dep.tri);
797 /* transpose mod to yes if modules are not enabled */
798 if (val == mod)
799 if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
800 val = yes;
802 /* transpose mod to yes if type is bool */
803 if (sym->type == S_BOOLEAN && val == mod)
804 val = yes;
806 switch (sym->type) {
807 case S_BOOLEAN:
808 case S_TRISTATE:
809 switch (val) {
810 case no: return "n";
811 case mod: return "m";
812 case yes: return "y";
814 case S_INT:
815 case S_HEX:
816 return str;
817 case S_STRING:
818 return str;
819 case S_OTHER:
820 case S_UNKNOWN:
821 break;
823 return "";
826 const char *sym_get_string_value(struct symbol *sym)
828 tristate val;
830 switch (sym->type) {
831 case S_BOOLEAN:
832 case S_TRISTATE:
833 val = sym_get_tristate_value(sym);
834 switch (val) {
835 case no:
836 return "n";
837 case mod:
838 sym_calc_value(modules_sym);
839 return (modules_sym->curr.tri == no) ? "n" : "m";
840 case yes:
841 return "y";
843 break;
844 default:
847 return (const char *)sym->curr.val;
850 bool sym_is_changable(struct symbol *sym)
852 tristate tri = sym->rev_dep.tri;
853 struct expr_select_value *esv;
855 for (esv = sym->val_dep; esv; esv = esv->next)
856 tri = EXPR_OR(tri, esv->tri);
858 return sym->visible > tri;
861 static unsigned strhash(const char *s)
863 /* fnv32 hash */
864 unsigned hash = 2166136261U;
865 for (; *s; s++)
866 hash = (hash ^ *s) * 0x01000193;
867 return hash;
870 struct symbol *sym_lookup(const char *name, int flags)
872 struct symbol *symbol;
873 char *new_name;
874 int hash;
876 if (name) {
877 if (name[0] && !name[1]) {
878 switch (name[0]) {
879 case 'y': return &symbol_yes;
880 case 'm': return &symbol_mod;
881 case 'n': return &symbol_no;
884 hash = strhash(name) % SYMBOL_HASHSIZE;
886 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
887 if (symbol->name &&
888 !strcmp(symbol->name, name) &&
889 (flags ? symbol->flags & flags
890 : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
891 return symbol;
893 new_name = strdup(name);
894 } else {
895 new_name = NULL;
896 hash = 0;
899 symbol = xmalloc(sizeof(*symbol));
900 memset(symbol, 0, sizeof(*symbol));
901 symbol->name = new_name;
902 symbol->type = S_UNKNOWN;
903 symbol->flags |= flags;
905 symbol->next = symbol_hash[hash];
906 symbol_hash[hash] = symbol;
908 return symbol;
911 struct symbol *sym_find(const char *name)
913 struct symbol *symbol = NULL;
914 int hash = 0;
916 if (!name)
917 return NULL;
919 if (name[0] && !name[1]) {
920 switch (name[0]) {
921 case 'y': return &symbol_yes;
922 case 'm': return &symbol_mod;
923 case 'n': return &symbol_no;
926 hash = strhash(name) % SYMBOL_HASHSIZE;
928 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
929 if (symbol->name &&
930 !strcmp(symbol->name, name) &&
931 !(symbol->flags & SYMBOL_CONST))
932 break;
935 return symbol;
939 * Expand symbol's names embedded in the string given in argument. Symbols'
940 * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
941 * the empty string.
943 const char *sym_expand_string_value(const char *in)
945 const char *src;
946 char *res;
947 size_t reslen;
949 reslen = strlen(in) + 1;
950 res = xmalloc(reslen);
951 res[0] = '\0';
953 while ((src = strchr(in, '$'))) {
954 char *p, name[SYMBOL_MAXLENGTH];
955 const char *symval = "";
956 struct symbol *sym;
957 size_t newlen;
959 strncat(res, in, src - in);
960 src++;
962 p = name;
963 while (isalnum(*src) || *src == '_')
964 *p++ = *src++;
965 *p = '\0';
967 sym = sym_find(name);
968 if (sym != NULL) {
969 sym_calc_value(sym);
970 symval = sym_get_string_value(sym);
973 newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
974 if (newlen > reslen) {
975 reslen = newlen;
976 res = realloc(res, reslen);
979 strcat(res, symval);
980 in = src;
982 strcat(res, in);
984 return res;
987 const char *sym_escape_string_value(const char *in)
989 const char *p;
990 size_t reslen;
991 char *res;
992 size_t l;
994 reslen = strlen(in) + strlen("\"\"") + 1;
996 p = in;
997 for (;;) {
998 l = strcspn(p, "\"\\");
999 p += l;
1001 if (p[0] == '\0')
1002 break;
1004 reslen++;
1005 p++;
1008 res = xmalloc(reslen);
1009 res[0] = '\0';
1011 strcat(res, "\"");
1013 p = in;
1014 for (;;) {
1015 l = strcspn(p, "\"\\");
1016 strncat(res, p, l);
1017 p += l;
1019 if (p[0] == '\0')
1020 break;
1022 strcat(res, "\\");
1023 strncat(res, p++, 1);
1026 strcat(res, "\"");
1027 return res;
1030 struct sym_match {
1031 struct symbol *sym;
1032 off_t so, eo;
1035 /* Compare matched symbols as thus:
1036 * - first, symbols that match exactly
1037 * - then, alphabetical sort
1039 static int sym_rel_comp(const void *sym1, const void *sym2)
1041 const struct sym_match *s1 = sym1;
1042 const struct sym_match *s2 = sym2;
1043 int exact1, exact2;
1045 /* Exact match:
1046 * - if matched length on symbol s1 is the length of that symbol,
1047 * then this symbol should come first;
1048 * - if matched length on symbol s2 is the length of that symbol,
1049 * then this symbol should come first.
1050 * Note: since the search can be a regexp, both symbols may match
1051 * exactly; if this is the case, we can't decide which comes first,
1052 * and we fallback to sorting alphabetically.
1054 exact1 = (s1->eo - s1->so) == strlen(s1->sym->name);
1055 exact2 = (s2->eo - s2->so) == strlen(s2->sym->name);
1056 if (exact1 && !exact2)
1057 return -1;
1058 if (!exact1 && exact2)
1059 return 1;
1061 /* As a fallback, sort symbols alphabetically */
1062 return strcmp(s1->sym->name, s2->sym->name);
1065 struct symbol **sym_re_search(const char *pattern)
1067 struct symbol *sym, **sym_arr = NULL;
1068 struct sym_match *sym_match_arr = NULL;
1069 int i, cnt, size;
1070 regex_t re;
1071 regmatch_t match[1];
1073 cnt = size = 0;
1074 /* Skip if empty */
1075 if (strlen(pattern) == 0)
1076 return NULL;
1077 if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
1078 return NULL;
1080 for_all_symbols(i, sym) {
1081 if (sym->flags & SYMBOL_CONST || !sym->name)
1082 continue;
1083 if (regexec(&re, sym->name, 1, match, 0))
1084 continue;
1085 if (cnt >= size) {
1086 void *tmp;
1087 size += 16;
1088 tmp = realloc(sym_match_arr, size * sizeof(struct sym_match));
1089 if (!tmp)
1090 goto sym_re_search_free;
1091 sym_match_arr = tmp;
1093 sym_calc_value(sym);
1094 /* As regexec returned 0, we know we have a match, so
1095 * we can use match[0].rm_[se]o without further checks
1097 sym_match_arr[cnt].so = match[0].rm_so;
1098 sym_match_arr[cnt].eo = match[0].rm_eo;
1099 sym_match_arr[cnt++].sym = sym;
1101 if (sym_match_arr) {
1102 qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp);
1103 sym_arr = malloc((cnt+1) * sizeof(struct symbol));
1104 if (!sym_arr)
1105 goto sym_re_search_free;
1106 for (i = 0; i < cnt; i++)
1107 sym_arr[i] = sym_match_arr[i].sym;
1108 sym_arr[cnt] = NULL;
1110 sym_re_search_free:
1111 /* sym_match_arr can be NULL if no match, but free(NULL) is OK */
1112 free(sym_match_arr);
1113 regfree(&re);
1115 return sym_arr;
1119 * When we check for recursive dependencies we use a stack to save
1120 * current state so we can print out relevant info to user.
1121 * The entries are located on the call stack so no need to free memory.
1122 * Note insert() remove() must always match to properly clear the stack.
1124 static struct dep_stack {
1125 struct dep_stack *prev, *next;
1126 struct symbol *sym;
1127 struct property *prop;
1128 struct expr *expr;
1129 } *check_top;
1131 static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
1133 memset(stack, 0, sizeof(*stack));
1134 if (check_top)
1135 check_top->next = stack;
1136 stack->prev = check_top;
1137 stack->sym = sym;
1138 check_top = stack;
1141 static void dep_stack_remove(void)
1143 check_top = check_top->prev;
1144 if (check_top)
1145 check_top->next = NULL;
1149 * Called when we have detected a recursive dependency.
1150 * check_top point to the top of the stact so we use
1151 * the ->prev pointer to locate the bottom of the stack.
1153 static void sym_check_print_recursive(struct symbol *last_sym)
1155 struct dep_stack *stack;
1156 struct symbol *sym, *next_sym;
1157 struct menu *menu = NULL;
1158 struct property *prop;
1159 struct dep_stack cv_stack;
1161 if (sym_is_choice_value(last_sym)) {
1162 dep_stack_insert(&cv_stack, last_sym);
1163 last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
1166 for (stack = check_top; stack != NULL; stack = stack->prev)
1167 if (stack->sym == last_sym)
1168 break;
1169 if (!stack) {
1170 fprintf(stderr, "unexpected recursive dependency error\n");
1171 return;
1174 for (; stack; stack = stack->next) {
1175 sym = stack->sym;
1176 next_sym = stack->next ? stack->next->sym : last_sym;
1177 prop = stack->prop;
1178 if (prop == NULL)
1179 prop = stack->sym->prop;
1181 /* for choice values find the menu entry (used below) */
1182 if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
1183 for (prop = sym->prop; prop; prop = prop->next) {
1184 menu = prop->menu;
1185 if (prop->menu)
1186 break;
1189 if (stack->sym == last_sym)
1190 fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
1191 prop->file->name, prop->lineno);
1192 if (stack->expr) {
1193 fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
1194 prop->file->name, prop->lineno,
1195 sym->name ? sym->name : "<choice>",
1196 prop_get_type_name(prop->type),
1197 next_sym->name ? next_sym->name : "<choice>");
1198 } else if (stack->prop) {
1199 fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
1200 prop->file->name, prop->lineno,
1201 sym->name ? sym->name : "<choice>",
1202 next_sym->name ? next_sym->name : "<choice>");
1203 } else if (sym_is_choice(sym)) {
1204 fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
1205 menu->file->name, menu->lineno,
1206 sym->name ? sym->name : "<choice>",
1207 next_sym->name ? next_sym->name : "<choice>");
1208 } else if (sym_is_choice_value(sym)) {
1209 fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
1210 menu->file->name, menu->lineno,
1211 sym->name ? sym->name : "<choice>",
1212 next_sym->name ? next_sym->name : "<choice>");
1213 } else {
1214 fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
1215 prop->file->name, prop->lineno,
1216 sym->name ? sym->name : "<choice>",
1217 next_sym->name ? next_sym->name : "<choice>");
1221 if (check_top == &cv_stack)
1222 dep_stack_remove();
1225 static struct symbol *sym_check_expr_deps(struct expr *e)
1227 struct symbol *sym;
1229 if (!e)
1230 return NULL;
1231 switch (e->type) {
1232 case E_OR:
1233 case E_AND:
1234 sym = sym_check_expr_deps(e->left.expr);
1235 if (sym)
1236 return sym;
1237 return sym_check_expr_deps(e->right.expr);
1238 case E_NOT:
1239 return sym_check_expr_deps(e->left.expr);
1240 case E_EQUAL:
1241 case E_UNEQUAL:
1242 sym = sym_check_deps(e->left.sym);
1243 if (sym)
1244 return sym;
1245 return sym_check_deps(e->right.sym);
1246 case E_SYMBOL:
1247 return sym_check_deps(e->left.sym);
1248 default:
1249 break;
1251 printf("Oops! How to check %d?\n", e->type);
1252 return NULL;
1255 /* return NULL when dependencies are OK */
1256 static struct symbol *sym_check_sym_deps(struct symbol *sym)
1258 struct symbol *sym2;
1259 struct property *prop;
1260 struct dep_stack stack;
1262 dep_stack_insert(&stack, sym);
1264 sym2 = sym_check_expr_deps(sym->rev_dep.expr);
1265 if (sym2)
1266 goto out;
1268 for (prop = sym->prop; prop; prop = prop->next) {
1269 if (prop->type == P_CHOICE || prop->type == P_SELECT)
1270 continue;
1271 stack.prop = prop;
1272 sym2 = sym_check_expr_deps(prop->visible.expr);
1273 if (sym2)
1274 break;
1275 if (prop->type != P_DEFAULT || sym_is_choice(sym))
1276 continue;
1277 stack.expr = prop->expr;
1278 sym2 = sym_check_expr_deps(prop->expr);
1279 if (sym2)
1280 break;
1281 stack.expr = NULL;
1284 out:
1285 dep_stack_remove();
1287 return sym2;
1290 static struct symbol *sym_check_choice_deps(struct symbol *choice)
1292 struct symbol *sym, *sym2;
1293 struct property *prop;
1294 struct expr *e;
1295 struct dep_stack stack;
1297 dep_stack_insert(&stack, choice);
1299 prop = sym_get_choice_prop(choice);
1300 expr_list_for_each_sym(prop->expr, e, sym)
1301 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1303 choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1304 sym2 = sym_check_sym_deps(choice);
1305 choice->flags &= ~SYMBOL_CHECK;
1306 if (sym2)
1307 goto out;
1309 expr_list_for_each_sym(prop->expr, e, sym) {
1310 sym2 = sym_check_sym_deps(sym);
1311 if (sym2)
1312 break;
1314 out:
1315 expr_list_for_each_sym(prop->expr, e, sym)
1316 sym->flags &= ~SYMBOL_CHECK;
1318 if (sym2 && sym_is_choice_value(sym2) &&
1319 prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
1320 sym2 = choice;
1322 dep_stack_remove();
1324 return sym2;
1327 struct symbol *sym_check_deps(struct symbol *sym)
1329 struct symbol *sym2;
1330 struct property *prop;
1332 if (sym->flags & SYMBOL_CHECK) {
1333 sym_check_print_recursive(sym);
1334 return sym;
1336 if (sym->flags & SYMBOL_CHECKED)
1337 return NULL;
1339 if (sym_is_choice_value(sym)) {
1340 struct dep_stack stack;
1342 /* for choice groups start the check with main choice symbol */
1343 dep_stack_insert(&stack, sym);
1344 prop = sym_get_choice_prop(sym);
1345 sym2 = sym_check_deps(prop_get_symbol(prop));
1346 dep_stack_remove();
1347 } else if (sym_is_choice(sym)) {
1348 sym2 = sym_check_choice_deps(sym);
1349 } else {
1350 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1351 sym2 = sym_check_sym_deps(sym);
1352 sym->flags &= ~SYMBOL_CHECK;
1355 if (sym2 && sym2 == sym)
1356 sym2 = NULL;
1358 return sym2;
1361 struct property *prop_alloc(enum prop_type type, struct symbol *sym)
1363 struct property *prop;
1364 struct property **propp;
1366 prop = xmalloc(sizeof(*prop));
1367 memset(prop, 0, sizeof(*prop));
1368 prop->type = type;
1369 prop->sym = sym;
1370 prop->file = current_file;
1371 prop->lineno = zconf_lineno();
1373 /* append property to the prop list of symbol */
1374 if (sym) {
1375 for (propp = &sym->prop; *propp; propp = &(*propp)->next)
1377 *propp = prop;
1380 return prop;
1383 struct symbol *prop_get_symbol(struct property *prop)
1385 if (prop->expr && (prop->expr->type == E_SYMBOL ||
1386 prop->expr->type == E_LIST))
1387 return prop->expr->left.sym;
1388 return NULL;
1391 const char *prop_get_type_name(enum prop_type type)
1393 switch (type) {
1394 case P_PROMPT:
1395 return "prompt";
1396 case P_ENV:
1397 return "env";
1398 case P_COMMENT:
1399 return "comment";
1400 case P_MENU:
1401 return "menu";
1402 case P_DEFAULT:
1403 return "default";
1404 case P_CHOICE:
1405 return "choice";
1406 case P_SELECT:
1407 return "select";
1408 case P_RANGE:
1409 return "range";
1410 case P_SYMBOL:
1411 return "symbol";
1412 case P_UNKNOWN:
1413 break;
1415 return "unknown";
1418 static void prop_add_env(const char *env)
1420 struct symbol *sym, *sym2;
1421 struct property *prop;
1422 char *p;
1424 sym = current_entry->sym;
1425 sym->flags |= SYMBOL_AUTO;
1426 for_all_properties(sym, prop, P_ENV) {
1427 sym2 = prop_get_symbol(prop);
1428 if (strcmp(sym2->name, env))
1429 menu_warn(current_entry, "redefining environment symbol from %s",
1430 sym2->name);
1431 return;
1434 prop = prop_alloc(P_ENV, sym);
1435 prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
1437 sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
1438 sym_env_list->right.sym = sym;
1440 p = getenv(env);
1441 if (p)
1442 sym_add_default(sym, p);
1443 else
1444 menu_warn(current_entry, "environment variable %s undefined", env);