aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2010-08-12 03:11:52 -0400
committerMichal Marek <mmarek@suse.cz>2010-08-12 04:55:02 -0400
commita64b44ead002ba15fdf841106a6fd344b8dd46d8 (patch)
treed5f3be005c10369a69ea1d968c790854f9d52a1a /scripts
parent801690caf1894d4f8b1277ca9f5dcf0bcf9b3f58 (diff)
kconfig: fix tristate choice with minimal config
If a minimal config did not specify the value of all choice values, the resulting configuration could have wrong values. Consider following example: config M def_bool y option modules choice prompt "choice list" config A tristate "a" config B tristate "b" endchoice With a defconfig like this: CONFIG_M=y CONFIG_A=y The resulting configuration would have CONFIG_A=m which was unexpected. The problem was not not all choice values were set and thus kconfig calculated a wrong value. The fix is to set all choice values when we read a defconfig files. conf_set_all_new_symbols() is refactored such that random choice values are now handled by a dedicated function. And new choice values are set by set_all_choice_values(). This was not the minimal fix, but the fix that resulted in the most readable code. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reported-by: Arve Hjønnevåg <arve@android.com> Tested-by: Arve Hjønnevåg <arve@android.com> Signed-off-by: Michal Marek <mmarek@suse.cz>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/kconfig/confdata.c102
1 files changed, 67 insertions, 35 deletions
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index e5d66e4f1484..ac13f0ff8e81 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -918,13 +918,73 @@ void conf_set_changed_callback(void (*fn)(void))
918 conf_changed_callback = fn; 918 conf_changed_callback = fn;
919} 919}
920 920
921static void randomize_choice_values(struct symbol *csym)
922{
923 struct property *prop;
924 struct symbol *sym;
925 struct expr *e;
926 int cnt, def;
921 927
922void conf_set_all_new_symbols(enum conf_def_mode mode) 928 /*
929 * If choice is mod then we may have more items slected
930 * and if no then no-one.
931 * In both cases stop.
932 */
933 if (csym->curr.tri != yes)
934 return;
935
936 prop = sym_get_choice_prop(csym);
937
938 /* count entries in choice block */
939 cnt = 0;
940 expr_list_for_each_sym(prop->expr, e, sym)
941 cnt++;
942
943 /*
944 * find a random value and set it to yes,
945 * set the rest to no so we have only one set
946 */
947 def = (rand() % cnt);
948
949 cnt = 0;
950 expr_list_for_each_sym(prop->expr, e, sym) {
951 if (def == cnt++) {
952 sym->def[S_DEF_USER].tri = yes;
953 csym->def[S_DEF_USER].val = sym;
954 }
955 else {
956 sym->def[S_DEF_USER].tri = no;
957 }
958 }
959 csym->flags |= SYMBOL_DEF_USER;
960 /* clear VALID to get value calculated */
961 csym->flags &= ~(SYMBOL_VALID);
962}
963
964static void set_all_choice_values(struct symbol *csym)
923{ 965{
924 struct symbol *sym, *csym;
925 struct property *prop; 966 struct property *prop;
967 struct symbol *sym;
926 struct expr *e; 968 struct expr *e;
927 int i, cnt, def; 969
970 prop = sym_get_choice_prop(csym);
971
972 /*
973 * Set all non-assinged choice values to no
974 */
975 expr_list_for_each_sym(prop->expr, e, sym) {
976 if (!sym_has_value(sym))
977 sym->def[S_DEF_USER].tri = no;
978 }
979 csym->flags |= SYMBOL_DEF_USER;
980 /* clear VALID to get value calculated */
981 csym->flags &= ~(SYMBOL_VALID);
982}
983
984void conf_set_all_new_symbols(enum conf_def_mode mode)
985{
986 struct symbol *sym, *csym;
987 int i, cnt;
928 988
929 for_all_symbols(i, sym) { 989 for_all_symbols(i, sym) {
930 if (sym_has_value(sym)) 990 if (sym_has_value(sym))
@@ -960,8 +1020,6 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
960 1020
961 sym_clear_all_valid(); 1021 sym_clear_all_valid();
962 1022
963 if (mode != def_random)
964 return;
965 /* 1023 /*
966 * We have different type of choice blocks. 1024 * We have different type of choice blocks.
967 * If curr.tri equal to mod then we can select several 1025 * If curr.tri equal to mod then we can select several
@@ -976,35 +1034,9 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
976 continue; 1034 continue;
977 1035
978 sym_calc_value(csym); 1036 sym_calc_value(csym);
979 1037 if (mode == def_random)
980 if (csym->curr.tri != yes) 1038 randomize_choice_values(csym);
981 continue; 1039 else
982 1040 set_all_choice_values(csym);
983 prop = sym_get_choice_prop(csym);
984
985 /* count entries in choice block */
986 cnt = 0;
987 expr_list_for_each_sym(prop->expr, e, sym)
988 cnt++;
989
990 /*
991 * find a random value and set it to yes,
992 * set the rest to no so we have only one set
993 */
994 def = (rand() % cnt);
995
996 cnt = 0;
997 expr_list_for_each_sym(prop->expr, e, sym) {
998 if (def == cnt++) {
999 sym->def[S_DEF_USER].tri = yes;
1000 csym->def[S_DEF_USER].val = sym;
1001 }
1002 else {
1003 sym->def[S_DEF_USER].tri = no;
1004 }
1005 }
1006 csym->flags |= SYMBOL_DEF_USER;
1007 /* clear VALID to get value calculated */
1008 csym->flags &= ~(SYMBOL_VALID);
1009 } 1041 }
1010} 1042}