diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2008-02-28 23:10:24 -0500 |
---|---|---|
committer | Sam Ravnborg <sam@uranus.ravnborg.org> | 2008-04-28 17:04:57 -0400 |
commit | 48981178869bf7d9770f11fc361996ad11217a75 (patch) | |
tree | 7e1cc7382f04ac3e724996a9ea13023bdb531f9a /scripts | |
parent | dfecbec8b54038ef02835d2f8181e1f44bd080d2 (diff) |
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>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/kconfig/symbol.c | 94 |
1 files changed, 76 insertions, 18 deletions
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 4a03191ad176..45f409a8f37f 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c | |||
@@ -762,8 +762,6 @@ struct symbol **sym_re_search(const char *pattern) | |||
762 | } | 762 | } |
763 | 763 | ||
764 | 764 | ||
765 | struct symbol *sym_check_deps(struct symbol *sym); | ||
766 | |||
767 | static struct symbol *sym_check_expr_deps(struct expr *e) | 765 | static struct symbol *sym_check_expr_deps(struct expr *e) |
768 | { | 766 | { |
769 | struct symbol *sym; | 767 | struct symbol *sym; |
@@ -795,40 +793,100 @@ static struct symbol *sym_check_expr_deps(struct expr *e) | |||
795 | } | 793 | } |
796 | 794 | ||
797 | /* return NULL when dependencies are OK */ | 795 | /* return NULL when dependencies are OK */ |
798 | struct symbol *sym_check_deps(struct symbol *sym) | 796 | static struct symbol *sym_check_sym_deps(struct symbol *sym) |
799 | { | 797 | { |
800 | struct symbol *sym2; | 798 | struct symbol *sym2; |
801 | struct property *prop; | 799 | struct property *prop; |
802 | 800 | ||
803 | if (sym->flags & SYMBOL_CHECK) { | ||
804 | fprintf(stderr, "%s:%d:error: found recursive dependency: %s", | ||
805 | sym->prop->file->name, sym->prop->lineno, sym->name); | ||
806 | return sym; | ||
807 | } | ||
808 | if (sym->flags & SYMBOL_CHECKED) | ||
809 | return NULL; | ||
810 | |||
811 | sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); | ||
812 | sym2 = sym_check_expr_deps(sym->rev_dep.expr); | 801 | sym2 = sym_check_expr_deps(sym->rev_dep.expr); |
813 | if (sym2) | 802 | if (sym2) |
814 | goto out; | 803 | return sym2; |
815 | 804 | ||
816 | for (prop = sym->prop; prop; prop = prop->next) { | 805 | for (prop = sym->prop; prop; prop = prop->next) { |
817 | if (prop->type == P_CHOICE || prop->type == P_SELECT) | 806 | if (prop->type == P_CHOICE || prop->type == P_SELECT) |
818 | continue; | 807 | continue; |
819 | sym2 = sym_check_expr_deps(prop->visible.expr); | 808 | sym2 = sym_check_expr_deps(prop->visible.expr); |
820 | if (sym2) | 809 | if (sym2) |
821 | goto out; | 810 | break; |
822 | if (prop->type != P_DEFAULT || sym_is_choice(sym)) | 811 | if (prop->type != P_DEFAULT || sym_is_choice(sym)) |
823 | continue; | 812 | continue; |
824 | sym2 = sym_check_expr_deps(prop->expr); | 813 | sym2 = sym_check_expr_deps(prop->expr); |
825 | if (sym2) | 814 | if (sym2) |
826 | goto out; | 815 | break; |
827 | } | 816 | } |
828 | out: | 817 | |
818 | return sym2; | ||
819 | } | ||
820 | |||
821 | static struct symbol *sym_check_choice_deps(struct symbol *choice) | ||
822 | { | ||
823 | struct symbol *sym, *sym2; | ||
824 | struct property *prop; | ||
825 | struct expr *e; | ||
826 | |||
827 | prop = sym_get_choice_prop(choice); | ||
828 | expr_list_for_each_sym(prop->expr, e, sym) | ||
829 | sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); | ||
830 | |||
831 | choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); | ||
832 | sym2 = sym_check_sym_deps(choice); | ||
833 | choice->flags &= ~SYMBOL_CHECK; | ||
829 | if (sym2) | 834 | if (sym2) |
830 | fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": ""); | 835 | goto out; |
831 | sym->flags &= ~SYMBOL_CHECK; | 836 | |
837 | expr_list_for_each_sym(prop->expr, e, sym) { | ||
838 | sym2 = sym_check_sym_deps(sym); | ||
839 | if (sym2) { | ||
840 | fprintf(stderr, " -> %s", sym->name); | ||
841 | break; | ||
842 | } | ||
843 | } | ||
844 | out: | ||
845 | expr_list_for_each_sym(prop->expr, e, sym) | ||
846 | sym->flags &= ~SYMBOL_CHECK; | ||
847 | |||
848 | if (sym2 && sym_is_choice_value(sym2) && | ||
849 | prop_get_symbol(sym_get_choice_prop(sym2)) == choice) | ||
850 | sym2 = choice; | ||
851 | |||
852 | return sym2; | ||
853 | } | ||
854 | |||
855 | struct symbol *sym_check_deps(struct symbol *sym) | ||
856 | { | ||
857 | struct symbol *sym2; | ||
858 | struct property *prop; | ||
859 | |||
860 | if (sym->flags & SYMBOL_CHECK) { | ||
861 | fprintf(stderr, "%s:%d:error: found recursive dependency: %s", | ||
862 | sym->prop->file->name, sym->prop->lineno, | ||
863 | sym->name ? sym->name : "<choice>"); | ||
864 | return sym; | ||
865 | } | ||
866 | if (sym->flags & SYMBOL_CHECKED) | ||
867 | return NULL; | ||
868 | |||
869 | if (sym_is_choice_value(sym)) { | ||
870 | /* for choice groups start the check with main choice symbol */ | ||
871 | prop = sym_get_choice_prop(sym); | ||
872 | sym2 = sym_check_deps(prop_get_symbol(prop)); | ||
873 | } else if (sym_is_choice(sym)) { | ||
874 | sym2 = sym_check_choice_deps(sym); | ||
875 | } else { | ||
876 | sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); | ||
877 | sym2 = sym_check_sym_deps(sym); | ||
878 | sym->flags &= ~SYMBOL_CHECK; | ||
879 | } | ||
880 | |||
881 | if (sym2) { | ||
882 | fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>"); | ||
883 | if (sym2 == sym) { | ||
884 | fprintf(stderr, "\n"); | ||
885 | zconfnerrs++; | ||
886 | sym2 = NULL; | ||
887 | } | ||
888 | } | ||
889 | |||
832 | return sym2; | 890 | return sym2; |
833 | } | 891 | } |
834 | 892 | ||