lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1321970626-12615-2-git-send-email-konrad@gaisler.com>
Date:	Tue, 22 Nov 2011 15:03:44 +0100
From:	Konrad Eisele <konrad@...sler.com>
To:	linux-kernel@...r.kernel.org
Cc:	lacombar@...il.com, mmarek@...e.cz,
	yann.morin.1998@...iens.enib.fr, linux-config@...r.kernel.org,
	konrad@...sler.com
Subject: [PATCH 1/3] kconfig: Move global elements into struct, create root context

Move modules_sym, symbol_hash, sym_defconfig_list, sym_env_list into a
structure instead of beeing global. Create a root context called &rootlevel
to be used as default by the config frontends.

Signed-off-by: Konrad Eisele <konrad@...sler.com>
---
 scripts/kconfig/conf.c      |   30 +++++-----
 scripts/kconfig/confdata.c  |  103 ++++++++++++++++++++------------
 scripts/kconfig/expr.h      |   23 ++++++-
 scripts/kconfig/gconf.c     |    8 +-
 scripts/kconfig/lkc.h       |   12 ++--
 scripts/kconfig/lkc_proto.h |   20 ++++---
 scripts/kconfig/mconf.c     |    8 +-
 scripts/kconfig/menu.c      |   10 ++--
 scripts/kconfig/nconf.c     |    8 +-
 scripts/kconfig/qconf.cc    |    6 +-
 scripts/kconfig/symbol.c    |  140 ++++++++++++++++++++++++++-----------------
 scripts/kconfig/util.c      |    8 +-
 scripts/kconfig/zconf.l     |    4 +-
 scripts/kconfig/zconf.y     |   49 ++++++++-------
 14 files changed, 255 insertions(+), 174 deletions(-)

diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index f208f90..4307427 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -553,7 +553,7 @@ int main(int ac, char **av)
 	case defconfig:
 		if (!defconfig_file)
 			defconfig_file = conf_get_default_confname();
-		if (conf_read(defconfig_file)) {
+		if (conf_read(defconfig_file, &rootlevel)) {
 			printf(_("***\n"
 				"*** Can't find default configuration \"%s\"!\n"
 				"***\n"), defconfig_file);
@@ -566,7 +566,7 @@ int main(int ac, char **av)
 	case oldconfig:
 	case listnewconfig:
 	case oldnoconfig:
-		conf_read(NULL);
+		conf_read(NULL, &rootlevel);
 		break;
 	case allnoconfig:
 	case allyesconfig:
@@ -575,7 +575,7 @@ int main(int ac, char **av)
 	case randconfig:
 		name = getenv("KCONFIG_ALLCONFIG");
 		if (name && !stat(name, &tmpstat)) {
-			conf_read_simple(name, S_DEF_USER);
+			conf_read_simple(name, S_DEF_USER, &rootlevel);
 			break;
 		}
 		switch (input_mode) {
@@ -587,9 +587,9 @@ int main(int ac, char **av)
 		default: break;
 		}
 		if (!stat(name, &tmpstat))
-			conf_read_simple(name, S_DEF_USER);
+			conf_read_simple(name, S_DEF_USER, &rootlevel);
 		else if (!stat("all.config", &tmpstat))
-			conf_read_simple("all.config", S_DEF_USER);
+			conf_read_simple("all.config", S_DEF_USER, &rootlevel);
 		break;
 	default:
 		break;
@@ -609,22 +609,22 @@ int main(int ac, char **av)
 
 	switch (input_mode) {
 	case allnoconfig:
-		conf_set_all_new_symbols(def_no);
+		conf_set_all_new_symbols(def_no, &rootlevel);
 		break;
 	case allyesconfig:
-		conf_set_all_new_symbols(def_yes);
+		conf_set_all_new_symbols(def_yes, &rootlevel);
 		break;
 	case allmodconfig:
-		conf_set_all_new_symbols(def_mod);
+		conf_set_all_new_symbols(def_mod, &rootlevel);
 		break;
 	case alldefconfig:
-		conf_set_all_new_symbols(def_default);
+		conf_set_all_new_symbols(def_default, &rootlevel);
 		break;
 	case randconfig:
-		conf_set_all_new_symbols(def_random);
+		conf_set_all_new_symbols(def_random, &rootlevel);
 		break;
 	case defconfig:
-		conf_set_all_new_symbols(def_default);
+		conf_set_all_new_symbols(def_default, &rootlevel);
 		break;
 	case savedefconfig:
 		break;
@@ -651,22 +651,22 @@ int main(int ac, char **av)
 		/* silentoldconfig is used during the build so we shall update autoconf.
 		 * All other commands are only used to generate a config.
 		 */
-		if (conf_get_changed() && conf_write(NULL)) {
+		if (conf_get_changed() && conf_write(NULL, &rootlevel)) {
 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
 			exit(1);
 		}
-		if (conf_write_autoconf()) {
+		if (conf_write_autoconf(&rootlevel)) {
 			fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
 			return 1;
 		}
 	} else if (input_mode == savedefconfig) {
-		if (conf_write_defconfig(defconfig_file)) {
+		if (conf_write_defconfig(defconfig_file, &rootlevel)) {
 			fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
 			        defconfig_file);
 			return 1;
 		}
 	} else if (input_mode != listnewconfig) {
-		if (conf_write(NULL)) {
+		if (conf_write(NULL, &rootlevel)) {
 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
 			exit(1);
 		}
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 5a58965..25c29c8 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -75,7 +75,7 @@ const char *conf_get_autoconfig_name(void)
 	return name ? name : "include/config/auto.conf";
 }
 
-static char *conf_expand_value(const char *in)
+static char *conf_expand_value(const char *in, struct conf_level *l)
 {
 	struct symbol *sym;
 	const char *src;
@@ -91,7 +91,7 @@ static char *conf_expand_value(const char *in)
 		while (isalnum(*src) || *src == '_')
 			*dst++ = *src++;
 		*dst = 0;
-		sym = sym_lookup(name, 0);
+		sym = sym_lookup(name, 0, l);
 		sym_calc_value(sym);
 		strcat(res_value, sym_get_string_value(sym));
 		in = src;
@@ -107,7 +107,7 @@ char *conf_get_default_confname(void)
 	static char fullname[PATH_MAX+1];
 	char *env, *name;
 
-	name = conf_expand_value(conf_defname);
+	name = conf_expand_value(conf_defname, &rootlevel);
 	env = getenv(SRCTREE);
 	if (env) {
 		sprintf(fullname, "%s/%s", env, name);
@@ -182,7 +182,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
 	return 0;
 }
 
-int conf_read_simple(const char *name, int def)
+int conf_read_simple(const char *name, int def, struct conf_level *l)
 {
 	FILE *in = NULL;
 	char line[1024];
@@ -200,17 +200,17 @@ int conf_read_simple(const char *name, int def)
 		if (in)
 			goto load;
 		sym_add_change_count(1);
-		if (!sym_defconfig_list) {
-			if (modules_sym)
-				sym_calc_value(modules_sym);
+		if (!l->sym_defconfig_list) {
+			if (l->modules_sym)
+				sym_calc_value(l->modules_sym);
 			return 1;
 		}
 
-		for_all_defaults(sym_defconfig_list, prop) {
+		for_all_defaults(l->sym_defconfig_list, prop) {
 			if (expr_calc_value(prop->visible.expr) == no ||
 			    prop->expr->type != E_SYMBOL)
 				continue;
-			name = conf_expand_value(prop->expr->left.sym->name);
+			name = conf_expand_value(prop->expr->left.sym->name, l);
 			in = zconf_fopen(name);
 			if (in) {
 				conf_message(_("using defaults found in %s"),
@@ -229,7 +229,7 @@ load:
 	conf_unsaved = 0;
 
 	def_flags = SYMBOL_DEF << def;
-	for_all_symbols(i, sym) {
+	for_all_symbols_level(i, sym, l) {
 		sym->flags |= SYMBOL_CHANGED;
 		sym->flags &= ~(def_flags|SYMBOL_VALID);
 		if (sym_is_choice(sym))
@@ -251,7 +251,7 @@ load:
 		conf_lineno++;
 		sym = NULL;
 		if (line[0] == '#') {
-			if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
+			if (memcmp(line + 2, l->conf_prefix, strlen(l->conf_prefix)))
 				continue;
 			p = strchr(line + 2 + strlen(CONFIG_), ' ');
 			if (!p)
@@ -260,13 +260,13 @@ load:
 			if (strncmp(p, "is not set", 10))
 				continue;
 			if (def == S_DEF_USER) {
-				sym = sym_find(line + 2 + strlen(CONFIG_));
+				sym = sym_find(line + 2 + strlen(l->conf_prefix), l);
 				if (!sym) {
 					sym_add_change_count(1);
 					goto setsym;
 				}
 			} else {
-				sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
+				sym = sym_lookup(line + 2 + strlen(l->conf_prefix), 0, l);
 				if (sym->type == S_UNKNOWN)
 					sym->type = S_BOOLEAN;
 			}
@@ -282,7 +282,7 @@ load:
 			default:
 				;
 			}
-		} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
+		} else if (memcmp(line, l->conf_prefix, strlen(l->conf_prefix)) == 0) {
 			p = strchr(line + strlen(CONFIG_), '=');
 			if (!p)
 				continue;
@@ -294,13 +294,13 @@ load:
 					*p2 = 0;
 			}
 			if (def == S_DEF_USER) {
-				sym = sym_find(line + strlen(CONFIG_));
+				sym = sym_find(line + strlen(l->conf_prefix), l);
 				if (!sym) {
 					sym_add_change_count(1);
 					goto setsym;
 				}
 			} else {
-				sym = sym_lookup(line + strlen(CONFIG_), 0);
+				sym = sym_lookup(line + strlen(l->conf_prefix), 0, l);
 				if (sym->type == S_UNKNOWN)
 					sym->type = S_OTHER;
 			}
@@ -337,12 +337,12 @@ setsym:
 	}
 	fclose(in);
 
-	if (modules_sym)
-		sym_calc_value(modules_sym);
+	if (l->modules_sym)
+		sym_calc_value(l->modules_sym);
 	return 0;
 }
 
-int conf_read(const char *name)
+int conf_read(const char *name, struct conf_level *l)
 {
 	struct symbol *sym, *choice_sym;
 	struct property *prop;
@@ -351,10 +351,10 @@ int conf_read(const char *name)
 
 	sym_set_change_count(0);
 
-	if (conf_read_simple(name, S_DEF_USER))
+	if (conf_read_simple(name, S_DEF_USER, l))
 		return 1;
 
-	for_all_symbols(i, sym) {
+	for_all_symbols_level(i, sym, l) {
 		sym_calc_value(sym);
 		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
 			goto sym_ok;
@@ -392,7 +392,7 @@ int conf_read(const char *name)
 		sym->flags &= flags | ~SYMBOL_DEF_USER;
 	}
 
-	for_all_symbols(i, sym) {
+	for_all_symbols_level(i, sym, l) {
 		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
 			/* Reset values of generates values, so they'll appear
 			 * as new, if they should become visible, but that
@@ -422,6 +422,19 @@ int conf_read(const char *name)
 	return 0;
 }
 
+int conf_read_all(const char *name) {
+	int r = 0;
+	struct conf_level *l;
+	if ((l = conf_levels)
+	    && !(r = conf_read(name, l))) {
+		while ((l = l->n)) {
+			if ((r = conf_read(l->conf, l)))
+				break;
+		}
+	}
+	return r;
+}
+
 /*
  * Kconfig configuration printer
  *
@@ -640,7 +653,7 @@ conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
  * Write out a minimal config.
  * All values that has default values are skipped as this is redundant.
  */
-int conf_write_defconfig(const char *filename)
+int conf_write_defconfig(const char *filename, struct conf_level *l)
 {
 	struct symbol *sym;
 	struct menu *menu;
@@ -650,7 +663,7 @@ int conf_write_defconfig(const char *filename)
 	if (!out)
 		return 1;
 
-	sym_clear_all_valid();
+	sym_clear_all_valid(l);
 
 	/* Traverse all menus to find all relevant symbols */
 	menu = rootmenu.list;
@@ -713,7 +726,7 @@ next_menu:
 	return 0;
 }
 
-int conf_write(const char *name)
+int conf_write(const char *name, struct conf_level *l)
 {
 	FILE *out;
 	struct symbol *sym;
@@ -760,7 +773,7 @@ int conf_write(const char *name)
 	conf_write_heading(out, &kconfig_printer_cb, NULL);
 
 	if (!conf_get_changed())
-		sym_clear_all_valid();
+		sym_clear_all_valid(l);
 
 	menu = rootmenu.list;
 	while (menu) {
@@ -813,7 +826,21 @@ next:
 	return 0;
 }
 
-static int conf_split_config(void)
+int conf_write_all(const char *name) {
+	int r = 0;
+	struct conf_level *l;
+	if ((l = conf_levels)
+	    && !(r = conf_write(name, l))) {
+		while ((l = l->n)) {
+			if ((r = conf_write(l->conf, l)))
+				break;
+		}
+	}
+	return r;
+}
+
+
+static int conf_split_config(struct conf_level *l)
 {
 	const char *name;
 	char path[PATH_MAX+1];
@@ -823,13 +850,13 @@ static int conf_split_config(void)
 	int res, i, fd;
 
 	name = conf_get_autoconfig_name();
-	conf_read_simple(name, S_DEF_AUTO);
+	conf_read_simple(name, S_DEF_AUTO, l);
 
 	if (chdir("include/config"))
 		return 1;
 
 	res = 0;
-	for_all_symbols(i, sym) {
+	for_all_symbols_level(i, sym, l) {
 		sym_calc_value(sym);
 		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
 			continue;
@@ -925,18 +952,18 @@ out:
 	return res;
 }
 
-int conf_write_autoconf(void)
+int conf_write_autoconf(struct conf_level *l)
 {
 	struct symbol *sym;
 	const char *name;
 	FILE *out, *tristate, *out_h;
 	int i;
 
-	sym_clear_all_valid();
+	sym_clear_all_valid(l);
 
-	file_write_dep("include/config/auto.conf.cmd");
+	file_write_dep("include/config/auto.conf.cmd", l);
 
-	if (conf_split_config())
+	if (conf_split_config(l))
 		return 1;
 
 	out = fopen(".tmpconfig", "w");
@@ -962,7 +989,7 @@ int conf_write_autoconf(void)
 
 	conf_write_heading(out_h, &header_printer_cb, NULL);
 
-	for_all_symbols(i, sym) {
+	for_all_symbols_level(i, sym, l) {
 		if (!sym->name)
 			continue;
 
@@ -1094,12 +1121,12 @@ static void set_all_choice_values(struct symbol *csym)
 	csym->flags &= ~(SYMBOL_VALID);
 }
 
-void conf_set_all_new_symbols(enum conf_def_mode mode)
+void conf_set_all_new_symbols(enum conf_def_mode mode, struct conf_level *l)
 {
 	struct symbol *sym, *csym;
 	int i, cnt;
 
-	for_all_symbols(i, sym) {
+	for_all_symbols_level(i, sym, l) {
 		if (sym_has_value(sym))
 			continue;
 		switch (sym_get_type(sym)) {
@@ -1131,7 +1158,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
 
 	}
 
-	sym_clear_all_valid();
+	sym_clear_all_valid(l);
 
 	/*
 	 * We have different type of choice blocks.
@@ -1142,7 +1169,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
 	 * selected in a choice block and we set it to yes,
 	 * and the rest to no.
 	 */
-	for_all_symbols(i, csym) {
+	for_all_symbols_level(i, csym, l) {
 		if (sym_has_value(csym) || !sym_is_choice(csym))
 			continue;
 
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 80fce57..12ac5bc 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -15,6 +15,10 @@ extern "C" {
 #include <stdbool.h>
 #endif
 
+struct conf_level;
+extern struct conf_level *conf_levels;
+extern struct conf_level *current_conf_level;
+
 struct file {
 	struct file *next;
 	struct file *parent;
@@ -81,9 +85,10 @@ struct symbol {
 	struct property *prop;
 	struct expr_value dir_dep;
 	struct expr_value rev_dep;
+	struct conf_level *level;
 };
 
-#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
+#define for_all_symbols_level(i, sym, l) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = l->symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
 
 #define SYMBOL_CONST      0x0001  /* symbol is const */
 #define SYMBOL_CHECK      0x0008  /* used during dependency checking */
@@ -172,13 +177,25 @@ struct menu {
 #define MENU_CHANGED		0x0001
 #define MENU_ROOT		0x0002
 
+struct conf_level {
+        struct conf_level *n;
+	struct conf_level *parent;
+	char *conf;
+	char *conf_prefix;
+	char *cwd;
+	struct symbol *symbol_hash[SYMBOL_HASHSIZE];
+	struct symbol *modules_sym;
+	tristate modules_val;
+	struct symbol *sym_defconfig_list;
+	struct expr *sym_env_list;
+};
+extern struct conf_level rootlevel;
+
 extern struct file *file_list;
 extern struct file *current_file;
 struct file *lookup_file(const char *name);
 
 extern struct symbol symbol_yes, symbol_no, symbol_mod;
-extern struct symbol *modules_sym;
-extern struct symbol *sym_defconfig_list;
 extern int cdebug;
 struct expr *expr_alloc_symbol(struct symbol *sym);
 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 9f44380..39dd257 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -519,7 +519,7 @@ load_filename(GtkFileSelection * file_selector, gpointer user_data)
 	fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
 					     (user_data));
 
-	if (conf_read(fn))
+	if (conf_read(fn, &rootlevel))
 		text_insert_msg(_("Error"), _("Unable to load configuration !"));
 	else
 		display_tree(&rootmenu);
@@ -547,7 +547,7 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
 
 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
-	if (conf_write(NULL))
+	if (conf_write(NULL, &rootlevel))
 		text_insert_msg(_("Error"), _("Unable to save configuration !"));
 }
 
@@ -560,7 +560,7 @@ store_filename(GtkFileSelection * file_selector, gpointer user_data)
 	fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
 					     (user_data));
 
-	if (conf_write(fn))
+	if (conf_write(fn, &rootlevel))
 		text_insert_msg(_("Error"), _("Unable to save configuration !"));
 
 	gtk_widget_destroy(GTK_WIDGET(user_data));
@@ -1512,7 +1512,7 @@ int main(int ac, char *av[])
 
 	conf_parse(name);
 	fixup_rootmenu(&rootmenu);
-	conf_read(NULL);
+	conf_read(NULL, &rootlevel);
 
 	/* Load the interface and connect signals */
 	init_main_window(glade_file);
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index b633bdb..689efd6 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -80,7 +80,7 @@ const char *conf_get_autoconfig_name(void);
 char *conf_get_default_confname(void);
 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);
+void conf_set_all_new_symbols(enum conf_def_mode mode, struct conf_level *l);
 
 struct conf_printer {
 	void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
@@ -112,8 +112,8 @@ void menu_finalize(struct menu *parent);
 void menu_set_type(int type);
 
 /* util.c */
-struct file *file_lookup(const char *name);
-int file_write_dep(const char *name);
+struct file *file_lookup(const char *name, struct conf_level *l);
+int file_write_dep(const char *name, struct conf_level *l);
 
 struct gstr {
 	size_t len;
@@ -134,9 +134,9 @@ const char *str_get(struct gstr *gs);
 /* symbol.c */
 extern struct expr *sym_env_list;
 
-void sym_init(void);
-void sym_clear_all_valid(void);
-void sym_set_all_changed(void);
+void sym_init(struct conf_level *l);
+void sym_clear_all_valid(struct conf_level *l);
+void sym_set_all_changed(struct conf_level *l);
 void sym_set_changed(struct symbol *sym);
 struct symbol *sym_choice_default(struct symbol *sym);
 const char *sym_get_string_default(struct symbol *sym);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 47fe9c3..749d78a 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -2,11 +2,13 @@
 
 /* confdata.c */
 P(conf_parse,void,(const char *name));
-P(conf_read,int,(const char *name));
-P(conf_read_simple,int,(const char *name, int));
-P(conf_write_defconfig,int,(const char *name));
-P(conf_write,int,(const char *name));
-P(conf_write_autoconf,int,(void));
+P(conf_read_all,int,(const char *name));
+P(conf_read,int,(const char *name,struct conf_level *l));
+P(conf_read_simple,int,(const char *name, int,struct conf_level *l));
+P(conf_write_defconfig,int,(const char *name, struct conf_level *l));
+P(conf_write,int,(const char *name, struct conf_level *l));
+P(conf_write_all,int,(const char *name));
+P(conf_write_autoconf,int,(struct conf_level *l));
 P(conf_get_changed,bool,(void));
 P(conf_set_changed_callback, void,(void (*fn)(void)));
 P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap)));
@@ -28,9 +30,9 @@ P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 /* symbol.c */
 P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
 
-P(sym_lookup,struct symbol *,(const char *name, int flags));
-P(sym_find,struct symbol *,(const char *name));
-P(sym_expand_string_value,const char *,(const char *in));
+P(sym_lookup,struct symbol *,(const char *name, int flags, struct conf_level *l));
+P(sym_find,struct symbol *,(const char *name, struct conf_level *l));
+P(sym_expand_string_value,const char *,(const char *in, struct conf_level *l));
 P(sym_escape_string_value, const char *,(const char *in));
 P(sym_re_search,struct symbol **,(const char *pattern));
 P(sym_type_name,const char *,(enum symbol_type type));
@@ -48,6 +50,8 @@ P(sym_get_default_prop,struct property *,(struct symbol *sym));
 P(sym_get_string_value,const char *,(struct symbol *sym));
 
 P(prop_get_type_name,const char *,(enum prop_type type));
+P(sym_level_open,void,(struct conf_level *l));
+P(sym_level_close,void,(struct conf_level *l));
 
 /* expr.c */
 P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 19e200d..e6abbde 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -752,7 +752,7 @@ static void conf_load(void)
 		case 0:
 			if (!dialog_input_result[0])
 				return;
-			if (!conf_read(dialog_input_result)) {
+			if (!conf_read(dialog_input_result, &rootlevel)) {
 				set_config_filename(dialog_input_result);
 				sym_set_change_count(1);
 				return;
@@ -779,7 +779,7 @@ static void conf_save(void)
 		case 0:
 			if (!dialog_input_result[0])
 				return;
-			if (!conf_write(dialog_input_result)) {
+			if (!conf_write(dialog_input_result, &rootlevel)) {
 				set_config_filename(dialog_input_result);
 				return;
 			}
@@ -811,7 +811,7 @@ static int handle_exit(void)
 
 	switch (res) {
 	case 0:
-		if (conf_write(filename)) {
+		if (conf_write(filename, &rootlevel)) {
 			fprintf(stderr, _("\n\n"
 					  "Error while writing of the configuration.\n"
 					  "Your configuration changes were NOT saved."
@@ -852,7 +852,7 @@ int main(int ac, char **av)
 	signal(SIGINT, sig_handler);
 
 	conf_parse(av[1]);
-	conf_read(NULL);
+	conf_read(NULL, &rootlevel);
 
 	mode = getenv("MENUCONFIG_MODE");
 	if (mode) {
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 8c2a97e..9977819 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -96,7 +96,7 @@ static struct expr *menu_check_dep(struct expr *e)
 	case E_SYMBOL:
 		/* change 'm' into 'm' && MODULES */
 		if (e->left.sym == &symbol_mod)
-			return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
+			return expr_alloc_and(e, expr_alloc_symbol(current_conf_level->modules_sym));
 		break;
 	default:
 		break;
@@ -188,13 +188,13 @@ void menu_add_option(int token, char *arg)
 
 	switch (token) {
 	case T_OPT_MODULES:
-		prop = prop_alloc(P_DEFAULT, modules_sym);
+		prop = prop_alloc(P_DEFAULT, current_conf_level->modules_sym);
 		prop->expr = expr_alloc_symbol(current_entry->sym);
 		break;
 	case T_OPT_DEFCONFIG_LIST:
-		if (!sym_defconfig_list)
-			sym_defconfig_list = current_entry->sym;
-		else if (sym_defconfig_list != current_entry->sym)
+		if (!current_conf_level->sym_defconfig_list)
+			current_conf_level->sym_defconfig_list = current_entry->sym;
+		else if (current_conf_level->sym_defconfig_list != current_entry->sym)
 			zconf_error("trying to redefine defconfig symbol");
 		break;
 	case T_OPT_ENV:
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 73070cb..d839bda 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -670,7 +670,7 @@ static int do_exit(void)
 	/* if we got here, the user really wants to exit */
 	switch (res) {
 	case 0:
-		res = conf_write(filename);
+		res = conf_write(filename, &rootlevel);
 		if (res)
 			btn_dialog(
 				main_window,
@@ -1402,7 +1402,7 @@ static void conf_load(void)
 		case 0:
 			if (!dialog_input_result[0])
 				return;
-			if (!conf_read(dialog_input_result)) {
+			if (!conf_read(dialog_input_result, &rootlevel)) {
 				set_config_filename(dialog_input_result);
 				sym_set_change_count(1);
 				return;
@@ -1433,7 +1433,7 @@ static void conf_save(void)
 		case 0:
 			if (!dialog_input_result[0])
 				return;
-			res = conf_write(dialog_input_result);
+			res = conf_write(dialog_input_result, &rootlevel);
 			if (!res) {
 				set_config_filename(dialog_input_result);
 				return;
@@ -1477,7 +1477,7 @@ int main(int ac, char **av)
 	textdomain(PACKAGE);
 
 	conf_parse(av[1]);
-	conf_read(NULL);
+	conf_read(NULL, &rootlevel);
 
 	mode = getenv("NCONFIG_MODE");
 	if (mode) {
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index df274fe..e8e26c0 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -1473,14 +1473,14 @@ void ConfigMainWindow::loadConfig(void)
 	QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);
 	if (s.isNull())
 		return;
-	if (conf_read(QFile::encodeName(s)))
+	if (conf_read(QFile::encodeName(s), &rootlevel))
 		QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
 	ConfigView::updateListAll();
 }
 
 bool ConfigMainWindow::saveConfig(void)
 {
-	if (conf_write(NULL)) {
+	if (conf_write(NULL, &rootlevel)) {
 		QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
 		return false;
 	}
@@ -1768,7 +1768,7 @@ int main(int ac, char** av)
 
 	conf_parse(name);
 	fixup_rootmenu(&rootmenu);
-	conf_read(NULL);
+	conf_read(NULL, &rootlevel);
 	//zconfdump(stdout);
 
 	configSettings = new ConfigSettings();
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 071f00c..6999c8d 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -29,32 +29,23 @@ struct symbol symbol_yes = {
 	.flags = SYMBOL_VALID,
 };
 
-struct symbol *sym_defconfig_list;
-struct symbol *modules_sym;
 tristate modules_val;
-
-struct expr *sym_env_list;
+struct conf_level rootlevel;
 
 static void sym_add_default(struct symbol *sym, const char *def)
 {
 	struct property *prop = prop_alloc(P_DEFAULT, sym);
 
-	prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
+	prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST, sym->level));
 }
 
-void sym_init(void)
+void sym_init(struct conf_level *l)
 {
 	struct symbol *sym;
 	struct utsname uts;
-	static bool inited = false;
-
-	if (inited)
-		return;
-	inited = true;
-
 	uname(&uts);
 
-	sym = sym_lookup("UNAME_RELEASE", 0);
+	sym = sym_lookup("UNAME_RELEASE", 0, l);
 	sym->type = S_STRING;
 	sym->flags |= SYMBOL_AUTO;
 	sym_add_default(sym, uts.release);
@@ -397,9 +388,9 @@ void sym_calc_value(struct symbol *sym)
 
 	if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
 		sym_set_changed(sym);
-		if (modules_sym == sym) {
-			sym_set_all_changed();
-			modules_val = modules_sym->curr.tri;
+		if (sym->level && sym->level->modules_sym == sym) {
+			sym_set_all_changed(sym->level);
+			modules_val = sym->level->modules_sym->curr.tri;
 		}
 	}
 
@@ -420,16 +411,20 @@ void sym_calc_value(struct symbol *sym)
 		sym->flags &= ~SYMBOL_WRITE;
 }
 
-void sym_clear_all_valid(void)
+void sym_clear_all_valid(struct conf_level *l)
 {
 	struct symbol *sym;
 	int i;
 
-	for_all_symbols(i, sym)
+	for_all_symbols_level(i, sym, l)
 		sym->flags &= ~SYMBOL_VALID;
 	sym_add_change_count(1);
-	if (modules_sym)
-		sym_calc_value(modules_sym);
+	l = conf_levels;
+	while (l) {
+		if (l->modules_sym)
+			sym_calc_value(l->modules_sym);
+		l = l->n;
+	}
 }
 
 void sym_set_changed(struct symbol *sym)
@@ -443,12 +438,12 @@ void sym_set_changed(struct symbol *sym)
 	}
 }
 
-void sym_set_all_changed(void)
+void sym_set_all_changed(struct conf_level *l)
 {
 	struct symbol *sym;
 	int i;
 
-	for_all_symbols(i, sym)
+	for_all_symbols_level(i, sym, l)
 		sym_set_changed(sym);
 }
 
@@ -502,7 +497,7 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val)
 
 	sym->def[S_DEF_USER].tri = val;
 	if (oldval != val)
-		sym_clear_all_valid();
+		sym_clear_all_valid(sym->level);
 
 	return true;
 }
@@ -659,7 +654,7 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
 
 	strcpy(val, newval);
 	free((void *)oldval);
-	sym_clear_all_valid();
+	sym_clear_all_valid(sym->level);
 
 	return true;
 }
@@ -679,7 +674,8 @@ const char *sym_get_string_default(struct symbol *sym)
 	tristate val;
 
 	sym_calc_visibility(sym);
-	sym_calc_value(modules_sym);
+	if (sym->level)
+		sym_calc_value(sym->level->modules_sym);
 	val = symbol_no.curr.tri;
 	str = symbol_empty.curr.val;
 
@@ -711,7 +707,7 @@ const char *sym_get_string_default(struct symbol *sym)
 
 	/* transpose mod to yes if modules are not enabled */
 	if (val == mod)
-		if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
+		if (!sym_is_choice_value(sym) && sym->level->modules_sym->curr.tri == no)
 			val = yes;
 
 	/* transpose mod to yes if type is bool */
@@ -750,8 +746,8 @@ const char *sym_get_string_value(struct symbol *sym)
 		case no:
 			return "n";
 		case mod:
-			sym_calc_value(modules_sym);
-			return (modules_sym->curr.tri == no) ? "n" : "m";
+			sym_calc_value(sym->level->modules_sym);
+			return (sym->level->modules_sym->curr.tri == no) ? "n" : "m";
 		case yes:
 			return "y";
 		}
@@ -776,7 +772,7 @@ static unsigned strhash(const char *s)
 	return hash;
 }
 
-struct symbol *sym_lookup(const char *name, int flags)
+struct symbol *sym_lookup(const char *name, int flags, struct conf_level *l)
 {
 	struct symbol *symbol;
 	char *new_name;
@@ -792,7 +788,7 @@ struct symbol *sym_lookup(const char *name, int flags)
 		}
 		hash = strhash(name) % SYMBOL_HASHSIZE;
 
-		for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+		for (symbol = l->symbol_hash[hash]; symbol; symbol = symbol->next) {
 			if (symbol->name &&
 			    !strcmp(symbol->name, name) &&
 			    (flags ? symbol->flags & flags
@@ -810,14 +806,15 @@ struct symbol *sym_lookup(const char *name, int flags)
 	symbol->name = new_name;
 	symbol->type = S_UNKNOWN;
 	symbol->flags |= flags;
+	symbol->level = l;
 
-	symbol->next = symbol_hash[hash];
-	symbol_hash[hash] = symbol;
+	symbol->next = l->symbol_hash[hash];
+	l->symbol_hash[hash] = symbol;
 
 	return symbol;
 }
 
-struct symbol *sym_find(const char *name)
+struct symbol *sym_find(const char *name, struct conf_level *l)
 {
 	struct symbol *symbol = NULL;
 	int hash = 0;
@@ -834,7 +831,7 @@ struct symbol *sym_find(const char *name)
 	}
 	hash = strhash(name) % SYMBOL_HASHSIZE;
 
-	for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+	for (symbol = l->symbol_hash[hash]; symbol; symbol = symbol->next) {
 		if (symbol->name &&
 		    !strcmp(symbol->name, name) &&
 		    !(symbol->flags & SYMBOL_CONST))
@@ -849,7 +846,7 @@ struct symbol *sym_find(const char *name)
  * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
  * the empty string.
  */
-const char *sym_expand_string_value(const char *in)
+const char *sym_expand_string_value(const char *in, struct conf_level *l)
 {
 	const char *src;
 	char *res;
@@ -873,7 +870,7 @@ const char *sym_expand_string_value(const char *in)
 			*p++ = *src++;
 		*p = '\0';
 
-		sym = sym_find(name);
+		sym = sym_find(name, l);
 		if (sym != NULL) {
 			sym_calc_value(sym);
 			symval = sym_get_string_value(sym);
@@ -939,6 +936,7 @@ const char *sym_escape_string_value(const char *in)
 struct symbol **sym_re_search(const char *pattern)
 {
 	struct symbol *sym, **sym_arr = NULL;
+	struct conf_level *l;
 	int i, cnt, size;
 	regex_t re;
 
@@ -948,24 +946,29 @@ struct symbol **sym_re_search(const char *pattern)
 		return NULL;
 	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
 		return NULL;
-
-	for_all_symbols(i, sym) {
-		if (sym->flags & SYMBOL_CONST || !sym->name)
-			continue;
-		if (regexec(&re, sym->name, 0, NULL, 0))
-			continue;
-		if (cnt + 1 >= size) {
-			void *tmp = sym_arr;
-			size += 16;
-			sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
-			if (!sym_arr) {
-				free(tmp);
-				return NULL;
+	
+	l = conf_levels;
+	while(l) {
+		for_all_symbols_level(i, sym, l) {
+			if (sym->flags & SYMBOL_CONST || !sym->name)
+				continue;
+			if (regexec(&re, sym->name, 0, NULL, 0))
+				continue;
+			if (cnt + 1 >= size) {
+				void *tmp = sym_arr;
+				size += 16;
+				sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
+				if (!sym_arr) {
+					free(tmp);
+					return NULL;
+				}
 			}
+			sym_calc_value(sym);
+			sym_arr[cnt++] = sym;
 		}
-		sym_calc_value(sym);
-		sym_arr[cnt++] = sym;
+		l = l->n;
 	}
+	
 	if (sym_arr)
 		sym_arr[cnt] = NULL;
 	regfree(&re);
@@ -1277,6 +1280,7 @@ static void prop_add_env(const char *env)
 {
 	struct symbol *sym, *sym2;
 	struct property *prop;
+	struct conf_level *l = current_entry->sym->level;
 	char *p;
 
 	sym = current_entry->sym;
@@ -1290,10 +1294,10 @@ static void prop_add_env(const char *env)
 	}
 
 	prop = prop_alloc(P_ENV, sym);
-	prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
+	prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST, l));
 
-	sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
-	sym_env_list->right.sym = sym;
+	l->sym_env_list = expr_alloc_one(E_LIST, l->sym_env_list);
+	l->sym_env_list->right.sym = sym;
 
 	p = getenv(env);
 	if (p)
@@ -1301,3 +1305,31 @@ static void prop_add_env(const char *env)
 	else
 		menu_warn(current_entry, "environment variable %s undefined", env);
 }
+
+void sym_level_open(struct conf_level *l)
+{
+	struct conf_level **lp;
+	memset(l, 0, sizeof(*l));
+
+	for (lp = &conf_levels; *lp; lp = &(*lp)->n) ;
+	*lp = l;
+	l->parent = current_conf_level;
+	current_conf_level = l;
+
+	l->modules_sym = sym_lookup(NULL, 0, current_conf_level);
+	l->modules_sym->type = S_BOOLEAN;
+	l->modules_sym->flags |= SYMBOL_AUTO;
+	l->conf_prefix = CONFIG_;
+
+	sym_init(current_conf_level);
+}
+
+void sym_level_close(struct conf_level *l)
+{
+	if (!l->modules_sym->prop) {
+		struct property *prop;
+		prop = prop_alloc(P_DEFAULT, l->modules_sym);
+		prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0, current_conf_level));
+	}
+	current_conf_level = l->parent;
+}
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index d0b8b23..f1b53ae 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -11,10 +11,10 @@
 #include "lkc.h"
 
 /* file already present in list? If not add it */
-struct file *file_lookup(const char *name)
+struct file *file_lookup(const char *name, struct conf_level *l)
 {
 	struct file *file;
-	const char *file_name = sym_expand_string_value(name);
+	const char *file_name = sym_expand_string_value(name, l);
 
 	for (file = file_list; file; file = file->next) {
 		if (!strcmp(name, file->name)) {
@@ -32,7 +32,7 @@ struct file *file_lookup(const char *name)
 }
 
 /* write a dependency file as used by kbuild to track dependencies */
-int file_write_dep(const char *name)
+int file_write_dep(const char *name, struct conf_level *l)
 {
 	struct symbol *sym, *env_sym;
 	struct expr *e;
@@ -54,7 +54,7 @@ int file_write_dep(const char *name)
 	fprintf(out, "\n%s: \\\n"
 		     "\t$(deps_config)\n\n", conf_get_autoconfig_name());
 
-	expr_list_for_each_sym(sym_env_list, e, sym) {
+	expr_list_for_each_sym(l->sym_env_list, e, sym) {
 		struct property *prop;
 		const char *value;
 
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
index 00f9d3a..cd863ad 100644
--- a/scripts/kconfig/zconf.l
+++ b/scripts/kconfig/zconf.l
@@ -291,14 +291,14 @@ void zconf_initscan(const char *name)
 	current_buf = malloc(sizeof(*current_buf));
 	memset(current_buf, 0, sizeof(*current_buf));
 
-	current_file = file_lookup(name);
+	current_file = file_lookup(name, current_conf_level);
 	current_file->lineno = 1;
 }
 
 void zconf_nextfile(const char *name)
 {
 	struct file *iter;
-	struct file *file = file_lookup(name);
+	struct file *file = file_lookup(name, current_conf_level);
 	struct buffer *buf = malloc(sizeof(*buf));
 	memset(buf, 0, sizeof(*buf));
 
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 864da07..c6e923f 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -26,9 +26,9 @@ static void zconf_error(const char *err, ...);
 static void zconferror(const char *err);
 static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
 
-struct symbol *symbol_hash[SYMBOL_HASHSIZE];
-
 static struct menu *current_menu, *current_entry;
+struct conf_level *current_conf_level = 0;
+struct conf_level *conf_levels = 0;
 
 %}
 %expect 30
@@ -141,7 +141,7 @@ option_error:
 
 config_entry_start: T_CONFIG T_WORD T_EOL
 {
-	struct symbol *sym = sym_lookup($2, 0);
+	struct symbol *sym = sym_lookup($2, 0, current_conf_level);
 	sym->flags |= SYMBOL_OPTIONAL;
 	menu_add_entry(sym);
 	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
@@ -155,7 +155,7 @@ config_stmt: config_entry_start config_option_list
 
 menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
 {
-	struct symbol *sym = sym_lookup($2, 0);
+	struct symbol *sym = sym_lookup($2, 0, current_conf_level);
 	sym->flags |= SYMBOL_OPTIONAL;
 	menu_add_entry(sym);
 	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
@@ -207,7 +207,7 @@ config_option: T_DEFAULT expr if_expr T_EOL
 
 config_option: T_SELECT T_WORD if_expr T_EOL
 {
-	menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
+	menu_add_symbol(P_SELECT, sym_lookup($2, 0, current_conf_level), $3);
 	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
 };
 
@@ -241,7 +241,7 @@ symbol_option_arg:
 
 choice: T_CHOICE word_opt T_EOL
 {
-	struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
+	struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE, current_conf_level);
 	sym->flags |= SYMBOL_AUTO;
 	menu_add_entry(sym);
 	menu_add_expr(P_CHOICE, NULL, NULL);
@@ -299,7 +299,7 @@ choice_option: T_OPTIONAL T_EOL
 choice_option: T_DEFAULT T_WORD if_expr T_EOL
 {
 	if ($1->stype == S_UNKNOWN) {
-		menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
+		menu_add_symbol(P_DEFAULT, sym_lookup($2, 0, current_conf_level), $3);
 		printd(DEBUG_PARSE, "%s:%d:default\n",
 			zconf_curname(), zconf_lineno());
 	} else
@@ -475,8 +475,8 @@ expr:	  symbol				{ $$ = expr_alloc_symbol($1); }
 	| expr T_AND expr			{ $$ = expr_alloc_two(E_AND, $1, $3); }
 ;
 
-symbol:	  T_WORD	{ $$ = sym_lookup($1, 0); free($1); }
-	| T_WORD_QUOTE	{ $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
+symbol:	  T_WORD	{ $$ = sym_lookup($1, 0, current_conf_level); free($1); }
+	| T_WORD_QUOTE	{ $$ = sym_lookup($1, SYMBOL_CONST, current_conf_level); free($1); }
 ;
 
 word_opt: /* empty */			{ $$ = NULL; }
@@ -487,15 +487,14 @@ word_opt: /* empty */			{ $$ = NULL; }
 void conf_parse(const char *name)
 {
 	struct symbol *sym;
+	struct conf_level *l;
 	int i;
 
+	sym_level_open(&rootlevel);
+
 	zconf_initscan(name);
 
-	sym_init();
 	_menu_init();
-	modules_sym = sym_lookup(NULL, 0);
-	modules_sym->type = S_BOOLEAN;
-	modules_sym->flags |= SYMBOL_AUTO;
 	rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
 	if (getenv("ZCONF_DEBUG"))
@@ -503,24 +502,26 @@ void conf_parse(const char *name)
 	zconfparse();
 	if (zconfnerrs)
 		exit(1);
-	if (!modules_sym->prop) {
-		struct property *prop;
-
-		prop = prop_alloc(P_DEFAULT, modules_sym);
-		prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
-	}
 
 	rootmenu.prompt->text = _(rootmenu.prompt->text);
-	rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
+	rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text, current_conf_level);
 
 	menu_finalize(&rootmenu);
-	for_all_symbols(i, sym) {
-		if (sym_check_deps(sym))
-			zconfnerrs++;
-        }
+
+	l = conf_levels;
+	while (l) {
+		for_all_symbols_level(i, sym, current_conf_level) {
+			if (sym_check_deps(sym))
+				zconfnerrs++;
+		}
+		l = l->n;
+	}	
+
 	if (zconfnerrs)
 		exit(1);
 	sym_set_change_count(1);
+
+	sym_level_close(&rootlevel);
 }
 
 static const char *zconf_tokenname(int token)
-- 
1.6.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ