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

Unified · Split

scripts/kconfig/symbol.c+127−15
@@ -783,6 +783,110 @@ struct symbol **sym_re_search(const char *pattern) · 782 unmodified lines
783 return sym_arr;783 return sym_arr;
784}784}
785 785
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 */
792static 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
799static 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
809static 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 */
821static 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}
786 890
787static struct symbol *sym_check_expr_deps(struct expr *e)891static struct symbol *sym_check_expr_deps(struct expr *e)
788{892{
@@ -819,24 +923,33 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) · 30 unmodified lines
819{923{
820 struct symbol *sym2;924 struct symbol *sym2;
821 struct property *prop;925 struct property *prop;
926 struct dep_stack stack;
927
928 dep_stack_insert(&stack, sym);
822 929
823 sym2 = sym_check_expr_deps(sym->rev_dep.expr);930 sym2 = sym_check_expr_deps(sym->rev_dep.expr);
824 if (sym2)931 if (sym2)
825 return sym2;932 goto out;
826 933
827 for (prop = sym->prop; prop; prop = prop->next) {934 for (prop = sym->prop; prop; prop = prop->next) {
828 if (prop->type == P_CHOICE || prop->type == P_SELECT)935 if (prop->type == P_CHOICE || prop->type == P_SELECT)
829 continue;936 continue;
937 stack.prop = prop;
830 sym2 = sym_check_expr_deps(prop->visible.expr);938 sym2 = sym_check_expr_deps(prop->visible.expr);
831 if (sym2)939 if (sym2)
832 break;940 break;
833 if (prop->type != P_DEFAULT || sym_is_choice(sym))941 if (prop->type != P_DEFAULT || sym_is_choice(sym))
834 continue;942 continue;
943 stack.expr = prop->expr;
835 sym2 = sym_check_expr_deps(prop->expr);944 sym2 = sym_check_expr_deps(prop->expr);
836 if (sym2)945 if (sym2)
837 break;946 break;
947 stack.expr = NULL;
838 }948 }
839 949
950out:
951 dep_stack_remove();
952
840 return sym2;953 return sym2;
841}954}
842 955
@@ -845,6 +958,9 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice) · 2 unmodified lines
845 struct symbol *sym, *sym2;958 struct symbol *sym, *sym2;
846 struct property *prop;959 struct property *prop;
847 struct expr *e;960 struct expr *e;
961 struct dep_stack stack;
962
963 dep_stack_insert(&stack, choice);
848 964
849 prop = sym_get_choice_prop(choice);965 prop = sym_get_choice_prop(choice);
850 expr_list_for_each_sym(prop->expr, e, sym)966 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
858 974
859 expr_list_for_each_sym(prop->expr, e, sym) {975 expr_list_for_each_sym(prop->expr, e, sym) {
860 sym2 = sym_check_sym_deps(sym);976 sym2 = sym_check_sym_deps(sym);
861 if (sym2) {977 if (sym2)
862 fprintf(stderr, " -> %s", sym->name);
863 break;978 break;
864 }
865 }979 }
866out:980out:
867 expr_list_for_each_sym(prop->expr, e, sym)981 expr_list_for_each_sym(prop->expr, e, sym)
@@ -871,6 +985,8 @@ out: · 3 unmodified lines
871 prop_get_symbol(sym_get_choice_prop(sym2)) == choice)985 prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
872 sym2 = choice;986 sym2 = choice;
873 987
988 dep_stack_remove();
989
874 return sym2;990 return sym2;
875}991}
876 992
@@ -880,18 +996,20 @@ struct symbol *sym_check_deps(struct symbol *sym) · 3 unmodified lines
880 struct property *prop;996 struct property *prop;
881 997
882 if (sym->flags & SYMBOL_CHECK) {998 if (sym->flags & SYMBOL_CHECK) {
883 fprintf(stderr, "%s:%d:error: found recursive dependency: %s",999 sym_check_print_recursive(sym);
884 sym->prop->file->name, sym->prop->lineno,
885 sym->name ? sym->name : "<choice>");
886 return sym;1000 return sym;
887 }1001 }
888 if (sym->flags & SYMBOL_CHECKED)1002 if (sym->flags & SYMBOL_CHECKED)
889 return NULL;1003 return NULL;
890 1004
891 if (sym_is_choice_value(sym)) {1005 if (sym_is_choice_value(sym)) {
1006 struct dep_stack stack;
1007
892 /* for choice groups start the check with main choice symbol */1008 /* for choice groups start the check with main choice symbol */
1009 dep_stack_insert(&stack, sym);
893 prop = sym_get_choice_prop(sym);1010 prop = sym_get_choice_prop(sym);
894 sym2 = sym_check_deps(prop_get_symbol(prop));1011 sym2 = sym_check_deps(prop_get_symbol(prop));
1012 dep_stack_remove();
895 } else if (sym_is_choice(sym)) {1013 } else if (sym_is_choice(sym)) {
896 sym2 = sym_check_choice_deps(sym);1014 sym2 = sym_check_choice_deps(sym);
897 } else {1015 } else {
@@ -900,14 +1018,8 @@ struct symbol *sym_check_deps(struct symbol *sym) · 2 unmodified lines
900 sym->flags &= ~SYMBOL_CHECK;1018 sym->flags &= ~SYMBOL_CHECK;
901 }1019 }
902 1020
903 if (sym2) {1021 if (sym2 && sym2 == sym)
904 fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");1022 sym2 = NULL;
905 if (sym2 == sym) {
906 fprintf(stderr, "\n");
907 zconfnerrs++;
908 sym2 = NULL;
909 }
910 }
911 1023
912 return sym2;1024 return sym2;
913}1025}