summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util/kconfig/symbol.c94
1 files changed, 76 insertions, 18 deletions
diff --git a/util/kconfig/symbol.c b/util/kconfig/symbol.c
index e4076e9357..06e50a0494 100644
--- a/util/kconfig/symbol.c
+++ b/util/kconfig/symbol.c
@@ -770,8 +770,6 @@ struct symbol **sym_re_search(const char *pattern)
}
-struct symbol *sym_check_deps(struct symbol *sym);
-
static struct symbol *sym_check_expr_deps(struct expr *e)
{
struct symbol *sym;
@@ -803,40 +801,100 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
}
/* return NULL when dependencies are OK */
-struct symbol *sym_check_deps(struct symbol *sym)
+static struct symbol *sym_check_sym_deps(struct symbol *sym)
{
struct symbol *sym2;
struct property *prop;
- if (sym->flags & SYMBOL_CHECK) {
- fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
- sym->prop->file->name, sym->prop->lineno, sym->name);
- return sym;
- }
- if (sym->flags & SYMBOL_CHECKED)
- return NULL;
-
- sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
if (sym2)
- goto out;
+ return sym2;
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->type == P_CHOICE || prop->type == P_SELECT)
continue;
sym2 = sym_check_expr_deps(prop->visible.expr);
if (sym2)
- goto out;
+ break;
if (prop->type != P_DEFAULT || sym_is_choice(sym))
continue;
sym2 = sym_check_expr_deps(prop->expr);
if (sym2)
- goto out;
+ break;
}
-out:
+
+ return sym2;
+}
+
+static struct symbol *sym_check_choice_deps(struct symbol *choice)
+{
+ struct symbol *sym, *sym2;
+ struct property *prop;
+ struct expr *e;
+
+ prop = sym_get_choice_prop(choice);
+ expr_list_for_each_sym(prop->expr, e, sym)
+ sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+
+ choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+ sym2 = sym_check_sym_deps(choice);
+ choice->flags &= ~SYMBOL_CHECK;
if (sym2)
- fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": "");
- sym->flags &= ~SYMBOL_CHECK;
+ goto out;
+
+ expr_list_for_each_sym(prop->expr, e, sym) {
+ sym2 = sym_check_sym_deps(sym);
+ if (sym2) {
+ fprintf(stderr, " -> %s", sym->name);
+ break;
+ }
+ }
+out:
+ expr_list_for_each_sym(prop->expr, e, sym)
+ sym->flags &= ~SYMBOL_CHECK;
+
+ if (sym2 && sym_is_choice_value(sym2) &&
+ prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
+ sym2 = choice;
+
+ return sym2;
+}
+
+struct symbol *sym_check_deps(struct symbol *sym)
+{
+ struct symbol *sym2;
+ struct property *prop;
+
+ if (sym->flags & SYMBOL_CHECK) {
+ fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
+ sym->prop->file->name, sym->prop->lineno,
+ sym->name ? sym->name : "<choice>");
+ return sym;
+ }
+ if (sym->flags & SYMBOL_CHECKED)
+ return NULL;
+
+ if (sym_is_choice_value(sym)) {
+ /* for choice groups start the check with main choice symbol */
+ prop = sym_get_choice_prop(sym);
+ sym2 = sym_check_deps(prop_get_symbol(prop));
+ } else if (sym_is_choice(sym)) {
+ sym2 = sym_check_choice_deps(sym);
+ } else {
+ sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+ sym2 = sym_check_sym_deps(sym);
+ sym->flags &= ~SYMBOL_CHECK;
+ }
+
+ if (sym2) {
+ fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
+ if (sym2 == sym) {
+ fprintf(stderr, "\n");
+ zconfnerrs++;
+ sym2 = NULL;
+ }
+ }
+
return sym2;
}