Commit a64b44ea authored by Sam Ravnborg's avatar Sam Ravnborg Committed by Michal Marek

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: default avatarSam Ravnborg <sam@ravnborg.org>
Reported-by: default avatarArve Hjønnevåg <arve@android.com>
Tested-by: default avatarArve Hjønnevåg <arve@android.com>
Signed-off-by: default avatarMichal Marek <mmarek@suse.cz>
parent 801690ca
...@@ -918,13 +918,73 @@ void conf_set_changed_callback(void (*fn)(void)) ...@@ -918,13 +918,73 @@ void conf_set_changed_callback(void (*fn)(void))
conf_changed_callback = fn; conf_changed_callback = fn;
} }
static void randomize_choice_values(struct symbol *csym)
{
struct property *prop;
struct symbol *sym;
struct expr *e;
int cnt, def;
void conf_set_all_new_symbols(enum conf_def_mode mode) /*
* If choice is mod then we may have more items slected
* and if no then no-one.
* In both cases stop.
*/
if (csym->curr.tri != yes)
return;
prop = sym_get_choice_prop(csym);
/* count entries in choice block */
cnt = 0;
expr_list_for_each_sym(prop->expr, e, sym)
cnt++;
/*
* find a random value and set it to yes,
* set the rest to no so we have only one set
*/
def = (rand() % cnt);
cnt = 0;
expr_list_for_each_sym(prop->expr, e, sym) {
if (def == cnt++) {
sym->def[S_DEF_USER].tri = yes;
csym->def[S_DEF_USER].val = sym;
}
else {
sym->def[S_DEF_USER].tri = no;
}
}
csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */
csym->flags &= ~(SYMBOL_VALID);
}
static void set_all_choice_values(struct symbol *csym)
{ {
struct symbol *sym, *csym;
struct property *prop; struct property *prop;
struct symbol *sym;
struct expr *e; struct expr *e;
int i, cnt, def;
prop = sym_get_choice_prop(csym);
/*
* Set all non-assinged choice values to no
*/
expr_list_for_each_sym(prop->expr, e, sym) {
if (!sym_has_value(sym))
sym->def[S_DEF_USER].tri = no;
}
csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */
csym->flags &= ~(SYMBOL_VALID);
}
void conf_set_all_new_symbols(enum conf_def_mode mode)
{
struct symbol *sym, *csym;
int i, cnt;
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
if (sym_has_value(sym)) if (sym_has_value(sym))
...@@ -960,8 +1020,6 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) ...@@ -960,8 +1020,6 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
sym_clear_all_valid(); sym_clear_all_valid();
if (mode != def_random)
return;
/* /*
* We have different type of choice blocks. * We have different type of choice blocks.
* If curr.tri equal to mod then we can select several * 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,35 +1034,9 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
continue; continue;
sym_calc_value(csym); sym_calc_value(csym);
if (mode == def_random)
if (csym->curr.tri != yes) randomize_choice_values(csym);
continue; else
set_all_choice_values(csym);
prop = sym_get_choice_prop(csym);
/* count entries in choice block */
cnt = 0;
expr_list_for_each_sym(prop->expr, e, sym)
cnt++;
/*
* find a random value and set it to yes,
* set the rest to no so we have only one set
*/
def = (rand() % cnt);
cnt = 0;
expr_list_for_each_sym(prop->expr, e, sym) {
if (def == cnt++) {
sym->def[S_DEF_USER].tri = yes;
csym->def[S_DEF_USER].val = sym;
}
else {
sym->def[S_DEF_USER].tri = no;
}
}
csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */
csym->flags &= ~(SYMBOL_VALID);
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment