diff options
Diffstat (limited to 'scripts/config/symbol.c')
-rw-r--r-- | scripts/config/symbol.c | 269 |
1 files changed, 182 insertions, 87 deletions
diff --git a/scripts/config/symbol.c b/scripts/config/symbol.c index b1dd9be29d..31f268a4ee 100644 --- a/scripts/config/symbol.c +++ b/scripts/config/symbol.c @@ -1,6 +1,6 @@ -// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. */ #include <ctype.h> @@ -33,6 +33,33 @@ struct symbol *sym_defconfig_list; struct symbol *modules_sym; tristate modules_val; +struct expr *sym_env_list; + +static void sym_add_default(struct symbol *sym, const char *def) +{ + struct property *prop = prop_alloc(P_DEFAULT, sym); + + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); +} + +void sym_init(void) +{ + struct symbol *sym; + struct utsname uts; + static bool inited = false; + + if (inited) + return; + inited = true; + + uname(&uts); + + sym = sym_lookup("UNAME_RELEASE", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + sym_add_default(sym, uts.release); +} + enum symbol_type sym_get_type(struct symbol *sym) { enum symbol_type type = sym->type; @@ -50,7 +77,7 @@ const char *sym_type_name(enum symbol_type type) { switch (type) { case S_BOOLEAN: - return "bool"; + return "boolean"; case S_TRISTATE: return "tristate"; case S_INT: @@ -61,6 +88,8 @@ const char *sym_type_name(enum symbol_type type) return "string"; case S_UNKNOWN: return "unknown"; + case S_OTHER: + break; } return "???"; } @@ -74,6 +103,15 @@ struct property *sym_get_choice_prop(struct symbol *sym) return NULL; } +struct property *sym_get_env_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_ENV) + return prop; + return NULL; +} + static struct property *sym_get_default_prop(struct symbol *sym) { struct property *prop; @@ -86,7 +124,7 @@ static struct property *sym_get_default_prop(struct symbol *sym) return NULL; } -struct property *sym_get_range_prop(struct symbol *sym) +static struct property *sym_get_range_prop(struct symbol *sym) { struct property *prop; @@ -145,7 +183,7 @@ static void sym_validate_range(struct symbol *sym) sprintf(str, "%lld", val2); else sprintf(str, "0x%llx", val2); - sym->curr.val = xstrdup(str); + sym->curr.val = strdup(str); } static void sym_set_changed(struct symbol *sym) @@ -205,7 +243,7 @@ static void sym_calc_visibility(struct symbol *sym) tri = yes; if (sym->dir_dep.expr) tri = expr_calc_value(sym->dir_dep.expr); - if (tri == mod && sym_get_type(sym) == S_BOOLEAN) + if (tri == mod) tri = yes; if (sym->dir_dep.tri != tri) { sym->dir_dep.tri = tri; @@ -220,15 +258,6 @@ static void sym_calc_visibility(struct symbol *sym) sym->rev_dep.tri = tri; sym_set_changed(sym); } - tri = no; - if (sym->implied.expr && sym->dir_dep.tri != no) - tri = expr_calc_value(sym->implied.expr); - if (tri == mod && sym_get_type(sym) == S_BOOLEAN) - tri = yes; - if (sym->implied.tri != tri) { - sym->implied.tri = tri; - sym_set_changed(sym); - } } /* @@ -333,13 +362,11 @@ void sym_calc_value(struct symbol *sym) sym->curr.tri = no; return; } - sym->flags &= ~SYMBOL_WRITE; + if (!sym_is_choice_value(sym)) + sym->flags &= ~SYMBOL_WRITE; sym_calc_visibility(sym); - if (sym->visible != no) - sym->flags |= SYMBOL_WRITE; - /* set default if recursively called */ sym->curr = newval; @@ -354,6 +381,7 @@ void sym_calc_value(struct symbol *sym) /* if the symbol is visible use the user value * if available, otherwise try the default value */ + sym->flags |= SYMBOL_WRITE; if (sym_has_value(sym)) { newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->visible); @@ -369,28 +397,26 @@ void sym_calc_value(struct symbol *sym) newval.tri = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri); } - if (sym->implied.tri != no) { - sym->flags |= SYMBOL_WRITE; - newval.tri = EXPR_OR(newval.tri, sym->implied.tri); - } } calc_newval: - if (sym->dir_dep.tri < sym->rev_dep.tri) { + if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { newval.tri = no; } else { newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); } } - if (newval.tri == mod && - (sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes)) + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) newval.tri = yes; break; case S_STRING: case S_HEX: case S_INT: - if (sym->visible != no && sym_has_value(sym)) { - newval.val = sym->def[S_DEF_USER].val; - break; + if (sym->visible != no) { + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.val = sym->def[S_DEF_USER].val; + break; + } } prop = sym_get_default_prop(sym); if (prop) { @@ -432,7 +458,7 @@ void sym_calc_value(struct symbol *sym) } } - if (sym->flags & SYMBOL_NO_WRITE) + if (sym->flags & SYMBOL_AUTO) sym->flags &= ~SYMBOL_WRITE; if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) @@ -464,8 +490,6 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val) return false; if (sym->visible <= sym->rev_dep.tri) return false; - if (sym->implied.tri == yes && val == mod) - return false; if (sym_is_choice_value(sym) && sym->visible == yes) return val == yes; return val >= sym->rev_dep.tri && val <= sym->visible; @@ -718,10 +742,6 @@ const char *sym_get_string_default(struct symbol *sym) if (sym->type == S_BOOLEAN && val == mod) val = yes; - /* adjust the default value if this symbol is implied by another */ - if (val < sym->implied.tri) - val = sym->implied.tri; - switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: @@ -735,6 +755,7 @@ const char *sym_get_string_default(struct symbol *sym) return str; case S_STRING: return str; + case S_OTHER: case S_UNKNOWN: break; } @@ -765,7 +786,7 @@ const char *sym_get_string_value(struct symbol *sym) return (const char *)sym->curr.val; } -bool sym_is_changeable(struct symbol *sym) +bool sym_is_changable(struct symbol *sym) { return sym->visible > sym->rev_dep.tri; } @@ -802,7 +823,7 @@ struct symbol *sym_lookup(const char *name, int flags) : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) return symbol; } - new_name = xstrdup(name); + new_name = strdup(name); } else { new_name = NULL; hash = 0; @@ -847,6 +868,55 @@ struct symbol *sym_find(const char *name) return symbol; } +/* + * Expand symbol's names embedded in the string given in argument. Symbols' + * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to + * the empty string. + */ +const char *sym_expand_string_value(const char *in) +{ + const char *src; + char *res; + size_t reslen; + + reslen = strlen(in) + 1; + res = xmalloc(reslen); + res[0] = '\0'; + + while ((src = strchr(in, '$'))) { + char *p, name[SYMBOL_MAXLENGTH]; + const char *symval = ""; + struct symbol *sym; + size_t newlen; + + strncat(res, in, src - in); + src++; + + p = name; + while (isalnum(*src) || *src == '_') + *p++ = *src++; + *p = '\0'; + + sym = sym_find(name); + if (sym != NULL) { + sym_calc_value(sym); + symval = sym_get_string_value(sym); + } + + newlen = strlen(res) + strlen(symval) + strlen(src) + 1; + if (newlen > reslen) { + reslen = newlen; + res = realloc(res, reslen); + } + + strcat(res, symval); + in = src; + } + strcat(res, in); + + return res; +} + const char *sym_escape_string_value(const char *in) { const char *p; @@ -963,7 +1033,7 @@ struct symbol **sym_re_search(const char *pattern) } if (sym_match_arr) { qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp); - sym_arr = malloc((cnt+1) * sizeof(struct symbol *)); + sym_arr = malloc((cnt+1) * sizeof(struct symbol)); if (!sym_arr) goto sym_re_search_free; for (i = 0; i < cnt; i++) @@ -988,7 +1058,7 @@ static struct dep_stack { struct dep_stack *prev, *next; struct symbol *sym; struct property *prop; - struct expr **expr; + struct expr *expr; } *check_top; static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) @@ -1052,52 +1122,37 @@ static void sym_check_print_recursive(struct symbol *last_sym) if (stack->sym == last_sym) fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", prop->file->name, prop->lineno); - - if (sym_is_choice(sym)) { - fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", - menu->file->name, menu->lineno, - sym->name ? sym->name : "<choice>", - next_sym->name ? next_sym->name : "<choice>"); - } else if (sym_is_choice_value(sym)) { - fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", - menu->file->name, menu->lineno, - sym->name ? sym->name : "<choice>", - next_sym->name ? next_sym->name : "<choice>"); - } else if (stack->expr == &sym->dir_dep.expr) { - fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", + fprintf(stderr, "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"); + fprintf(stderr, "subsection \"Kconfig recursive dependency limitations\"\n"); + if (stack->expr) { + fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", prop->file->name, prop->lineno, sym->name ? sym->name : "<choice>", + prop_get_type_name(prop->type), next_sym->name ? next_sym->name : "<choice>"); - } else if (stack->expr == &sym->rev_dep.expr) { - fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", + } else if (stack->prop) { + fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", prop->file->name, prop->lineno, sym->name ? sym->name : "<choice>", next_sym->name ? next_sym->name : "<choice>"); - } else if (stack->expr == &sym->implied.expr) { - fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n", - prop->file->name, prop->lineno, + } else if (sym_is_choice(sym)) { + fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", + menu->file->name, menu->lineno, sym->name ? sym->name : "<choice>", next_sym->name ? next_sym->name : "<choice>"); - } else if (stack->expr) { - fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", - prop->file->name, prop->lineno, + } else if (sym_is_choice_value(sym)) { + fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", + menu->file->name, menu->lineno, sym->name ? sym->name : "<choice>", - prop_get_type_name(prop->type), next_sym->name ? next_sym->name : "<choice>"); } else { - fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n", + fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", prop->file->name, prop->lineno, sym->name ? sym->name : "<choice>", - prop_get_type_name(prop->type), next_sym->name ? next_sym->name : "<choice>"); } } - fprintf(stderr, - "For a resolution refer to Documentation/kbuild/kconfig-language.rst\n" - "subsection \"Kconfig recursive dependency limitations\"\n" - "\n"); - if (check_top == &cv_stack) dep_stack_remove(); } @@ -1132,7 +1187,7 @@ static struct symbol *sym_check_expr_deps(struct expr *e) default: break; } - fprintf(stderr, "Oops! How to check %d?\n", e->type); + printf("Oops! How to check %d?\n", e->type); return NULL; } @@ -1145,26 +1200,12 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) dep_stack_insert(&stack, sym); - stack.expr = &sym->dir_dep.expr; - sym2 = sym_check_expr_deps(sym->dir_dep.expr); - if (sym2) - goto out; - - stack.expr = &sym->rev_dep.expr; sym2 = sym_check_expr_deps(sym->rev_dep.expr); if (sym2) goto out; - stack.expr = &sym->implied.expr; - sym2 = sym_check_expr_deps(sym->implied.expr); - if (sym2) - goto out; - - stack.expr = NULL; - for (prop = sym->prop; prop; prop = prop->next) { - if (prop->type == P_CHOICE || prop->type == P_SELECT || - prop->type == P_IMPLY) + if (prop->type == P_CHOICE || prop->type == P_SELECT) continue; stack.prop = prop; sym2 = sym_check_expr_deps(prop->visible.expr); @@ -1172,7 +1213,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) break; if (prop->type != P_DEFAULT || sym_is_choice(sym)) continue; - stack.expr = &prop->expr; + stack.expr = prop->expr; sym2 = sym_check_expr_deps(prop->expr); if (sym2) break; @@ -1250,9 +1291,34 @@ struct symbol *sym_check_deps(struct symbol *sym) sym->flags &= ~SYMBOL_CHECK; } + if (sym2 && sym2 == sym) + sym2 = NULL; + return sym2; } +struct property *prop_alloc(enum prop_type type, struct symbol *sym) +{ + struct property *prop; + struct property **propp; + + prop = xmalloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->sym = sym; + prop->file = current_file; + prop->lineno = zconf_lineno(); + + /* append property to the prop list of symbol */ + if (sym) { + for (propp = &sym->prop; *propp; propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + struct symbol *prop_get_symbol(struct property *prop) { if (prop->expr && (prop->expr->type == E_SYMBOL || @@ -1266,6 +1332,8 @@ const char *prop_get_type_name(enum prop_type type) switch (type) { case P_PROMPT: return "prompt"; + case P_ENV: + return "env"; case P_COMMENT: return "comment"; case P_MENU: @@ -1276,8 +1344,6 @@ const char *prop_get_type_name(enum prop_type type) return "choice"; case P_SELECT: return "select"; - case P_IMPLY: - return "imply"; case P_RANGE: return "range"; case P_SYMBOL: @@ -1289,3 +1355,32 @@ const char *prop_get_type_name(enum prop_type type) } return "unknown"; } + +static void prop_add_env(const char *env) +{ + struct symbol *sym, *sym2; + struct property *prop; + char *p; + + sym = current_entry->sym; + sym->flags |= SYMBOL_AUTO; + for_all_properties(sym, prop, P_ENV) { + sym2 = prop_get_symbol(prop); + if (strcmp(sym2->name, env)) + menu_warn(current_entry, "redefining environment symbol from %s", + sym2->name); + return; + } + + prop = prop_alloc(P_ENV, sym); + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); + + sym_env_list = expr_alloc_one(E_LIST, sym_env_list); + sym_env_list->right.sym = sym; + + p = getenv(env); + if (p) + sym_add_default(sym, p); + else + menu_warn(current_entry, "environment variable %s undefined", env); +} |