kconfig: fix choice dependency check

Properly check the dependency of choices as a group.
Also fix that sym_check_deps() correctly terminates the dependency loop
error check (otherwise it would continue printing the dependency chain).

Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>

=======

Cherry-picked from the Linux kernel.

Change-Id: I0c98760dd0f55cf2ff70c53e0b014288b59574c8
Signed-off-by: Gabe Black <gabeblack@chromium.org>
Reviewed-on: http://review.coreboot.org/3290
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
Roman Zippel 2008-02-29 05:10:24 +01:00 committed by Ronald G. Minnich
parent 48757668a5
commit 330bb6acc8
1 changed files with 81 additions and 23 deletions

View File

@ -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) static struct symbol *sym_check_expr_deps(struct expr *e)
{ {
struct symbol *sym; struct symbol *sym;
@ -803,6 +801,65 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
} }
/* return NULL when dependencies are OK */ /* return NULL when dependencies are OK */
static struct symbol *sym_check_sym_deps(struct symbol *sym)
{
struct symbol *sym2;
struct property *prop;
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
if (sym2)
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)
break;
if (prop->type != P_DEFAULT || sym_is_choice(sym))
continue;
sym2 = sym_check_expr_deps(prop->expr);
if (sym2)
break;
}
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)
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 *sym_check_deps(struct symbol *sym)
{ {
struct symbol *sym2; struct symbol *sym2;
@ -810,33 +867,34 @@ struct symbol *sym_check_deps(struct symbol *sym)
if (sym->flags & SYMBOL_CHECK) { if (sym->flags & SYMBOL_CHECK) {
fprintf(stderr, "%s:%d:error: found recursive dependency: %s", fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
sym->prop->file->name, sym->prop->lineno, sym->name); sym->prop->file->name, sym->prop->lineno,
sym->name ? sym->name : "<choice>");
return sym; return sym;
} }
if (sym->flags & SYMBOL_CHECKED) if (sym->flags & SYMBOL_CHECKED)
return NULL; return NULL;
sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); if (sym_is_choice_value(sym)) {
sym2 = sym_check_expr_deps(sym->rev_dep.expr); /* for choice groups start the check with main choice symbol */
if (sym2) prop = sym_get_choice_prop(sym);
goto out; sym2 = sym_check_deps(prop_get_symbol(prop));
} else if (sym_is_choice(sym)) {
for (prop = sym->prop; prop; prop = prop->next) { sym2 = sym_check_choice_deps(sym);
if (prop->type == P_CHOICE || prop->type == P_SELECT) } else {
continue; sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
sym2 = sym_check_expr_deps(prop->visible.expr); sym2 = sym_check_sym_deps(sym);
if (sym2) sym->flags &= ~SYMBOL_CHECK;
goto out;
if (prop->type != P_DEFAULT || sym_is_choice(sym))
continue;
sym2 = sym_check_expr_deps(prop->expr);
if (sym2)
goto out;
} }
out:
if (sym2) if (sym2) {
fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": ""); fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
sym->flags &= ~SYMBOL_CHECK; if (sym2 == sym) {
fprintf(stderr, "\n");
zconfnerrs++;
sym2 = NULL;
}
}
return sym2; return sym2;
} }