History

kconfig: print more info when we see a recursive dependency

Consider following kconfig file: config TEST1 bool "test 1" depends on TEST2 config TEST2 bool "test 2" depends on TEST1 Previously kconfig would report: foo:6:error: found recursive dependency: TEST2 -> TEST1 -> TEST2 With the following patch kconfig reports: foo:5:error: recursive dependency detected! foo:5: symbol TEST2 depends on TEST1 foo:1: symbol TEST1 depends on TEST2 Note that we now report where the offending symbols are defined. This can be a great help for complex situations involving several files. Patch is originally from Roman Zippel with a few adjustments by Sam.

Roman Zippel committed 16 years ago

Commit d595cea1 parent 59e89e31 file · +127 −15Browse files

Showing the changes to scripts (1 of 1 file). Show all

Unified · Split

scripts/kconfig/symbol.c+127−15
@@ -783,6 +783,110 @@ struct symbol **sym_re_search(const char *pattern) · 782 unmodified lines
783783 return sym_arr;
784784 }
785785
786+/*
787+ * When we check for recursive dependencies we use a stack to save
788+ * current state so we can print out relevant info to user.
789+ * The entries are located on the call stack so no need to free memory.
790+ * Note inser() remove() must always match to properly clear the stack.
791+ */
792+static struct dep_stack {
793+ struct dep_stack *prev, *next;
794+ struct symbol *sym;
795+ struct property *prop;
796+ struct expr *expr;
797+} *check_top;
798+
799+static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
800+{
801+ memset(stack, 0, sizeof(*stack));
802+ if (check_top)
803+ check_top->next = stack;
804+ stack->prev = check_top;
805+ stack->sym = sym;
806+ check_top = stack;
807+}
808+
809+static void dep_stack_remove(void)
810+{
811+ check_top = check_top->prev;
812+ if (check_top)
813+ check_top->next = NULL;
814+}
815+
816+/*
817+ * Called when we have detected a recursive dependency.
818+ * check_top point to the top of the stact so we use
819+ * the ->prev pointer to locate the bottom of the stack.
820+ */
821+static void sym_check_print_recursive(struct symbol *last_sym)
822+{
823+ struct dep_stack *stack;
824+ struct symbol *sym, *next_sym;
825+ struct menu *menu = NULL;
826+ struct property *prop;
827+ struct dep_stack cv_stack;
828+
829+ if (sym_is_choice_value(last_sym)) {
830+ dep_stack_insert(&cv_stack, last_sym);
831+ last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
832+ }
833+
834+ for (stack = check_top; stack != NULL; stack = stack->prev)
835+ if (stack->sym == last_sym)
836+ break;
837+ if (!stack) {
838+ fprintf(stderr, "unexpected recursive dependency error\n");
839+ return;
840+ }
841+
842+ for (; stack; stack = stack->next) {
843+ sym = stack->sym;
844+ next_sym = stack->next ? stack->next->sym : last_sym;
845+ prop = stack->prop;
846+
847+ /* for choice values find the menu entry (used below) */
848+ if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
849+ for (prop = sym->prop; prop; prop = prop->next) {
850+ menu = prop->menu;
851+ if (prop->menu)
852+ break;
853+ }
854+ }
855+ if (stack->sym == last_sym)
856+ fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
857+ prop->file->name, prop->lineno);
858+ if (stack->expr) {
859+ fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
860+ prop->file->name, prop->lineno,
861+ sym->name ? sym->name : "<choice>",
862+ prop_get_type_name(prop->type),
863+ next_sym->name ? next_sym->name : "<choice>");
864+ } else if (stack->prop) {
865+ fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
866+ prop->file->name, prop->lineno,
867+ sym->name ? sym->name : "<choice>",
868+ next_sym->name ? next_sym->name : "<choice>");
869+ } else if (sym_is_choice(sym)) {
870+ fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
871+ menu->file->name, menu->lineno,
872+ sym->name ? sym->name : "<choice>",
873+ next_sym->name ? next_sym->name : "<choice>");
874+ } else if (sym_is_choice_value(sym)) {
875+ fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
876+ menu->file->name, menu->lineno,
877+ sym->name ? sym->name : "<choice>",
878+ next_sym->name ? next_sym->name : "<choice>");
879+ } else {
880+ fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
881+ prop->file->name, prop->lineno,
882+ sym->name ? sym->name : "<choice>",
883+ next_sym->name ? next_sym->name : "<choice>");
884+ }
885+ }
886+
887+ if (check_top == &cv_stack)
888+ dep_stack_remove();
889+}
786890
787891 static struct symbol *sym_check_expr_deps(struct expr *e)
788892 {
@@ -819,24 +923,33 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) · 30 unmodified lines
819923 {
820924 struct symbol *sym2;
821925 struct property *prop;
926+ struct dep_stack stack;
927+
928+ dep_stack_insert(&stack, sym);
822929
823930 sym2 = sym_check_expr_deps(sym->rev_dep.expr);
824931 if (sym2)
825− return sym2;
932+ goto out;
826933
827934 for (prop = sym->prop; prop; prop = prop->next) {
828935 if (prop->type == P_CHOICE || prop->type == P_SELECT)
829936 continue;
937+ stack.prop = prop;
830938 sym2 = sym_check_expr_deps(prop->visible.expr);
831939 if (sym2)
832940 break;
833941 if (prop->type != P_DEFAULT || sym_is_choice(sym))
834942 continue;
943+ stack.expr = prop->expr;
835944 sym2 = sym_check_expr_deps(prop->expr);
836945 if (sym2)
837946 break;
947+ stack.expr = NULL;
838948 }
839949
950+out:
951+ dep_stack_remove();
952+
840953 return sym2;
841954 }
842955
@@ -845,6 +958,9 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice) · 2 unmodified lines
845958 struct symbol *sym, *sym2;
846959 struct property *prop;
847960 struct expr *e;
961+ struct dep_stack stack;
962+
963+ dep_stack_insert(&stack, choice);
848964
849965 prop = sym_get_choice_prop(choice);
850966 expr_list_for_each_sym(prop->expr, e, sym)
@@ -858,10 +974,8 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice) · 7 unmodified lines
858974
859975 expr_list_for_each_sym(prop->expr, e, sym) {
860976 sym2 = sym_check_sym_deps(sym);
861− if (sym2) {
862− fprintf(stderr, " -> %s", sym->name);
977+ if (sym2)
863978 break;
864− }
865979 }
866980 out:
867981 expr_list_for_each_sym(prop->expr, e, sym)
@@ -871,6 +985,8 @@ out: · 3 unmodified lines
871985 prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
872986 sym2 = choice;
873987
988+ dep_stack_remove();
989+
874990 return sym2;
875991 }
876992
@@ -880,18 +996,20 @@ struct symbol *sym_check_deps(struct symbol *sym) · 3 unmodified lines
880996 struct property *prop;
881997
882998 if (sym->flags & SYMBOL_CHECK) {
883− fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
884− sym->prop->file->name, sym->prop->lineno,
885− sym->name ? sym->name : "<choice>");
999+ sym_check_print_recursive(sym);
8861000 return sym;
8871001 }
8881002 if (sym->flags & SYMBOL_CHECKED)
8891003 return NULL;
8901004
8911005 if (sym_is_choice_value(sym)) {
1006+ struct dep_stack stack;
1007+
8921008 /* for choice groups start the check with main choice symbol */
1009+ dep_stack_insert(&stack, sym);
8931010 prop = sym_get_choice_prop(sym);
8941011 sym2 = sym_check_deps(prop_get_symbol(prop));
1012+ dep_stack_remove();
8951013 } else if (sym_is_choice(sym)) {
8961014 sym2 = sym_check_choice_deps(sym);
8971015 } else {
@@ -900,14 +1018,8 @@ struct symbol *sym_check_deps(struct symbol *sym) · 2 unmodified lines
9001018 sym->flags &= ~SYMBOL_CHECK;
9011019 }
9021020
903− if (sym2) {
904− fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
905− if (sym2 == sym) {
906− fprintf(stderr, "\n");
907− zconfnerrs++;
908− sym2 = NULL;
909− }
910− }
1021+ if (sym2 && sym2 == sym)
1022+ sym2 = NULL;
9111023
9121024 return sym2;
9131025 }