On (23/08/16 21:42), Sergey Senozhatsky wrote: > Hi, > > We recently were hit (unnecessarily hard) when after kernel uprev we > figured that something wasn't working. The root cause was a rename of > the CONFIG_FOO option between kernel releases, which make oldconfig > doesn't warn/notify about. > > Would it be possible to add either a new --listunknown mode to conf or > to somehow make it conf_warning("unknown symbol: %s\n", line) when it > reads a line from oldconf that it cannot sym_find()? > > That would save a ton of time. So I have this simple (quick-n-dirty) patch, that seem to be doing the trick. Just to show the idea. Running `make listunknown` produces the following (on a hand-crafted .config): .config:6:warning: unknown symbol: CONFIG_DISABLE_BUGS .config:7:warning: unknown symbol: CONFIG_COMPILE_GOOD_CODE_ONLY make[2]: *** [scripts/kconfig/Makefile:77: listunknown] Error 1 ... --- diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 33d19e419908..37b777a0848c 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -36,6 +36,7 @@ enum input_mode { yes2modconfig, mod2yesconfig, mod2noconfig, + listunknown, }; static enum input_mode input_mode = oldaskconfig; static int input_mode_opt; @@ -683,6 +684,7 @@ static const struct option long_opts[] = { {"yes2modconfig", no_argument, &input_mode_opt, yes2modconfig}, {"mod2yesconfig", no_argument, &input_mode_opt, mod2yesconfig}, {"mod2noconfig", no_argument, &input_mode_opt, mod2noconfig}, + {"listunknown", no_argument, &input_mode_opt, listunknown}, {NULL, 0, NULL, 0} }; @@ -712,6 +714,7 @@ static void conf_usage(const char *progname) printf(" --yes2modconfig Change answers from yes to mod if possible\n"); printf(" --mod2yesconfig Change answers from mod to yes if possible\n"); printf(" --mod2noconfig Change answers from mod to no if possible\n"); + printf(" --listunknown List symbols that are not recognized anymore\n"); printf(" (If none of the above is given, --oldaskconfig is the default)\n"); } @@ -823,6 +826,12 @@ int main(int ac, char **av) exit(1); } break; + case listunknown: + if (conf_read_listunknown()) + exit(1); + else + exit(0); + break; default: break; } diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 992575f1e976..d70cd3b034e1 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -341,64 +341,113 @@ static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) return -1; } -int conf_read_simple(const char *name, int def) +static FILE *open_conf_file(const char *name) { - FILE *in = NULL; - char *line = NULL; - size_t line_asize = 0; - char *p, *p2; - struct symbol *sym; - int i, def_flags; + char *env, *p; + FILE *in; - if (name) { - in = zconf_fopen(name); - } else { - char *env; + if (name) + return zconf_fopen(name); - name = conf_get_configname(); - in = zconf_fopen(name); - if (in) - goto load; - conf_set_changed(true); + name = conf_get_configname(); + in = zconf_fopen(name); + if (in) + return in; - env = getenv("KCONFIG_DEFCONFIG_LIST"); - if (!env) - return 1; + conf_set_changed(true); - while (1) { - bool is_last; + env = getenv("KCONFIG_DEFCONFIG_LIST"); + if (!env) + return NULL; - while (isspace(*env)) - env++; + while (1) { + bool is_last; - if (!*env) - break; + while (isspace(*env)) + env++; - p = env; - while (*p && !isspace(*p)) - p++; + if (!*env) + break; - is_last = (*p == '\0'); + p = env; + while (*p && !isspace(*p)) + p++; - *p = '\0'; + is_last = (*p == '\0'); - in = zconf_fopen(env); - if (in) { - conf_message("using defaults found in %s", - env); - goto load; - } + *p = '\0'; - if (is_last) - break; + in = zconf_fopen(env); + if (in) { + conf_message("using defaults found in %s", + env); + return in; + } + + if (is_last) + break; + env = p + 1; + } + + return NULL; +} + +int conf_read_listunknown(void) +{ + FILE *in = NULL; + char *line = NULL; + size_t line_asize = 0; + char *p, *p2; + struct symbol *sym; - env = p + 1; + conf_filename = conf_get_configname(); + in = open_conf_file(conf_filename); + if (!in) + return 1; + + conf_warnings = 0; + while (compat_getline(&line, &line_asize, in) != -1) { + conf_lineno++; + sym = NULL; + if (line[0] == '#') + continue; + + if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { + p = strchr(line + strlen(CONFIG_), '='); + if (!p) + continue; + *p++ = 0; + p2 = strchr(p, '\n'); + if (p2) { + *p2-- = 0; + if (*p2 == '\r') + *p2 = 0; + } + + sym = sym_find(line + strlen(CONFIG_)); + if (!sym) + conf_warning("unknown symbol: %s", line); } } + + free(line); + fclose(in); + return conf_warnings; +} + +int conf_read_simple(const char *name, int def) +{ + FILE *in = NULL; + char *line = NULL; + size_t line_asize = 0; + char *p, *p2; + struct symbol *sym; + int i, def_flags; + + in = open_conf_file(name); if (!in) return 1; -load: conf_filename = name; conf_lineno = 0; conf_warnings = 0; diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index edd1e617b25c..d76faaec120a 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -5,6 +5,7 @@ void conf_parse(const char *name); int conf_read(const char *name); int conf_read_simple(const char *name, int); +int conf_read_listunknown(void); int conf_write_defconfig(const char *name); int conf_write(const char *name); int conf_write_autoconf(int overwrite);