Revert "build: scripts/config - update to kconfig-v5.6"
[oweals/openwrt.git] / scripts / config / symbol.c
index b1dd9be29d541217c931c61492810326e2e82d68..31f268a4eecd6a9f767100920c381a8d7ddb7b1b 100644 (file)
@@ -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);
+}