From 801690caf1894d4f8b1277ca9f5dcf0bcf9b3f58 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Thu, 12 Aug 2010 09:11:51 +0200 Subject: [PATCH 1/5] kconfig: fix savedefconfig for tristate choices savedefconfig failed to save choice symbols equal to 'y' for tristate choices. This resulted in this value being lost. In particular is fixes an issue where make ARCH=avr32 atngw100_defconfig make ARCH=avr32 savedefconfig cp defconfig arch/avr32/configs/atngw100_defconfig make ARCH=avr32 atngw100_defconfig diff -u .config .config.old failed to produce an identical .config. Signed-off-by: Sam Ravnborg Signed-off-by: Michal Marek --- scripts/kconfig/confdata.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index f81f263b64f2..e5d66e4f1484 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -497,7 +497,7 @@ int conf_write_defconfig(const char *filename) /* * If symbol is a choice value and equals to the * default for a choice - skip. - * But only if value equal to "y". + * But only if value is bool and equal to "y" . */ if (sym_is_choice_value(sym)) { struct symbol *cs; @@ -506,9 +506,8 @@ int conf_write_defconfig(const char *filename) cs = prop_get_symbol(sym_get_choice_prop(sym)); ds = sym_choice_default(cs); if (sym == ds) { - if ((sym->type == S_BOOLEAN || - sym->type == S_TRISTATE) && - sym_get_tristate_value(sym) == yes) + if ((sym->type == S_BOOLEAN) && + sym_get_tristate_value(sym) == yes) goto next_menu; } } From a64b44ead002ba15fdf841106a6fd344b8dd46d8 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Thu, 12 Aug 2010 09:11:52 +0200 Subject: [PATCH 2/5] kconfig: fix tristate choice with minimal config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reported-by: Arve Hjønnevåg Tested-by: Arve Hjønnevåg Signed-off-by: Michal Marek --- scripts/kconfig/confdata.c | 102 ++++++++++++++++++++++++------------- 1 file 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)) conf_changed_callback = fn; } +static void randomize_choice_values(struct symbol *csym) +{ + struct property *prop; + struct symbol *sym; + struct expr *e; + int cnt, def; + + /* + * 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 property *prop; + struct symbol *sym; + struct expr *e; + + 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; - struct property *prop; - struct expr *e; - int i, cnt, def; + int i, cnt; for_all_symbols(i, sym) { if (sym_has_value(sym)) @@ -960,8 +1020,6 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) sym_clear_all_valid(); - if (mode != def_random) - return; /* * We have different type of choice blocks. * 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) continue; sym_calc_value(csym); - - if (csym->curr.tri != yes) - continue; - - 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); + if (mode == def_random) + randomize_choice_values(csym); + else + set_all_choice_values(csym); } } From 866af407dad3f2202e5d5d717ebd6156ccc33cdd Mon Sep 17 00:00:00 2001 From: Andrej Gelenberg Date: Mon, 2 Aug 2010 11:59:31 +0200 Subject: [PATCH 3/5] nconfig: Fix segfault when menu is empty nconf crush with segfault if press right arrow in empty menu. Signed-off-by: Andrej Gelenberg Signed-off-by: Michal Marek --- scripts/kconfig/nconf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 762caf80ce37..2ba71bcd38e6 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -676,6 +676,8 @@ static void *item_data(void) struct mitem *mcur; cur = current_item(curses_menu); + if (!cur) + return NULL; mcur = (struct mitem *) item_userptr(cur); return mcur->usrptr; From bf5e327a300a9ac959a89440e7c67dc89f3bd804 Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Wed, 4 Aug 2010 16:01:02 -0600 Subject: [PATCH 4/5] kconfig: Fix warning: ignoring return value of 'fwrite' This fix facilitates fwrite() in both confdata.c and expr.c, either it succeeds in writing, or an error occurs, or the end of file is reached. Signed-off-by: Jean Sacren Signed-off-by: Michal Marek --- scripts/kconfig/confdata.c | 2 +- scripts/kconfig/expr.c | 2 +- scripts/kconfig/lkc.h | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index ac13f0ff8e81..c39327e60ea4 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -412,7 +412,7 @@ static void conf_write_string(bool headerfile, const char *name, while (1) { l = strcspn(str, "\"\\"); if (l) { - fwrite(str, l, 1, out); + xfwrite(str, l, 1, out); str += l; } if (!*str) diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c index 8f18e37892cb..330e7c0048a8 100644 --- a/scripts/kconfig/expr.c +++ b/scripts/kconfig/expr.c @@ -1087,7 +1087,7 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char * static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) { - fwrite(str, strlen(str), 1, data); + xfwrite(str, strlen(str), 1, data); } void expr_fprint(struct expr *e, FILE *out) diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 76db065ed72c..2ac33f5d273c 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -80,6 +80,13 @@ void sym_set_change_count(int count); void sym_add_change_count(int count); void conf_set_all_new_symbols(enum conf_def_mode mode); +/* confdata.c and expr.c */ +static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) +{ + if (fwrite(str, len, count, out) < count) + fprintf(stderr, "\nError in writing or end of file.\n"); +} + /* kconfig_load.c */ void kconfig_load(void); From 4418a2b904805814bbd14b555d6add6a175f49f3 Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Wed, 4 Aug 2010 16:03:16 -0600 Subject: [PATCH 5/5] kconfig: Fix warning: ignoring return value of 'fgets' This fix facilitates fgets() either it returns on success or on error or when end of file occurs. Signed-off-by: Jean Sacren Signed-off-by: Michal Marek --- scripts/kconfig/conf.c | 15 +++++++++++++-- scripts/kconfig/lkc.h | 3 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 010600ef58c0..4f0ed5b3a75e 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -108,7 +108,7 @@ static int conf_askvalue(struct symbol *sym, const char *def) check_stdin(); case oldaskconfig: fflush(stdout); - fgets(line, 128, stdin); + xfgets(line, 128, stdin); return 1; default: break; @@ -306,7 +306,7 @@ static int conf_choice(struct menu *menu) check_stdin(); case oldaskconfig: fflush(stdout); - fgets(line, 128, stdin); + xfgets(line, 128, stdin); strip(line); if (line[0] == '?') { print_help(menu); @@ -644,3 +644,14 @@ int main(int ac, char **av) } return 0; } +/* + * Helper function to facilitate fgets() by Jean Sacren. + */ +void xfgets(str, size, in) + char *str; + int size; + FILE *in; +{ + if (fgets(str, size, in) == NULL) + fprintf(stderr, "\nError in reading or end of file.\n"); +} diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 2ac33f5d273c..bdf71bd31412 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -72,6 +72,9 @@ void zconf_nextfile(const char *name); int zconf_lineno(void); char *zconf_curname(void); +/* conf.c */ +void xfgets(char *str, int size, FILE *in); + /* confdata.c */ const char *conf_get_configname(void); const char *conf_get_autoconfig_name(void);