diff options
author | Yann E. MORIN <yann.morin.1998@free.fr> | 2013-04-28 16:36:38 -0400 |
---|---|---|
committer | Yann E. MORIN <yann.morin.1998@free.fr> | 2013-06-24 14:03:30 -0400 |
commit | 3b9a19e08960e5cdad5253998637653e592a3c29 (patch) | |
tree | 2293b53b7f29ff79f67fa7245ea027a36bda91fc /scripts/kconfig | |
parent | a1ce636f560336ba007bfabb15b167ff31b592cf (diff) |
kconfig: loop as long as we changed some symbols in randconfig
Because of choice-in-a-choice constructs, it can happen that not all
symbols are assigned a value during randconfig, leading in rare cases
to this situation:
---8<--- choice-in-choice.in
choice
bool "A/B/C"
config A
bool "A"
config B
bool "B"
if B
choice
bool "E/F"
config E
bool "E"
config F
bool "F"
endchoice
endif # B
config C
bool "C"
endchoice
---8<---
$ ./scripts/kconfig/conf --randconfig choice-in-choice.in
[--SNIP--]
$ ./scripts/kconfig/conf --silentoldconfig choice-in-choice.in </dev/null
[--SNIP--]
A/B/C
1. A (A)
> 2. B (B)
3. C (C)
choice[1-3]: 2
E/F
> 1. E (E) (NEW)
2. F (F) (NEW)
choice[1-2]: aborted!
Console input/output is redirected. Run 'make oldconfig' to update
configuration.
Fix this by looping in randconfig for as long as some symbol gets assigned
a value.
Note: this was spotted with the USB EHCI Debug Device Gadget (USB_G_DBGP),
which uses this choice-in-a-choice construct, and exhibits this problem.
The example above is just a stripped-down minimalist test-case.
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Diffstat (limited to 'scripts/kconfig')
-rw-r--r-- | scripts/kconfig/conf.c | 3 | ||||
-rw-r--r-- | scripts/kconfig/confdata.c | 18 | ||||
-rw-r--r-- | scripts/kconfig/lkc.h | 2 |
3 files changed, 17 insertions, 6 deletions
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 38616c14c071..d19944f9c3ac 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c | |||
@@ -654,7 +654,8 @@ int main(int ac, char **av) | |||
654 | conf_set_all_new_symbols(def_default); | 654 | conf_set_all_new_symbols(def_default); |
655 | break; | 655 | break; |
656 | case randconfig: | 656 | case randconfig: |
657 | conf_set_all_new_symbols(def_random); | 657 | /* Really nothing to do in this loop */ |
658 | while (conf_set_all_new_symbols(def_random)) ; | ||
658 | break; | 659 | break; |
659 | case defconfig: | 660 | case defconfig: |
660 | conf_set_all_new_symbols(def_default); | 661 | conf_set_all_new_symbols(def_default); |
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index d36bc1f1d563..c55c227af463 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c | |||
@@ -1040,7 +1040,7 @@ void conf_set_changed_callback(void (*fn)(void)) | |||
1040 | conf_changed_callback = fn; | 1040 | conf_changed_callback = fn; |
1041 | } | 1041 | } |
1042 | 1042 | ||
1043 | static void randomize_choice_values(struct symbol *csym) | 1043 | static bool randomize_choice_values(struct symbol *csym) |
1044 | { | 1044 | { |
1045 | struct property *prop; | 1045 | struct property *prop; |
1046 | struct symbol *sym; | 1046 | struct symbol *sym; |
@@ -1053,7 +1053,7 @@ static void randomize_choice_values(struct symbol *csym) | |||
1053 | * In both cases stop. | 1053 | * In both cases stop. |
1054 | */ | 1054 | */ |
1055 | if (csym->curr.tri != yes) | 1055 | if (csym->curr.tri != yes) |
1056 | return; | 1056 | return false; |
1057 | 1057 | ||
1058 | prop = sym_get_choice_prop(csym); | 1058 | prop = sym_get_choice_prop(csym); |
1059 | 1059 | ||
@@ -1084,6 +1084,8 @@ static void randomize_choice_values(struct symbol *csym) | |||
1084 | csym->flags |= SYMBOL_DEF_USER; | 1084 | csym->flags |= SYMBOL_DEF_USER; |
1085 | /* clear VALID to get value calculated */ | 1085 | /* clear VALID to get value calculated */ |
1086 | csym->flags &= ~(SYMBOL_VALID); | 1086 | csym->flags &= ~(SYMBOL_VALID); |
1087 | |||
1088 | return true; | ||
1087 | } | 1089 | } |
1088 | 1090 | ||
1089 | void set_all_choice_values(struct symbol *csym) | 1091 | void set_all_choice_values(struct symbol *csym) |
@@ -1106,7 +1108,7 @@ void set_all_choice_values(struct symbol *csym) | |||
1106 | csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); | 1108 | csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); |
1107 | } | 1109 | } |
1108 | 1110 | ||
1109 | void conf_set_all_new_symbols(enum conf_def_mode mode) | 1111 | bool conf_set_all_new_symbols(enum conf_def_mode mode) |
1110 | { | 1112 | { |
1111 | struct symbol *sym, *csym; | 1113 | struct symbol *sym, *csym; |
1112 | int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y | 1114 | int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y |
@@ -1154,6 +1156,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) | |||
1154 | exit( 1 ); | 1156 | exit( 1 ); |
1155 | } | 1157 | } |
1156 | } | 1158 | } |
1159 | bool has_changed = false; | ||
1157 | 1160 | ||
1158 | for_all_symbols(i, sym) { | 1161 | for_all_symbols(i, sym) { |
1159 | if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) | 1162 | if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) |
@@ -1161,6 +1164,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) | |||
1161 | switch (sym_get_type(sym)) { | 1164 | switch (sym_get_type(sym)) { |
1162 | case S_BOOLEAN: | 1165 | case S_BOOLEAN: |
1163 | case S_TRISTATE: | 1166 | case S_TRISTATE: |
1167 | has_changed = true; | ||
1164 | switch (mode) { | 1168 | switch (mode) { |
1165 | case def_yes: | 1169 | case def_yes: |
1166 | sym->def[S_DEF_USER].tri = yes; | 1170 | sym->def[S_DEF_USER].tri = yes; |
@@ -1219,6 +1223,12 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) | |||
1219 | 1223 | ||
1220 | sym_calc_value(csym); | 1224 | sym_calc_value(csym); |
1221 | if (mode == def_random) | 1225 | if (mode == def_random) |
1222 | randomize_choice_values(csym); | 1226 | has_changed = randomize_choice_values(csym); |
1227 | else { | ||
1228 | set_all_choice_values(csym); | ||
1229 | has_changed = true; | ||
1230 | } | ||
1223 | } | 1231 | } |
1232 | |||
1233 | return has_changed; | ||
1224 | } | 1234 | } |
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 0c8d4191ca87..09f4edfdc911 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h | |||
@@ -86,7 +86,7 @@ const char *conf_get_autoconfig_name(void); | |||
86 | char *conf_get_default_confname(void); | 86 | char *conf_get_default_confname(void); |
87 | void sym_set_change_count(int count); | 87 | void sym_set_change_count(int count); |
88 | void sym_add_change_count(int count); | 88 | void sym_add_change_count(int count); |
89 | void conf_set_all_new_symbols(enum conf_def_mode mode); | 89 | bool conf_set_all_new_symbols(enum conf_def_mode mode); |
90 | void set_all_choice_values(struct symbol *csym); | 90 | void set_all_choice_values(struct symbol *csym); |
91 | 91 | ||
92 | struct conf_printer { | 92 | struct conf_printer { |