Re: kconfig: list unknown symbols in the old .config

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);



[Index of Archives]     [Linux&nblp;USB Development]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite Secrets]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux