]> Pileus Git - ~andy/linux/blobdiff - scripts/kconfig/symbol.c
kconfig: save location of config symbols
[~andy/linux] / scripts / kconfig / symbol.c
index 6c8fbbb66ebcaddefff183696d1c5d89bc2d6c09..9f180ab7698d3314c3e164983fd154521672bef1 100644 (file)
@@ -205,6 +205,16 @@ static void sym_calc_visibility(struct symbol *sym)
        }
        if (sym_is_choice_value(sym))
                return;
+       /* defaulting to "yes" if no explicit "depends on" are given */
+       tri = yes;
+       if (sym->dir_dep.expr)
+               tri = expr_calc_value(sym->dir_dep.expr);
+       if (tri == mod)
+               tri = yes;
+       if (sym->dir_dep.tri != tri) {
+               sym->dir_dep.tri = tri;
+               sym_set_changed(sym);
+       }
        tri = no;
        if (sym->rev_dep.expr)
                tri = expr_calc_value(sym->rev_dep.expr);
@@ -222,13 +232,15 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
        struct property *prop;
        struct expr *e;
 
+       /* first calculate all choice values' visibilities */
+       prop = sym_get_choice_prop(sym);
+       expr_list_for_each_sym(prop->expr, e, def_sym)
+               sym_calc_visibility(def_sym);
+
        /* is the user choice visible? */
        def_sym = sym->def[S_DEF_USER].val;
-       if (def_sym) {
-               sym_calc_visibility(def_sym);
-               if (def_sym->visible != no)
-                       return def_sym;
-       }
+       if (def_sym && def_sym->visible != no)
+               return def_sym;
 
        /* any of the defaults visible? */
        for_all_defaults(sym, prop) {
@@ -236,18 +248,15 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
                if (prop->visible.tri == no)
                        continue;
                def_sym = prop_get_symbol(prop);
-               sym_calc_visibility(def_sym);
                if (def_sym->visible != no)
                        return def_sym;
        }
 
        /* just get the first visible value */
        prop = sym_get_choice_prop(sym);
-       expr_list_for_each_sym(prop->expr, e, def_sym) {
-               sym_calc_visibility(def_sym);
+       expr_list_for_each_sym(prop->expr, e, def_sym)
                if (def_sym->visible != no)
                        return def_sym;
-       }
 
        /* no choice? reset tristate value */
        sym->curr.tri = no;
@@ -321,6 +330,14 @@ void sym_calc_value(struct symbol *sym)
                                }
                        }
                calc_newval:
+                       if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
+                               fprintf(stderr, "warning: (");
+                               expr_fprint(sym->rev_dep.expr, stderr);
+                               fprintf(stderr, ") selects %s which has unmet direct dependencies (",
+                                       sym->name);
+                               expr_fprint(sym->dir_dep.expr, stderr);
+                               fprintf(stderr, ")\n");
+                       }
                        newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
                }
                if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
@@ -365,12 +382,13 @@ void sym_calc_value(struct symbol *sym)
 
        if (sym_is_choice(sym)) {
                struct symbol *choice_sym;
-               int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
 
                prop = sym_get_choice_prop(sym);
                expr_list_for_each_sym(prop->expr, e, choice_sym) {
-                       choice_sym->flags |= flags;
-                       if (flags & SYMBOL_CHANGED)
+                       if ((sym->flags & SYMBOL_WRITE) &&
+                           choice_sym->visible != no)
+                               choice_sym->flags |= SYMBOL_WRITE;
+                       if (sym->flags & SYMBOL_CHANGED)
                                sym_set_changed(choice_sym);
                }
        }
@@ -651,12 +669,20 @@ bool sym_is_changable(struct symbol *sym)
        return sym->visible > sym->rev_dep.tri;
 }
 
+static unsigned strhash(const char *s)
+{
+       /* fnv32 hash */
+       unsigned hash = 2166136261U;
+       for (; *s; s++)
+               hash = (hash ^ *s) * 0x01000193;
+       return hash;
+}
+
 struct symbol *sym_lookup(const char *name, int flags)
 {
        struct symbol *symbol;
-       const char *ptr;
        char *new_name;
-       int hash = 0;
+       int hash;
 
        if (name) {
                if (name[0] && !name[1]) {
@@ -666,12 +692,11 @@ struct symbol *sym_lookup(const char *name, int flags)
                        case 'n': return &symbol_no;
                        }
                }
-               for (ptr = name; *ptr; ptr++)
-                       hash += *ptr;
-               hash &= 0xff;
+               hash = strhash(name) % SYMBOL_HASHSIZE;
 
                for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
-                       if (!strcmp(symbol->name, name) &&
+                       if (symbol->name &&
+                           !strcmp(symbol->name, name) &&
                            (flags ? symbol->flags & flags
                                   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
                                return symbol;
@@ -679,7 +704,7 @@ struct symbol *sym_lookup(const char *name, int flags)
                new_name = strdup(name);
        } else {
                new_name = NULL;
-               hash = 256;
+               hash = 0;
        }
 
        symbol = malloc(sizeof(*symbol));
@@ -697,7 +722,6 @@ struct symbol *sym_lookup(const char *name, int flags)
 struct symbol *sym_find(const char *name)
 {
        struct symbol *symbol = NULL;
-       const char *ptr;
        int hash = 0;
 
        if (!name)
@@ -710,12 +734,11 @@ struct symbol *sym_find(const char *name)
                case 'n': return &symbol_no;
                }
        }
-       for (ptr = name; *ptr; ptr++)
-               hash += *ptr;
-       hash &= 0xff;
+       hash = strhash(name) % SYMBOL_HASHSIZE;
 
        for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
-               if (!strcmp(symbol->name, name) &&
+               if (symbol->name &&
+                   !strcmp(symbol->name, name) &&
                    !(symbol->flags & SYMBOL_CONST))
                                break;
        }
@@ -750,6 +773,7 @@ struct symbol **sym_re_search(const char *pattern)
                                return NULL;
                        }
                }
+               sym_calc_value(sym);
                sym_arr[cnt++] = sym;
        }
        if (sym_arr)
@@ -937,6 +961,8 @@ const char *prop_get_type_name(enum prop_type type)
                return "select";
        case P_RANGE:
                return "range";
+       case P_SYMBOL:
+               return "symbol";
        case P_UNKNOWN:
                break;
        }