Peter Kjellerstedt at axis.com writes:

Hello,

the attached patch should bring extra/config in line
with the Linux 2.6.7 sources.

The following are the commit messages for the respective
files from the Linux bk-repository:

checklist.c:
* fix menuconfig choice item help display

confdata.c:
* config: choice fix
* kconfig: don't rename target dir when saving config

expr.c, expr.h:
* config: disable debug prints

mconf.c:
* fix menuconfig choice item help display

menu.c:
* Kconfig: use select statements

symbol.c:
* config: choice fix
* Avoid bogus warning about recursive dependencies
* c99 struct initialiser conversions

textbox.c:
* janitor: don't init statics to 0

util.c:
* fix lxdialog behaviour

//Peter
diff --git a/scripts/config/checklist.c b/scripts/config/checklist.c
index 9744d79..4dbd166 100644
--- a/scripts/config/checklist.c
+++ b/scripts/config/checklist.c
@@ -138,10 +138,12 @@
 
     /* Initializes status */
     for (i = 0; i < item_no; i++) {
-	status[i] = items[i]->selected;
-	if (!choice && status[i])
-            choice = i;
+	status[i] = (items[i]->selected == 1); /* ON */
+	if ((!choice && status[i]) || items[i]->selected == 2) /* SELECTED */
+            choice = i + 1;
     }
+    if (choice)
+	    choice--;
 
     max_choice = MIN (list_height, item_no);
 
@@ -303,6 +305,9 @@
 	case 'H':
 	case 'h':
 	case '?':
+	    for (i = 0; i < item_no; i++)
+		items[i]->selected = 0;
+	    items[scroll + choice]->selected = 1;
 	    delwin (dialog);
 	    free (status);
 	    return 1;
@@ -341,7 +346,11 @@
 		for (i = 0; i < item_no; i++) {
 			items[i]->selected = status[i];
 		}
-            }
+            } else {
+		    for (i = 0; i < item_no; i++)
+			    items[i]->selected = 0;
+		    items[scroll + choice]->selected = 1;
+	    }
 	    delwin (dialog);
 	    free (status);
 	    return button;
diff --git a/scripts/config/confdata.c b/scripts/config/confdata.c
index c46aea8..fd3a345 100644
--- a/scripts/config/confdata.c
+++ b/scripts/config/confdata.c
@@ -225,6 +225,8 @@
 	}
 	fclose(in);
 
+	if (modules_sym)
+		sym_calc_value(modules_sym);
 	for_all_symbols(i, sym) {
 		sym_calc_value(sym);
 		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
@@ -265,8 +267,14 @@
 
 	dirname[0] = 0;
 	if (name && name[0]) {
-		char *slash = strrchr(name, '/');
-		if (slash) {
+		struct stat st;
+		char *slash;
+
+		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
+			strcpy(dirname, name);
+			strcat(dirname, "/");
+			basename = conf_def_filename;
+		} else if ((slash = strrchr(name, '/'))) {
 			int size = slash - name + 1;
 			memcpy(dirname, name, size);
 			dirname[size] = 0;
diff --git a/scripts/config/expr.c b/scripts/config/expr.c
index 3f15ae8..10f4523 100644
--- a/scripts/config/expr.c
+++ b/scripts/config/expr.c
@@ -10,6 +10,8 @@
 #define LKC_DIRECT_LINK
 #include "lkc.h"
 
+#define DEBUG_EXPR	0
+
 struct expr *expr_alloc_symbol(struct symbol *sym)
 {
 	struct expr *e = malloc(sizeof(*e));
@@ -220,10 +222,12 @@
 		/* panic */;
 	}
 
-	print_expr(0, e1, 0);
-	printf(" = ");
-	print_expr(0, e2, 0);
-	printf(" ?\n");
+	if (DEBUG_EXPR) {
+		expr_fprint(e1, stdout);
+		printf(" = ");
+		expr_fprint(e2, stdout);
+		printf(" ?\n");
+	}
 
 	return 0;
 }
@@ -397,11 +401,13 @@
 			return expr_alloc_symbol(&symbol_yes);
 	}
 
-	printf("optimize ");
-	print_expr(0, e1, 0);
-	printf(" || ");
-	print_expr(0, e2, 0);
-	printf(" ?\n");
+	if (DEBUG_EXPR) {
+		printf("optimize (");
+		expr_fprint(e1, stdout);
+		printf(") || (");
+		expr_fprint(e2, stdout);
+		printf(")?\n");
+	}
 	return NULL;
 }
 
@@ -444,6 +450,11 @@
 		// (a) && (a!='n') -> (a)
 		return expr_alloc_symbol(sym1);
 
+	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
+	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
+		// (a) && (a!='m') -> (a='y')
+		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
 	if (sym1->type == S_TRISTATE) {
 		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
 			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
@@ -483,11 +494,14 @@
 		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
 			return NULL;
 	}
-	printf("optimize ");
-	print_expr(0, e1, 0);
-	printf(" && ");
-	print_expr(0, e2, 0);
-	printf(" ?\n");
+
+	if (DEBUG_EXPR) {
+		printf("optimize (");
+		expr_fprint(e1, stdout);
+		printf(") && (");
+		expr_fprint(e2, stdout);
+		printf(")?\n");
+	}
 	return NULL;
 }
 
@@ -1073,11 +1087,3 @@
 {
 	expr_print(e, expr_print_file_helper, out, E_NONE);
 }
-
-void print_expr(int mask, struct expr *e, int prevtoken)
-{
-	if (!(cdebug & mask))
-		return;
-	expr_fprint(e, stdout);
-}
-
diff --git a/scripts/config/expr.h b/scripts/config/expr.h
index cc616f1..cac51f6 100644
--- a/scripts/config/expr.h
+++ b/scripts/config/expr.h
@@ -174,7 +174,6 @@
 struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
 
 void expr_fprint(struct expr *e, FILE *out);
-void print_expr(int mask, struct expr *e, int prevtoken);
 
 static inline int expr_is_yes(struct expr *e)
 {
diff --git a/scripts/config/mconf.c b/scripts/config/mconf.c
index fe4562b..0ac3a8d 100644
--- a/scripts/config/mconf.c
+++ b/scripts/config/mconf.c
@@ -515,9 +515,9 @@
 	struct menu *child;
 	struct symbol *active;
 
+	active = sym_get_choice_value(menu->sym);
 	while (1) {
 		current_menu = menu;
-		active = sym_get_choice_value(menu->sym);
 		cdone(); cinit();
 		for (child = menu->list; child; child = child->next) {
 			if (!menu_is_visible(child))
@@ -525,19 +525,28 @@
 			cmake();
 			cprint_tag("%p", child);
 			cprint_name("%s", menu_get_prompt(child));
-			items[item_no - 1]->selected = (child->sym == active);
+			if (child->sym == sym_get_choice_value(menu->sym))
+				items[item_no - 1]->selected = 1; /* ON */
+			else if (child->sym == active)
+				items[item_no - 1]->selected = 2; /* SELECTED */
+			else
+				items[item_no - 1]->selected = 0; /* OFF */
 		}
 
 		switch (dialog_checklist(prompt ? prompt : "Main Menu",
 					radiolist_instructions, 15, 70, 6,
 					item_no, items, FLAG_RADIO)) {
 		case 0:
-			if (sscanf(first_sel_item(item_no, items)->tag, "%p", &menu) != 1)
+			if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) != 1)
 				break;
-			sym_set_tristate_value(menu->sym, yes);
+			sym_set_tristate_value(child->sym, yes);
 			return;
 		case 1:
-			show_help(menu);
+			if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) == 1) {
+				show_help(child);
+				active = child->sym;
+			} else
+				show_help(menu);
 			break;
 		case 255:
 			return;
diff --git a/scripts/config/menu.c b/scripts/config/menu.c
index 9b8d389..6425296 100644
--- a/scripts/config/menu.c
+++ b/scripts/config/menu.c
@@ -16,6 +16,26 @@
 struct file *file_list;
 struct file *current_file;
 
+static void menu_warn(struct menu *menu, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+}
+
+static void prop_warn(struct property *prop, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+}
+
 void menu_init(void)
 {
 	current_entry = current_menu = &rootmenu;
@@ -94,9 +114,9 @@
 		sym->type = type;
 		return;
 	}
-	fprintf(stderr, "%s:%d:warning: type of '%s' redefined from '%s' to '%s'\n",
-		current_entry->file->name, current_entry->lineno,
-		sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type));
+	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n",
+	    sym->name ? sym->name : "<choice>",
+	    sym_type_name(sym->type), sym_type_name(type));
 }
 
 struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
@@ -110,8 +130,7 @@
 
 	if (prompt) {
 		if (current_entry->prompt)
-			fprintf(stderr, "%s:%d: prompt redefined\n",
-				current_entry->file->name, current_entry->lineno);
+			menu_warn(current_entry, "prompt redefined\n");
 		current_entry->prompt = prop;
 	}
 
@@ -133,6 +152,50 @@
 	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
 }
 
+void sym_check_prop(struct symbol *sym)
+{
+	struct property *prop;
+	struct symbol *sym2;
+	for (prop = sym->prop; prop; prop = prop->next) {
+		switch (prop->type) {
+		case P_DEFAULT:
+			if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
+			    prop->expr->type != E_SYMBOL)
+				prop_warn(prop,
+				    "default for config symbol '%'"
+				    " must be a single symbol", sym->name);
+			break;
+		case P_SELECT:
+			sym2 = prop_get_symbol(prop);
+			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
+				prop_warn(prop,
+				    "config symbol '%s' uses select, but is "
+				    "not boolean or tristate", sym->name);
+			else if (sym2->type == S_UNKNOWN)
+				prop_warn(prop,
+				    "'select' used by config symbol '%s' "
+				    "refer to undefined symbol '%s'",
+				    sym->name, sym2->name);
+			else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
+				prop_warn(prop,
+				    "'%s' has wrong type. 'select' only "
+				    "accept arguments of boolean and "
+				    "tristate type", sym2->name);
+			break;
+		case P_RANGE:
+			if (sym->type != S_INT && sym->type != S_HEX)
+				prop_warn(prop, "range is only allowed "
+				                "for int or hex symbols");
+			if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
+			    !sym_string_valid(sym, prop->expr->right.sym->name))
+				prop_warn(prop, "range is invalid");
+			break;
+		default:
+			;
+		}
+	}
+}
+
 void menu_finalize(struct menu *parent)
 {
 	struct menu *menu, *last_menu;
@@ -222,17 +285,16 @@
 		if (sym && sym_is_choice(sym) && menu->sym) {
 			menu->sym->flags |= SYMBOL_CHOICEVAL;
 			if (!menu->prompt)
-				fprintf(stderr, "%s:%d:warning: choice value must have a prompt\n",
-					menu->file->name, menu->lineno);
+				menu_warn(menu, "choice value must have a prompt");
 			for (prop = menu->sym->prop; prop; prop = prop->next) {
 				if (prop->type == P_PROMPT && prop->menu != menu) {
-					fprintf(stderr, "%s:%d:warning: choice values currently only support a single prompt\n",
-						prop->file->name, prop->lineno);
-
+					prop_warn(prop, "choice values "
+					    "currently only support a "
+					    "single prompt");
 				}
 				if (prop->type == P_DEFAULT)
-					fprintf(stderr, "%s:%d:warning: defaults for choice values not supported\n",
-						prop->file->name, prop->lineno);
+					prop_warn(prop, "defaults for choice "
+					    "values not supported");
 			}
 			current_entry = menu;
 			menu_set_type(sym->type);
@@ -256,43 +318,15 @@
 	}
 
 	if (sym && !(sym->flags & SYMBOL_WARNED)) {
-		struct symbol *sym2;
 		if (sym->type == S_UNKNOWN)
-			fprintf(stderr, "%s:%d:warning: config symbol defined without type\n",
-				parent->file->name, parent->lineno);
+			menu_warn(parent, "config symbol defined "
+			    "without type\n");
 
 		if (sym_is_choice(sym) && !parent->prompt)
-			fprintf(stderr, "%s:%d:warning: choice must have a prompt\n",
-				parent->file->name, parent->lineno);
+			menu_warn(parent, "choice must have a prompt\n");
 
-		for (prop = sym->prop; prop; prop = prop->next) {
-			switch (prop->type) {
-			case P_DEFAULT:
-				if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
-				    prop->expr->type != E_SYMBOL)
-					fprintf(stderr, "%s:%d:warning: default must be a single symbol\n",
-						prop->file->name, prop->lineno);
-				break;
-			case P_SELECT:
-				sym2 = prop_get_symbol(prop);
-				if ((sym->type != S_BOOLEAN && sym->type != S_TRISTATE) ||
-				    (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE))
-					fprintf(stderr, "%s:%d:warning: enable is only allowed with boolean and tristate symbols\n",
-						prop->file->name, prop->lineno);
-				break;
-			case P_RANGE:
-				if (sym->type != S_INT && sym->type != S_HEX)
-					fprintf(stderr, "%s:%d:warning: range is only allowed for int or hex symbols\n",
-						prop->file->name, prop->lineno);
-				if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
-				    !sym_string_valid(sym, prop->expr->right.sym->name))
-					fprintf(stderr, "%s:%d:warning: range is invalid\n",
-						prop->file->name, prop->lineno);
-				break;
-			default:
-				;
-			}
-		}
+		/* Check properties connected to this symbol */
+		sym_check_prop(sym);
 		sym->flags |= SYMBOL_WARNED;
 	}
 
diff --git a/scripts/config/symbol.c b/scripts/config/symbol.c
index 29d8d3e..a9fae9c 100644
--- a/scripts/config/symbol.c
+++ b/scripts/config/symbol.c
@@ -12,25 +12,26 @@
 #include "lkc.h"
 
 struct symbol symbol_yes = {
-	name: "y",
-	curr: { "y", yes },
-	flags: SYMBOL_YES|SYMBOL_VALID,
+	.name = "y",
+	.curr = { "y", yes },
+	.flags = SYMBOL_YES|SYMBOL_VALID,
 }, symbol_mod = {
-	name: "m",
-	curr: { "m", mod },
-	flags: SYMBOL_MOD|SYMBOL_VALID,
+	.name = "m",
+	.curr = { "m", mod },
+	.flags = SYMBOL_MOD|SYMBOL_VALID,
 }, symbol_no = {
-	name: "n",
-	curr: { "n", no },
-	flags: SYMBOL_NO|SYMBOL_VALID,
+	.name = "n",
+	.curr = { "n", no },
+	.flags = SYMBOL_NO|SYMBOL_VALID,
 }, symbol_empty = {
-	name: "",
-	curr: { "", no },
-	flags: SYMBOL_VALID,
+	.name = "",
+	.curr = { "", no },
+	.flags = SYMBOL_VALID,
 };
 
 int sym_change_count;
 struct symbol *modules_sym;
+tristate modules_val;
 
 void sym_add_default(struct symbol *sym, const char *def)
 {
@@ -72,11 +73,8 @@
 	if (type == S_TRISTATE) {
 		if (sym_is_choice_value(sym) && sym->visible == yes)
 			type = S_BOOLEAN;
-		else {
-			sym_calc_value(modules_sym);
-			if (modules_sym->curr.tri == no)
-				type = S_BOOLEAN;
-		}
+		else if (modules_val == no)
+			type = S_BOOLEAN;
 	}
 	return type;
 }
@@ -146,6 +144,8 @@
 		prop->visible.tri = expr_calc_value(prop->visible.expr);
 		tri = E_OR(tri, prop->visible.tri);
 	}
+	if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
+		tri = yes;
 	if (sym->visible != tri) {
 		sym->visible = tri;
 		sym_set_changed(sym);
@@ -155,6 +155,8 @@
 	tri = no;
 	if (sym->rev_dep.expr)
 		tri = expr_calc_value(sym->rev_dep.expr);
+	if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
+		tri = yes;
 	if (sym->rev_dep.tri != tri) {
 		sym->rev_dep.tri = tri;
 		sym_set_changed(sym);
@@ -261,14 +263,8 @@
 				newval.tri = expr_calc_value(prop->expr);
 			}
 		}
-		if (sym_get_type(sym) == S_BOOLEAN) {
-			if (newval.tri == mod)
-				newval.tri = yes;
-			if (sym->visible == mod)
-				sym->visible = yes;
-			if (sym->rev_dep.tri == mod)
-				sym->rev_dep.tri = yes;
-		}
+		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
+			newval.tri = yes;
 		break;
 	case S_STRING:
 	case S_HEX:
@@ -300,6 +296,8 @@
 
 	if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
 		sym_set_changed(sym);
+	if (modules_sym == sym)
+		modules_val = modules_sym->curr.tri;
 
 	if (sym_is_choice(sym)) {
 		int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
@@ -320,6 +318,8 @@
 	for_all_symbols(i, sym)
 		sym->flags &= ~SYMBOL_VALID;
 	sym_change_count++;
+	if (modules_sym)
+		sym_calc_value(modules_sym);
 }
 
 void sym_set_changed(struct symbol *sym)
@@ -699,7 +699,7 @@
 		goto out;
 
 	for (prop = sym->prop; prop; prop = prop->next) {
-		if (prop->type == P_CHOICE)
+		if (prop->type == P_CHOICE || prop->type == P_SELECT)
 			continue;
 		sym2 = sym_check_expr_deps(prop->visible.expr);
 		if (sym2)
diff --git a/scripts/config/textbox.c b/scripts/config/textbox.c
index 8fe9077..a5a460b 100644
--- a/scripts/config/textbox.c
+++ b/scripts/config/textbox.c
@@ -27,8 +27,8 @@
 static char *get_line (void);
 static void print_position (WINDOW * win, int height, int width);
 
-static int hscroll = 0, fd, file_size, bytes_read;
-static int begin_reached = 1, end_reached = 0, page_length;
+static int hscroll, fd, file_size, bytes_read;
+static int begin_reached = 1, end_reached, page_length;
 static char *buf, *page;
 
 /*
diff --git a/scripts/config/util.c b/scripts/config/util.c
index 104ff0e..0a2f827 100644
--- a/scripts/config/util.c
+++ b/scripts/config/util.c
@@ -348,7 +348,7 @@
 		c = tolower(string[i]);
 
 		if (strchr("<[(", c)) ++in_paren;
-		if (strchr(">])", c)) --in_paren;
+		if (strchr(">])", c) && in_paren > 0) --in_paren;
 
 		if ((! in_paren) && isalpha(c) &&
 		     strchr(exempt, c) == 0)