Updated to match trunk/uClibc/extra/config as of r10132, and thus
Linux 2.6.11.
diff --git a/scripts/config/Makefile b/scripts/config/Makefile
index c0b5b9d..3c4669f 100644
--- a/scripts/config/Makefile
+++ b/scripts/config/Makefile
@@ -9,7 +9,11 @@
 
 all: ncurses conf mconf
 
+ifeq ($(shell uname),SunOS)
+LIBS = -lcurses
+else
 LIBS = -lncurses
+endif
 ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
 	HOSTNCURSES += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
 else
@@ -32,14 +36,17 @@
 endif
 endif
 
-CONF_SRC  =conf.c
-MCONF_SRC =mconf.c checklist.c menubox.c textbox.c yesno.c inputbox.c util.c msgbox.c
-SHARED_SRC=zconf.tab.c
-SHARED_DEPS:=$(srcdir)/lkc.h $(srcdir)/lkc_proto.h \
-  lkc_defs.h $(srcdir)/expr.h zconf.tab.h
-CONF_OBJS =$(patsubst %.c,%.o, $(CONF_SRC))
-MCONF_OBJS=$(patsubst %.c,%.o, $(MCONF_SRC))
-SHARED_OBJS=$(patsubst %.c,%.o, $(SHARED_SRC))
+CONF_SRC     = conf.c
+MCONF_SRC    = mconf.c
+LXD_SRC      = lxdialog/checklist.c lxdialog/menubox.c lxdialog/textbox.c \
+               lxdialog/yesno.c lxdialog/inputbox.c lxdialog/util.c \
+               lxdialog/msgbox.c
+SHARED_SRC   = zconf.tab.c
+SHARED_DEPS := $(srcdir)/lkc.h $(srcdir)/lkc_proto.h \
+               lkc_defs.h $(srcdir)/expr.h zconf.tab.h
+CONF_OBJS    = $(patsubst %.c,%.o, $(CONF_SRC))
+MCONF_OBJS   = $(patsubst %.c,%.o, $(MCONF_SRC) $(LXD_SRC))
+SHARED_OBJS  = $(patsubst %.c,%.o, $(SHARED_SRC))
 
 conf: $(CONF_OBJS) $(SHARED_OBJS)
 	$(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@
diff --git a/scripts/config/conf.c b/scripts/config/conf.c
index 3b0c1c1..78c1af5 100644
--- a/scripts/config/conf.c
+++ b/scripts/config/conf.c
@@ -31,14 +31,14 @@
 static int indent = 1;
 static int valid_stdin = 1;
 static int conf_cnt;
-static char line[128];
+static signed char line[128];
 static struct menu *rootEntry;
 
 static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
 
-static void strip(char *str)
+static void strip(signed char *str)
 {
-	char *p = str;
+	signed char *p = str;
 	int l;
 
 	while ((isspace(*p)))
diff --git a/scripts/config/confdata.c b/scripts/config/confdata.c
index fd3a345..7b9000e 100644
--- a/scripts/config/confdata.c
+++ b/scripts/config/confdata.c
@@ -23,10 +23,10 @@
 	NULL,
 };
 
-static char *conf_expand_value(const char *in)
+static char *conf_expand_value(const signed char *in)
 {
 	struct symbol *sym;
-	const char *src;
+	const signed char *src;
 	static char res_value[SYMBOL_MAXLENGTH];
 	char *dst, name[SYMBOL_MAXLENGTH];
 
@@ -287,7 +287,7 @@
 	} else
 		basename = conf_def_filename;
 
-	sprintf(newname, "%s.tmpconfig.%d", dirname, getpid());
+	sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
 	out = fopen(newname, "w");
 	if (!out)
 		return 1;
diff --git a/scripts/config/expr.c b/scripts/config/expr.c
index 10f4523..30e4f9d 100644
--- a/scripts/config/expr.c
+++ b/scripts/config/expr.c
@@ -1087,3 +1087,13 @@
 {
 	expr_print(e, expr_print_file_helper, out, E_NONE);
 }
+
+static void expr_print_gstr_helper(void *data, const char *str)
+{
+	str_append((struct gstr*)data, str);
+}
+
+void expr_gstr_print(struct expr *e, struct gstr *gs)
+{
+	expr_print(e, expr_print_gstr_helper, gs, E_NONE);
+}
diff --git a/scripts/config/expr.h b/scripts/config/expr.h
index cac51f6..7d39ff4 100644
--- a/scripts/config/expr.h
+++ b/scripts/config/expr.h
@@ -174,6 +174,8 @@
 struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
 
 void expr_fprint(struct expr *e, FILE *out);
+struct gstr; /* forward */
+void expr_gstr_print(struct expr *e, struct gstr *gs);
 
 static inline int expr_is_yes(struct expr *e)
 {
diff --git a/scripts/config/lkc.h b/scripts/config/lkc.h
index dd040f7..b8a67fc 100644
--- a/scripts/config/lkc.h
+++ b/scripts/config/lkc.h
@@ -56,11 +56,21 @@
 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
 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);
 
-extern struct menu *current_entry;
-extern struct menu *current_menu;
+struct gstr {
+	size_t len;
+	char  *s;
+};
+struct gstr str_new(void);
+struct gstr str_assign(const char *s);
+void str_free(struct gstr *gs);
+void str_append(struct gstr *gs, const char *s);
+void str_printf(struct gstr *gs, const char *fmt, ...);
+const char *str_get(struct gstr *gs);
 
 /* symbol.c */
 void sym_init(void);
diff --git a/scripts/config/lkc_proto.h b/scripts/config/lkc_proto.h
index 97c7917..6dc6d0c 100644
--- a/scripts/config/lkc_proto.h
+++ b/scripts/config/lkc_proto.h
@@ -18,6 +18,7 @@
 
 P(sym_lookup,struct symbol *,(const char *name, int isconst));
 P(sym_find,struct symbol *,(const char *name));
+P(sym_re_search,struct symbol **,(const char *pattern));
 P(sym_type_name,const char *,(enum symbol_type type));
 P(sym_calc_value,void,(struct symbol *sym));
 P(sym_get_type,enum symbol_type,(struct symbol *sym));
diff --git a/scripts/config/lxdialog/BIG.FAT.WARNING b/scripts/config/lxdialog/BIG.FAT.WARNING
new file mode 100644
index 0000000..a8999d8
--- /dev/null
+++ b/scripts/config/lxdialog/BIG.FAT.WARNING
@@ -0,0 +1,4 @@
+This is NOT the official version of dialog.  This version has been
+significantly modified from the original.  It is for use by the Linux
+kernel configuration script.  Please do not bother Savio Lam with 
+questions about this program.
diff --git a/scripts/config/checklist.c b/scripts/config/lxdialog/checklist.c
similarity index 98%
rename from scripts/config/checklist.c
rename to scripts/config/lxdialog/checklist.c
index 4dbd166..71de4a1 100644
--- a/scripts/config/checklist.c
+++ b/scripts/config/lxdialog/checklist.c
@@ -120,7 +120,7 @@
 dialog_checklist (const char *title, const char *prompt, int height, int width,
 	int list_height, int item_no, struct dialog_list_item ** items,
 	int flag)
-
+	
 {
     int i, x, y, box_x, box_y;
     int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
@@ -197,7 +197,7 @@
 
     /* Find length of longest item in order to center checklist */
     check_x = 0;
-    for (i = 0; i < item_no; i++)
+    for (i = 0; i < item_no; i++) 
 	check_x = MAX (check_x, + strlen (items[i]->name) + 4);
 
     check_x = (list_width - check_x) / 2;
@@ -231,7 +231,7 @@
                 break;
 
 
-	if ( i < max_choice || key == KEY_UP || key == KEY_DOWN ||
+	if ( i < max_choice || key == KEY_UP || key == KEY_DOWN || 
 	    key == '+' || key == '-' ) {
 	    if (key == KEY_UP || key == '-') {
 		if (!choice) {
@@ -342,7 +342,7 @@
 		}
 		wnoutrefresh (list);
 		wrefresh (dialog);
-
+            
 		for (i = 0; i < item_no; i++) {
 			items[i]->selected = status[i];
 		}
@@ -364,7 +364,7 @@
 	/* Now, update everything... */
 	doupdate ();
     }
-
+    
 
     delwin (dialog);
     free (status);
diff --git a/scripts/config/colors.h b/scripts/config/lxdialog/colors.h
similarity index 100%
rename from scripts/config/colors.h
rename to scripts/config/lxdialog/colors.h
diff --git a/scripts/config/dialog.h b/scripts/config/lxdialog/dialog.h
similarity index 97%
rename from scripts/config/dialog.h
rename to scripts/config/lxdialog/dialog.h
index 6486cc8..7bab3ad 100644
--- a/scripts/config/dialog.h
+++ b/scripts/config/lxdialog/dialog.h
@@ -27,6 +27,9 @@
 #include <string.h>
 
 #ifdef CURSES_LOC
+#ifdef __sun__
+#define CURS_MACROS
+#endif
 #include CURSES_LOC
 
 /*
@@ -86,7 +89,7 @@
 #define ACS_DARROW 'v'
 #endif
 
-/*
+/* 
  * Attribute names
  */
 #define screen_attr                   attributes[0]
@@ -130,7 +133,7 @@
 extern chtype attributes[];
 #endif
 
-extern char *backtitle;
+extern const char *backtitle;
 
 struct dialog_list_item {
 	char *name;
@@ -162,7 +165,7 @@
 		int width, int pause);
 int dialog_textbox (const char *title, const char *file, int height, int width);
 int dialog_menu (const char *title, const char *prompt, int height, int width,
-		int menu_height, const char *choice, int item_no,
+		int menu_height, const char *choice, int item_no, 
 		struct dialog_list_item ** items);
 int dialog_checklist (const char *title, const char *prompt, int height,
 		int width, int list_height, int item_no,
diff --git a/scripts/config/inputbox.c b/scripts/config/lxdialog/inputbox.c
similarity index 100%
rename from scripts/config/inputbox.c
rename to scripts/config/lxdialog/inputbox.c
diff --git a/scripts/config/menubox.c b/scripts/config/lxdialog/menubox.c
similarity index 97%
rename from scripts/config/menubox.c
rename to scripts/config/lxdialog/menubox.c
index 431f09f..873dc58 100644
--- a/scripts/config/menubox.c
+++ b/scripts/config/lxdialog/menubox.c
@@ -26,7 +26,7 @@
  *
  *    *)  A bugfix for the Page-Down problem
  *
- *    *)  Formerly when I used Page Down and Page Up, the cursor would be set
+ *    *)  Formerly when I used Page Down and Page Up, the cursor would be set 
  *        to the first position in the menu box.  Now lxdialog is a bit
  *        smarter and works more like other menu systems (just have a look at
  *        it).
@@ -71,7 +71,7 @@
 
     strncpy(menu_item, item, menu_width);
     menu_item[menu_width] = 0;
-    j = first_alpha(menu_item, "YyNnMm");
+    j = first_alpha(menu_item, "YyNnMmHh");
 
     /* Clear 'residue' of last item */
     wattrset (win, menubox_attr);
@@ -225,7 +225,7 @@
 
     /*
      * Find length of longest item in order to center menu.
-     * Set 'choice' to default item.
+     * Set 'choice' to default item. 
      */
     item_x = 0;
     for (i = 0; i < item_no; i++) {
@@ -278,23 +278,23 @@
 
 	if (key < 256 && isalpha(key)) key = tolower(key);
 
-	if (strchr("ynm", key))
+	if (strchr("ynmh", key))
 		i = max_choice;
 	else {
         for (i = choice+1; i < max_choice; i++) {
-		j = first_alpha(items[scroll + i]->name, "YyNnMm>");
+		j = first_alpha(items[scroll + i]->name, "YyNnMmHh");
 		if (key == tolower(items[scroll + i]->name[j]))
                 	break;
 	}
 	if (i == max_choice)
        		for (i = 0; i < max_choice; i++) {
-			j = first_alpha(items[scroll + i]->name, "YyNnMm>");
+			j = first_alpha(items[scroll + i]->name, "YyNnMmHh");
 			if (key == tolower(items[scroll + i]->name[j]))
                 		break;
 		}
 	}
 
-	if (i < max_choice ||
+	if (i < max_choice || 
             key == KEY_UP || key == KEY_DOWN ||
             key == '-' || key == '+' ||
             key == KEY_PPAGE || key == KEY_NPAGE) {
@@ -398,6 +398,7 @@
 	case 'y':
 	case 'n':
 	case 'm':
+	case '/':
 	    /* save scroll info */
 	    if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
 		fprintf(f,"%d\n",scroll);
@@ -411,6 +412,7 @@
             case 'n': return 4;
             case 'm': return 5;
             case ' ': return 6;
+            case '/': return 7;
             }
 	    return 0;
 	case 'h':
diff --git a/scripts/config/msgbox.c b/scripts/config/lxdialog/msgbox.c
similarity index 100%
rename from scripts/config/msgbox.c
rename to scripts/config/lxdialog/msgbox.c
diff --git a/scripts/config/textbox.c b/scripts/config/lxdialog/textbox.c
similarity index 100%
rename from scripts/config/textbox.c
rename to scripts/config/lxdialog/textbox.c
diff --git a/scripts/config/lxdialog/util.c b/scripts/config/lxdialog/util.c
new file mode 100644
index 0000000..6f83951
--- /dev/null
+++ b/scripts/config/lxdialog/util.c
@@ -0,0 +1,375 @@
+/*
+ *  util.c
+ *
+ *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+
+/* use colors by default? */
+bool use_colors = 1;
+
+const char *backtitle = NULL;
+
+const char *dialog_result;
+
+/* 
+ * Attribute values, default is for mono display
+ */
+chtype attributes[] =
+{
+    A_NORMAL,			/* screen_attr */
+    A_NORMAL,			/* shadow_attr */
+    A_NORMAL,			/* dialog_attr */
+    A_BOLD,			/* title_attr */
+    A_NORMAL,			/* border_attr */
+    A_REVERSE,			/* button_active_attr */
+    A_DIM,			/* button_inactive_attr */
+    A_REVERSE,			/* button_key_active_attr */
+    A_BOLD,			/* button_key_inactive_attr */
+    A_REVERSE,			/* button_label_active_attr */
+    A_NORMAL,			/* button_label_inactive_attr */
+    A_NORMAL,			/* inputbox_attr */
+    A_NORMAL,			/* inputbox_border_attr */
+    A_NORMAL,			/* searchbox_attr */
+    A_BOLD,			/* searchbox_title_attr */
+    A_NORMAL,			/* searchbox_border_attr */
+    A_BOLD,			/* position_indicator_attr */
+    A_NORMAL,			/* menubox_attr */
+    A_NORMAL,			/* menubox_border_attr */
+    A_NORMAL,			/* item_attr */
+    A_REVERSE,			/* item_selected_attr */
+    A_BOLD,			/* tag_attr */
+    A_REVERSE,			/* tag_selected_attr */
+    A_BOLD,			/* tag_key_attr */
+    A_REVERSE,			/* tag_key_selected_attr */
+    A_BOLD,			/* check_attr */
+    A_REVERSE,			/* check_selected_attr */
+    A_BOLD,			/* uarrow_attr */
+    A_BOLD			/* darrow_attr */
+};
+
+
+#include "colors.h"
+
+/*
+ * Table of color values
+ */
+int color_table[][3] =
+{
+    {SCREEN_FG, SCREEN_BG, SCREEN_HL},
+    {SHADOW_FG, SHADOW_BG, SHADOW_HL},
+    {DIALOG_FG, DIALOG_BG, DIALOG_HL},
+    {TITLE_FG, TITLE_BG, TITLE_HL},
+    {BORDER_FG, BORDER_BG, BORDER_HL},
+    {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
+    {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
+    {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
+    {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
+    {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL},
+    {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
+     BUTTON_LABEL_INACTIVE_HL},
+    {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
+    {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
+    {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
+    {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
+    {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
+    {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
+    {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
+    {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
+    {ITEM_FG, ITEM_BG, ITEM_HL},
+    {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
+    {TAG_FG, TAG_BG, TAG_HL},
+    {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
+    {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
+    {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
+    {CHECK_FG, CHECK_BG, CHECK_HL},
+    {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
+    {UARROW_FG, UARROW_BG, UARROW_HL},
+    {DARROW_FG, DARROW_BG, DARROW_HL},
+};				/* color_table */
+
+/*
+ * Set window to attribute 'attr'
+ */
+void
+attr_clear (WINDOW * win, int height, int width, chtype attr)
+{
+    int i, j;
+
+    wattrset (win, attr);
+    for (i = 0; i < height; i++) {
+	wmove (win, i, 0);
+	for (j = 0; j < width; j++)
+	    waddch (win, ' ');
+    }
+    touchwin (win);
+}
+
+void dialog_clear (void)
+{
+    attr_clear (stdscr, LINES, COLS, screen_attr);
+    /* Display background title if it exists ... - SLH */
+    if (backtitle != NULL) {
+        int i;
+
+        wattrset (stdscr, screen_attr);
+        mvwaddstr (stdscr, 0, 1, (char *)backtitle);
+        wmove (stdscr, 1, 1);
+        for (i = 1; i < COLS - 1; i++)
+            waddch (stdscr, ACS_HLINE);
+    }
+    wnoutrefresh (stdscr);
+}
+
+/*
+ * Do some initialization for dialog
+ */
+void
+init_dialog (void)
+{
+    initscr ();			/* Init curses */
+    keypad (stdscr, TRUE);
+    cbreak ();
+    noecho ();
+
+
+    if (use_colors)	/* Set up colors */
+	color_setup ();
+
+
+    dialog_clear ();
+}
+
+/*
+ * Setup for color display
+ */
+void
+color_setup (void)
+{
+    int i;
+
+    if (has_colors ()) {	/* Terminal supports color? */
+	start_color ();
+
+	/* Initialize color pairs */
+	for (i = 0; i < ATTRIBUTE_COUNT; i++)
+	    init_pair (i + 1, color_table[i][0], color_table[i][1]);
+
+	/* Setup color attributes */
+	for (i = 0; i < ATTRIBUTE_COUNT; i++)
+	    attributes[i] = C_ATTR (color_table[i][2], i + 1);
+    }
+}
+
+/*
+ * End using dialog functions.
+ */
+void
+end_dialog (void)
+{
+    endwin ();
+}
+
+
+/*
+ * Print a string of text in a window, automatically wrap around to the
+ * next line if the string is too long to fit on one line. Newline
+ * characters '\n' are replaced by spaces.  We start on a new line
+ * if there is no room for at least 4 nonblanks following a double-space.
+ */
+void
+print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
+{
+    int newl, cur_x, cur_y;
+    int i, prompt_len, room, wlen;
+    char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
+
+    strcpy (tempstr, prompt);
+
+    prompt_len = strlen(tempstr);
+	
+    /*
+     * Remove newlines
+     */
+    for(i=0; i<prompt_len; i++) {
+	if(tempstr[i] == '\n') tempstr[i] = ' ';
+    }
+
+    if (prompt_len <= width - x * 2) {	/* If prompt is short */
+	wmove (win, y, (width - prompt_len) / 2);
+	waddstr (win, tempstr);
+    } else {
+	cur_x = x;
+	cur_y = y;
+	newl = 1;
+	word = tempstr;
+	while (word && *word) {
+	    sp = index(word, ' ');
+	    if (sp)
+	        *sp++ = 0;
+
+	    /* Wrap to next line if either the word does not fit,
+	       or it is the first word of a new sentence, and it is
+	       short, and the next word does not fit. */
+	    room = width - cur_x;
+	    wlen = strlen(word);
+	    if (wlen > room ||
+	       (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
+		     && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
+		cur_y++;
+		cur_x = x;
+	    }
+	    wmove (win, cur_y, cur_x);
+	    waddstr (win, word);
+	    getyx (win, cur_y, cur_x);
+	    cur_x++;
+	    if (sp && *sp == ' ') {
+	        cur_x++;	/* double space */
+		while (*++sp == ' ');
+		newl = 1;
+	    } else
+	        newl = 0;
+	    word = sp;
+	}
+    }
+}
+
+/*
+ * Print a button
+ */
+void
+print_button (WINDOW * win, const char *label, int y, int x, int selected)
+{
+    int i, temp;
+
+    wmove (win, y, x);
+    wattrset (win, selected ? button_active_attr : button_inactive_attr);
+    waddstr (win, "<");
+    temp = strspn (label, " ");
+    label += temp;
+    wattrset (win, selected ? button_label_active_attr
+	      : button_label_inactive_attr);
+    for (i = 0; i < temp; i++)
+	waddch (win, ' ');
+    wattrset (win, selected ? button_key_active_attr
+	      : button_key_inactive_attr);
+    waddch (win, label[0]);
+    wattrset (win, selected ? button_label_active_attr
+	      : button_label_inactive_attr);
+    waddstr (win, (char *)label + 1);
+    wattrset (win, selected ? button_active_attr : button_inactive_attr);
+    waddstr (win, ">");
+    wmove (win, y, x + temp + 1);
+}
+
+/*
+ * Draw a rectangular box with line drawing characters
+ */
+void
+draw_box (WINDOW * win, int y, int x, int height, int width,
+	  chtype box, chtype border)
+{
+    int i, j;
+
+    wattrset (win, 0);
+    for (i = 0; i < height; i++) {
+	wmove (win, y + i, x);
+	for (j = 0; j < width; j++)
+	    if (!i && !j)
+		waddch (win, border | ACS_ULCORNER);
+	    else if (i == height - 1 && !j)
+		waddch (win, border | ACS_LLCORNER);
+	    else if (!i && j == width - 1)
+		waddch (win, box | ACS_URCORNER);
+	    else if (i == height - 1 && j == width - 1)
+		waddch (win, box | ACS_LRCORNER);
+	    else if (!i)
+		waddch (win, border | ACS_HLINE);
+	    else if (i == height - 1)
+		waddch (win, box | ACS_HLINE);
+	    else if (!j)
+		waddch (win, border | ACS_VLINE);
+	    else if (j == width - 1)
+		waddch (win, box | ACS_VLINE);
+	    else
+		waddch (win, box | ' ');
+    }
+}
+
+/*
+ * Draw shadows along the right and bottom edge to give a more 3D look
+ * to the boxes
+ */
+void
+draw_shadow (WINDOW * win, int y, int x, int height, int width)
+{
+    int i;
+
+    if (has_colors ()) {	/* Whether terminal supports color? */
+	wattrset (win, shadow_attr);
+	wmove (win, y + height, x + 2);
+	for (i = 0; i < width; i++)
+	    waddch (win, winch (win) & A_CHARTEXT);
+	for (i = y + 1; i < y + height + 1; i++) {
+	    wmove (win, i, x + width);
+	    waddch (win, winch (win) & A_CHARTEXT);
+	    waddch (win, winch (win) & A_CHARTEXT);
+	}
+	wnoutrefresh (win);
+    }
+}
+
+/*
+ *  Return the position of the first alphabetic character in a string.
+ */
+int
+first_alpha(const char *string, const char *exempt)
+{
+	int i, in_paren=0, c;
+
+	for (i = 0; i < strlen(string); i++) {
+		c = tolower(string[i]);
+
+		if (strchr("<[(", c)) ++in_paren;
+		if (strchr(">])", c) && in_paren > 0) --in_paren;
+
+		if ((! in_paren) && isalpha(c) && 
+		     strchr(exempt, c) == 0)
+			return i;
+	}
+
+	return 0;
+}
+
+/*
+ * Get the first selected item in the dialog_list_item list.
+ */
+struct dialog_list_item *
+first_sel_item(int item_no, struct dialog_list_item ** items)
+{
+	int i;
+
+	for (i = 0; i < item_no; i++) {
+		if (items[i]->selected)
+			return items[i];
+	}
+
+	return NULL;
+}
diff --git a/scripts/config/yesno.c b/scripts/config/lxdialog/yesno.c
similarity index 100%
rename from scripts/config/yesno.c
rename to scripts/config/lxdialog/yesno.c
diff --git a/scripts/config/mconf.c b/scripts/config/mconf.c
index 63b4ff7..5bc2abd 100644
--- a/scripts/config/mconf.c
+++ b/scripts/config/mconf.c
@@ -23,18 +23,150 @@
 #include <termios.h>
 #include <unistd.h>
 
-#include "dialog.h"
+#include "lxdialog/dialog.h"
 
 #define LKC_DIRECT_LINK
 #include "lkc.h"
 
 static char menu_backtitle[128];
-static const char menu_instructions[] =
+static const char mconf_readme[] =
+"Overview\n"
+"--------\n"
+"Some features may be built directly into BusyBox.  Some features\n"
+"may be completely removed altogether.  There are also certain\n"
+"parameters which are not really features, but must be\n"
+"entered in as decimal or hexadecimal numbers or possibly text.\n"
+"\n"
+"Menu items beginning with [*] or [ ] represent features\n"
+"configured to be built in or removed respectively.\n"
+"\n"
+"To change any of these features, highlight it with the cursor\n"
+"keys and press <Y> to build it in or <N> to removed it.\n"
+"You may also press the <Space Bar> to cycle\n"
+"through the available options (ie. Y->N->Y).\n"
+"\n"
+"Some additional keyboard hints:\n"
+"\n"
+"Menus\n"
+"----------\n"
+"o  Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
+"   you wish to change or submenu wish to select and press <Enter>.\n"
+"   Submenus are designated by \"--->\".\n"
+"\n"
+"   Shortcut: Press the option's highlighted letter (hotkey).\n"
+"             Pressing a hotkey more than once will sequence\n"
+"             through all visible items which use that hotkey.\n"
+"\n"
+"   You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
+"   unseen options into view.\n"
+"\n"
+"o  To exit a menu use the cursor keys to highlight the <Exit> button\n"
+"   and press <ENTER>.\n"
+"\n"
+"   Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
+"             using those letters.  You may press a single <ESC>, but\n"
+"             there is a delayed response which you may find annoying.\n"
+"\n"
+"   Also, the <TAB> and cursor keys will cycle between <Select>,\n"
+"   <Exit> and <Help>\n"
+"\n"
+"o  To get help with an item, use the cursor keys to highlight <Help>\n"
+"   and Press <ENTER>.\n"
+"\n"
+"   Shortcut: Press <H> or <?>.\n"
+"\n"
+"\n"
+"Radiolists  (Choice lists)\n"
+"-----------\n"
+"o  Use the cursor keys to select the option you wish to set and press\n"
+"   <S> or the <SPACE BAR>.\n"
+"\n"
+"   Shortcut: Press the first letter of the option you wish to set then\n"
+"             press <S> or <SPACE BAR>.\n"
+"\n"
+"o  To see available help for the item, use the cursor keys to highlight\n"
+"   <Help> and Press <ENTER>.\n"
+"\n"
+"   Shortcut: Press <H> or <?>.\n"
+"\n"
+"   Also, the <TAB> and cursor keys will cycle between <Select> and\n"
+"   <Help>\n"
+"\n"
+"\n"
+"Data Entry\n"
+"-----------\n"
+"o  Enter the requested information and press <ENTER>\n"
+"   If you are entering hexadecimal values, it is not necessary to\n"
+"   add the '0x' prefix to the entry.\n"
+"\n"
+"o  For help, use the <TAB> or cursor keys to highlight the help option\n"
+"   and press <ENTER>.  You can try <TAB><H> as well.\n"
+"\n"
+"\n"
+"Text Box    (Help Window)\n"
+"--------\n"
+"o  Use the cursor keys to scroll up/down/left/right.  The VI editor\n"
+"   keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
+"   who are familiar with less and lynx.\n"
+"\n"
+"o  Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
+"\n"
+"\n"
+"Alternate Configuration Files\n"
+"-----------------------------\n"
+"Menuconfig supports the use of alternate configuration files for\n"
+"those who, for various reasons, find it necessary to switch\n"
+"between different configurations.\n"
+"\n"
+"At the end of the main menu you will find two options.  One is\n"
+"for saving the current configuration to a file of your choosing.\n"
+"The other option is for loading a previously saved alternate\n"
+"configuration.\n"
+"\n"
+"Even if you don't use alternate configuration files, but you\n"
+"find during a Menuconfig session that you have completely messed\n"
+"up your settings, you may use the \"Load Alternate...\" option to\n"
+"restore your previously saved settings from \".config\" without\n"
+"restarting Menuconfig.\n"
+"\n"
+"Other information\n"
+"-----------------\n"
+"If you use Menuconfig in an XTERM window make sure you have your\n"
+"$TERM variable set to point to a xterm definition which supports color.\n"
+"Otherwise, Menuconfig will look rather bad.  Menuconfig will not\n"
+"display correctly in a RXVT window because rxvt displays only one\n"
+"intensity of color, bright.\n"
+"\n"
+"Menuconfig will display larger menus on screens or xterms which are\n"
+"set to display more than the standard 25 row by 80 column geometry.\n"
+"In order for this to work, the \"stty size\" command must be able to\n"
+"display the screen's current row and column geometry.  I STRONGLY\n"
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
+"LINES and COLUMNS exported into your environment.  Some distributions\n"
+"export those variables via /etc/profile.  Some ncurses programs can\n"
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
+"the true screen size.\n"
+"\n"
+"Optional personality available\n"
+"------------------------------\n"
+"If you prefer to have all of the options listed in a single\n"
+"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
+"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
+"\n"
+"make MENUCONFIG_MODE=single_menu menuconfig\n"
+"\n"
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
+"is already unrolled.\n"
+"\n"
+"Note that this mode can eventually be a little more CPU expensive\n"
+"(especially with a larger number of unrolled categories) than the\n"
+"default mode.\n",
+menu_instructions[] =
 	"Arrow keys navigate the menu.  "
 	"<Enter> selects submenus --->.  "
 	"Highlighted letters are hotkeys.  "
 	"Pressing <Y> selectes a feature, while <N> will exclude a feature.  "
-	"Press <Esc><Esc> to exit, <?> for Help.  "
+	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  "
 	"Legend: [*] feature is selected  [ ] feature is excluded",
 radiolist_instructions[] =
 	"Use the arrow keys to navigate this window or "
@@ -85,23 +217,50 @@
 	"\n"
 	"If you are uncertain what all this means then you should probably\n"
 	"leave this blank.\n",
-top_menu_help[] =
+search_help[] =
 	"\n"
-	"Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
-	"you wish to change or submenu wish to select and press <Enter>.\n"
-	"Submenus are designated by \"--->\".\n"
+	"Search for CONFIG_ symbols and display their relations.\n"
+	"Example: search for \"^FOO\"\n"
+	"Result:\n"
+	"-----------------------------------------------------------------\n"
+	"Symbol: FOO [=m]\n"
+	"Prompt: Foo bus is used to drive the bar HW\n"
+	"Defined at drivers/pci/Kconfig:47\n"
+	"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+	"Location:\n"
+	"  -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
+	"    -> PCI support (PCI [=y])\n"
+	"      -> PCI access mode (<choice> [=y])\n"
+	"Selects: LIBCRC32\n"
+	"Selected by: BAR\n"
+	"-----------------------------------------------------------------\n"
+	"o The line 'Prompt:' shows the text used in the menu structure for\n"
+	"  this CONFIG_ symbol\n"
+	"o The 'Defined at' line tell at what file / line number the symbol\n"
+	"  is defined\n"
+	"o The 'Depends on:' line tell what symbols needs to be defined for\n"
+	"  this symbol to be visible in the menu (selectable)\n"
+	"o The 'Location:' lines tell where in the menu structure this symbol\n"
+	"  is located\n"
+	"    A location followed by a [=y] indicate that this is a selectable\n"
+	"    menu item - and current value is displayed inside brackets.\n"
+	"o The 'Selects:' line tell what symbol will be automatically\n"
+	"  selected if this symbol is selected (y or m)\n"
+	"o The 'Selected by' line tell what symbol has selected this symbol\n"
 	"\n"
-	"Shortcut: Press the option's highlighted letter (hotkey).\n"
-	"\n"
-	"You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
-	"unseen options into view.\n"
-;
+	"Only relevant lines are shown.\n"
+	"\n\n"
+	"Search examples:\n"
+	"Examples: USB	=> find all CONFIG_ symbols containing USB\n"
+	"          ^USB => find all CONFIG_ symbols starting with USB\n"
+	"          USB$ => find all CONFIG_ symbols ending with USB\n"
+	"\n";
 
 static char filename[PATH_MAX+1] = ".config";
-static int indent = 0;
+static int indent;
 static struct termios ios_org;
-static int rows, cols;
-struct menu *current_menu;
+static int rows = 0, cols = 0;
+static struct menu *current_menu;
 static int child_count;
 static int single_menu_mode;
 
@@ -116,33 +275,31 @@
 static void show_textbox(const char *title, const char *text, int r, int c);
 static void show_helptext(const char *title, const char *text);
 static void show_help(struct menu *menu);
-static void show_readme(void);
+static void show_file(const char *filename, const char *title, int r, int c);
 
 static void init_wsize(void)
 {
 	struct winsize ws;
 	char *env;
 
-	if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
-		rows = 24;
-		cols = 80;
-	} else {
+	if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
 		rows = ws.ws_row;
 		cols = ws.ws_col;
-		if (!rows) {
-			env = getenv("LINES");
-			if (env)
-				rows = atoi(env);
-			if (!rows)
-				rows = 24;
-		}
-		if (!cols) {
-			env = getenv("COLUMNS");
-			if (env)
-				cols = atoi(env);
-			if (!cols)
-				cols = 80;
-		}
+	}
+
+	if (!rows) {
+		env = getenv("LINES");
+		if (env)
+			rows = atoi(env);
+		if (!rows)
+			rows = 24;
+	}
+	if (!cols) {
+		env = getenv("COLUMNS");
+		if (env)
+			cols = atoi(env);
+		if (!cols)
+			cols = 80;
 	}
 
 	if (rows < 19 || cols < 80) {
@@ -214,6 +371,103 @@
 	item_no = 0;
 }
 
+static void get_prompt_str(struct gstr *r, struct property *prop)
+{
+	int i, j;
+	struct menu *submenu[8], *menu;
+
+	str_printf(r, "Prompt: %s\n", prop->text);
+	str_printf(r, "  Defined at %s:%d\n", prop->menu->file->name,
+		prop->menu->lineno);
+	if (!expr_is_yes(prop->visible.expr)) {
+		str_append(r, "  Depends on: ");
+		expr_gstr_print(prop->visible.expr, r);
+		str_append(r, "\n");
+	}
+	menu = prop->menu->parent;
+	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
+		submenu[i++] = menu;
+	if (i > 0) {
+		str_printf(r, "  Location:\n");
+		for (j = 4; --i >= 0; j += 2) {
+			menu = submenu[i];
+			str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
+			if (menu->sym) {
+				str_printf(r, " (%s [=%s])", menu->sym->name ?
+					menu->sym->name : "<choice>",
+					sym_get_string_value(menu->sym));
+			}
+			str_append(r, "\n");
+		}
+	}
+}
+
+static void get_symbol_str(struct gstr *r, struct symbol *sym)
+{
+	bool hit;
+	struct property *prop;
+
+	str_printf(r, "Symbol: %s [=%s]\n", sym->name,
+	                               sym_get_string_value(sym));
+	for_all_prompts(sym, prop)
+		get_prompt_str(r, prop);
+	hit = false;
+	for_all_properties(sym, prop, P_SELECT) {
+		if (!hit) {
+			str_append(r, "  Selects: ");
+			hit = true;
+		} else
+			str_printf(r, " && ");
+		expr_gstr_print(prop->expr, r);
+	}
+	if (hit)
+		str_append(r, "\n");
+	if (sym->rev_dep.expr) {
+		str_append(r, "  Selected by: ");
+		expr_gstr_print(sym->rev_dep.expr, r);
+		str_append(r, "\n");
+	}
+	str_append(r, "\n\n");
+}
+
+static struct gstr get_relations_str(struct symbol **sym_arr)
+{
+	struct symbol *sym;
+	struct gstr res = str_new();
+	int i;
+
+	for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
+		get_symbol_str(&res, sym);
+	if (!i)
+		str_append(&res, "No matches found.\n");
+	return res;
+}
+
+static void search_conf(void)
+{
+	struct symbol **sym_arr;
+	struct gstr res;
+
+again:
+	switch (dialog_inputbox("Search Configuration Parameter",
+				"Enter Keyword", 10, 75,
+				NULL)) {
+	case 0:
+		break;
+	case 1:
+		show_helptext("Search Configuration", search_help);
+		goto again;
+	default:
+		return;
+	}
+
+	sym_arr = sym_re_search(dialog_input_result);
+	res = get_relations_str(sym_arr);
+	free(sym_arr);
+	show_textbox("Search Results", str_get(&res), 0, 0);
+	str_free(&res);
+}
+
 static void build_conf(struct menu *menu)
 {
 	struct symbol *sym;
@@ -308,6 +562,11 @@
 			return;
 		}
 	} else {
+		if (menu == current_menu) {
+			cprint_tag(":%p", menu);
+			cprint_name("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+			goto conf_childs;
+		}
 		child_count++;
 		val = sym_get_tristate_value(sym);
 		if (sym_is_choice_value(sym) && val == yes) {
@@ -376,7 +635,7 @@
 	while (1) {
 		indent = 0;
 		child_count = 0;
-  		current_menu = menu;
+		current_menu = menu;
 		cdone(); cinit();
 		build_conf(menu);
 		if (!child_count)
@@ -441,7 +700,7 @@
 			if (sym)
 				show_help(submenu);
 			else
-				show_readme();
+				show_helptext("README", mconf_readme);
 			break;
 		case 3:
 			if (type == 't') {
@@ -465,6 +724,9 @@
 			else if (type == 'm')
 				conf(submenu);
 			break;
+		case 7:
+			search_conf();
+			break;
 		}
 	}
 }
@@ -476,37 +738,39 @@
 	fd = creat(".help.tmp", 0777);
 	write(fd, text, strlen(text));
 	close(fd);
-	while (dialog_textbox(title, ".help.tmp", r, c) < 0)
-		;
+	show_file(".help.tmp", title, r, c);
 	unlink(".help.tmp");
 }
 
 static void show_helptext(const char *title, const char *text)
 {
-	show_textbox(title, text, rows, cols);
+	show_textbox(title, text, 0, 0);
 }
 
 static void show_help(struct menu *menu)
 {
-	const char *help;
-	char *helptext;
+	struct gstr help = str_new();
 	struct symbol *sym = menu->sym;
 
-	help = sym->help;
-	if (!help)
-		help = nohelp_text;
-	if (sym->name) {
-		helptext = malloc(strlen(sym->name) + strlen(help) + 16);
-		sprintf(helptext, "%s:\n\n%s", sym->name, help);
-		show_helptext(menu_get_prompt(menu), helptext);
-		free(helptext);
-	} else
-		show_helptext(menu_get_prompt(menu), help);
+	if (sym->help)
+	{
+		if (sym->name) {
+			str_printf(&help, "%s:\n\n", sym->name);
+			str_append(&help, sym->help);
+			str_append(&help, "\n");
+		}
+	} else {
+		str_append(&help, nohelp_text);
+	}
+	get_symbol_str(&help, sym);
+	show_helptext(menu_get_prompt(menu), str_get(&help));
+	str_free(&help);
 }
 
-static void show_readme(void)
+static void show_file(const char *filename, const char *title, int r, int c)
 {
-	show_helptext("Help", top_menu_help);
+	while (dialog_textbox(title, filename, r ? r : rows, c ? c : cols) < 0)
+		;
 }
 
 static void conf_choice(struct menu *menu)
@@ -667,9 +931,9 @@
 
 int main(int ac, char **av)
 {
-	int stat;
-	char *mode;
 	struct symbol *sym;
+	char *mode;
+	int stat;
 
 	conf_parse(av[1]);
 	conf_read(NULL);
@@ -697,7 +961,7 @@
 	init_dialog();
 	do {
 		stat = dialog_yesno(NULL,
-				"Do you wish to save your new BusyBox configuration?", 5, 60);
+				    "Do you wish to save your new BusyBox configuration?", 5, 60);
 	} while (stat < 0);
 	end_dialog();
 
diff --git a/scripts/config/menu.c b/scripts/config/menu.c
index 6425296..0c13156 100644
--- a/scripts/config/menu.c
+++ b/scripts/config/menu.c
@@ -10,7 +10,6 @@
 #include "lkc.h"
 
 struct menu rootmenu;
-struct menu *current_menu, *current_entry;
 static struct menu **last_entry_ptr;
 
 struct file *file_list;
@@ -389,43 +388,3 @@
 	return menu;
 }
 
-struct file *file_lookup(const char *name)
-{
-	struct file *file;
-
-	for (file = file_list; file; file = file->next) {
-		if (!strcmp(name, file->name))
-			return file;
-	}
-
-	file = malloc(sizeof(*file));
-	memset(file, 0, sizeof(*file));
-	file->name = strdup(name);
-	file->next = file_list;
-	file_list = file;
-	return file;
-}
-
-int file_write_dep(const char *name)
-{
-	struct file *file;
-	FILE *out;
-
-	if (!name)
-		name = ".config.cmd";
-	out = fopen(".config.tmp", "w");
-	if (!out)
-		return 1;
-	fprintf(out, "deps_config := \\\n");
-	for (file = file_list; file; file = file->next) {
-		if (file->next)
-			fprintf(out, "\t%s \\\n", file->name);
-		else
-			fprintf(out, "\t%s\n", file->name);
-	}
-	fprintf(out, "\n.config include/config.h: $(deps_config)\n\n$(deps_config):\n");
-	fclose(out);
-	rename(".config.tmp", name);
-	return 0;
-}
-
diff --git a/scripts/config/symbol.c b/scripts/config/symbol.c
index a9fae9c..ea62972 100644
--- a/scripts/config/symbol.c
+++ b/scripts/config/symbol.c
@@ -6,6 +6,7 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
+#include <regex.h>
 #include <sys/utsname.h>
 
 #define LKC_DIRECT_LINK
@@ -414,7 +415,7 @@
 
 bool sym_string_valid(struct symbol *sym, const char *str)
 {
-	char ch;
+	signed char ch;
 
 	switch (sym->type) {
 	case S_STRING:
@@ -649,6 +650,43 @@
 	return symbol;
 }
 
+struct symbol **sym_re_search(const char *pattern)
+{
+	struct symbol *sym, **sym_arr = NULL;
+	int i, cnt, size;
+	regex_t re;
+
+	cnt = size = 0;
+	/* Skip if empty */
+	if (strlen(pattern) == 0)
+		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;
+			}
+		}
+		sym_arr[cnt++] = sym;
+	}
+	if (sym_arr)
+		sym_arr[cnt] = NULL;
+	regfree(&re);
+
+	return sym_arr;
+}
+
+
 struct symbol *sym_check_deps(struct symbol *sym);
 
 static struct symbol *sym_check_expr_deps(struct expr *e)
diff --git a/scripts/config/util.c b/scripts/config/util.c
index 0a2f827..a72f5ea 100644
--- a/scripts/config/util.c
+++ b/scripts/config/util.c
@@ -1,375 +1,109 @@
 /*
- *  util.c
+ * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
+ * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
  *
- *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version 2
- *  of the License, or (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Released under the terms of the GNU GPL v2.0.
  */
 
-#include "dialog.h"
+#include <string.h>
+#include "lkc.h"
 
-
-/* use colors by default? */
-bool use_colors = 1;
-
-char *backtitle = NULL;
-
-const char *dialog_result;
-
-/*
- * Attribute values, default is for mono display
- */
-chtype attributes[] =
+/* file already present in list? If not add it */
+struct file *file_lookup(const char *name)
 {
-    A_NORMAL,			/* screen_attr */
-    A_NORMAL,			/* shadow_attr */
-    A_NORMAL,			/* dialog_attr */
-    A_BOLD,			/* title_attr */
-    A_NORMAL,			/* border_attr */
-    A_REVERSE,			/* button_active_attr */
-    A_DIM,			/* button_inactive_attr */
-    A_REVERSE,			/* button_key_active_attr */
-    A_BOLD,			/* button_key_inactive_attr */
-    A_REVERSE,			/* button_label_active_attr */
-    A_NORMAL,			/* button_label_inactive_attr */
-    A_NORMAL,			/* inputbox_attr */
-    A_NORMAL,			/* inputbox_border_attr */
-    A_NORMAL,			/* searchbox_attr */
-    A_BOLD,			/* searchbox_title_attr */
-    A_NORMAL,			/* searchbox_border_attr */
-    A_BOLD,			/* position_indicator_attr */
-    A_NORMAL,			/* menubox_attr */
-    A_NORMAL,			/* menubox_border_attr */
-    A_NORMAL,			/* item_attr */
-    A_REVERSE,			/* item_selected_attr */
-    A_BOLD,			/* tag_attr */
-    A_REVERSE,			/* tag_selected_attr */
-    A_BOLD,			/* tag_key_attr */
-    A_REVERSE,			/* tag_key_selected_attr */
-    A_BOLD,			/* check_attr */
-    A_REVERSE,			/* check_selected_attr */
-    A_BOLD,			/* uarrow_attr */
-    A_BOLD			/* darrow_attr */
-};
+	struct file *file;
 
-
-#include "colors.h"
-
-/*
- * Table of color values
- */
-int color_table[][3] =
-{
-    {SCREEN_FG, SCREEN_BG, SCREEN_HL},
-    {SHADOW_FG, SHADOW_BG, SHADOW_HL},
-    {DIALOG_FG, DIALOG_BG, DIALOG_HL},
-    {TITLE_FG, TITLE_BG, TITLE_HL},
-    {BORDER_FG, BORDER_BG, BORDER_HL},
-    {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
-    {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
-    {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
-    {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
-    {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL},
-    {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
-     BUTTON_LABEL_INACTIVE_HL},
-    {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
-    {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
-    {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
-    {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
-    {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
-    {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
-    {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
-    {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
-    {ITEM_FG, ITEM_BG, ITEM_HL},
-    {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
-    {TAG_FG, TAG_BG, TAG_HL},
-    {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
-    {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
-    {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
-    {CHECK_FG, CHECK_BG, CHECK_HL},
-    {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
-    {UARROW_FG, UARROW_BG, UARROW_HL},
-    {DARROW_FG, DARROW_BG, DARROW_HL},
-};				/* color_table */
-
-/*
- * Set window to attribute 'attr'
- */
-void
-attr_clear (WINDOW * win, int height, int width, chtype attr)
-{
-    int i, j;
-
-    wattrset (win, attr);
-    for (i = 0; i < height; i++) {
-	wmove (win, i, 0);
-	for (j = 0; j < width; j++)
-	    waddch (win, ' ');
-    }
-    touchwin (win);
-}
-
-void dialog_clear (void)
-{
-    attr_clear (stdscr, LINES, COLS, screen_attr);
-    /* Display background title if it exists ... - SLH */
-    if (backtitle != NULL) {
-        int i;
-
-        wattrset (stdscr, screen_attr);
-        mvwaddstr (stdscr, 0, 1, (char *)backtitle);
-        wmove (stdscr, 1, 1);
-        for (i = 1; i < COLS - 1; i++)
-            waddch (stdscr, ACS_HLINE);
-    }
-    wnoutrefresh (stdscr);
-}
-
-/*
- * Do some initialization for dialog
- */
-void
-init_dialog (void)
-{
-    initscr ();			/* Init curses */
-    keypad (stdscr, TRUE);
-    cbreak ();
-    noecho ();
-
-
-    if (use_colors)	/* Set up colors */
-	color_setup ();
-
-
-    dialog_clear ();
-}
-
-/*
- * Setup for color display
- */
-void
-color_setup (void)
-{
-    int i;
-
-    if (has_colors ()) {	/* Terminal supports color? */
-	start_color ();
-
-	/* Initialize color pairs */
-	for (i = 0; i < ATTRIBUTE_COUNT; i++)
-	    init_pair (i + 1, color_table[i][0], color_table[i][1]);
-
-	/* Setup color attributes */
-	for (i = 0; i < ATTRIBUTE_COUNT; i++)
-	    attributes[i] = C_ATTR (color_table[i][2], i + 1);
-    }
-}
-
-/*
- * End using dialog functions.
- */
-void
-end_dialog (void)
-{
-    endwin ();
-}
-
-
-/*
- * Print a string of text in a window, automatically wrap around to the
- * next line if the string is too long to fit on one line. Newline
- * characters '\n' are replaced by spaces.  We start on a new line
- * if there is no room for at least 4 nonblanks following a double-space.
- */
-void
-print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
-{
-    int newl, cur_x, cur_y;
-    int i, prompt_len, room, wlen;
-    char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
-
-    strcpy (tempstr, prompt);
-
-    prompt_len = strlen(tempstr);
-
-    /*
-     * Remove newlines
-     */
-    for(i=0; i<prompt_len; i++) {
-	if(tempstr[i] == '\n') tempstr[i] = ' ';
-    }
-
-    if (prompt_len <= width - x * 2) {	/* If prompt is short */
-	wmove (win, y, (width - prompt_len) / 2);
-	waddstr (win, tempstr);
-    } else {
-	cur_x = x;
-	cur_y = y;
-	newl = 1;
-	word = tempstr;
-	while (word && *word) {
-	    sp = index(word, ' ');
-	    if (sp)
-	        *sp++ = 0;
-
-	    /* Wrap to next line if either the word does not fit,
-	       or it is the first word of a new sentence, and it is
-	       short, and the next word does not fit. */
-	    room = width - cur_x;
-	    wlen = strlen(word);
-	    if (wlen > room ||
-	       (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
-		     && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
-		cur_y++;
-		cur_x = x;
-	    }
-	    wmove (win, cur_y, cur_x);
-	    waddstr (win, word);
-	    getyx (win, cur_y, cur_x);
-	    cur_x++;
-	    if (sp && *sp == ' ') {
-	        cur_x++;	/* double space */
-		while (*++sp == ' ');
-		newl = 1;
-	    } else
-	        newl = 0;
-	    word = sp;
-	}
-    }
-}
-
-/*
- * Print a button
- */
-void
-print_button (WINDOW * win, const char *label, int y, int x, int selected)
-{
-    int i, temp;
-
-    wmove (win, y, x);
-    wattrset (win, selected ? button_active_attr : button_inactive_attr);
-    waddstr (win, "<");
-    temp = strspn (label, " ");
-    label += temp;
-    wattrset (win, selected ? button_label_active_attr
-	      : button_label_inactive_attr);
-    for (i = 0; i < temp; i++)
-	waddch (win, ' ');
-    wattrset (win, selected ? button_key_active_attr
-	      : button_key_inactive_attr);
-    waddch (win, label[0]);
-    wattrset (win, selected ? button_label_active_attr
-	      : button_label_inactive_attr);
-    waddstr (win, (char *)label + 1);
-    wattrset (win, selected ? button_active_attr : button_inactive_attr);
-    waddstr (win, ">");
-    wmove (win, y, x + temp + 1);
-}
-
-/*
- * Draw a rectangular box with line drawing characters
- */
-void
-draw_box (WINDOW * win, int y, int x, int height, int width,
-	  chtype box, chtype border)
-{
-    int i, j;
-
-    wattrset (win, 0);
-    for (i = 0; i < height; i++) {
-	wmove (win, y + i, x);
-	for (j = 0; j < width; j++)
-	    if (!i && !j)
-		waddch (win, border | ACS_ULCORNER);
-	    else if (i == height - 1 && !j)
-		waddch (win, border | ACS_LLCORNER);
-	    else if (!i && j == width - 1)
-		waddch (win, box | ACS_URCORNER);
-	    else if (i == height - 1 && j == width - 1)
-		waddch (win, box | ACS_LRCORNER);
-	    else if (!i)
-		waddch (win, border | ACS_HLINE);
-	    else if (i == height - 1)
-		waddch (win, box | ACS_HLINE);
-	    else if (!j)
-		waddch (win, border | ACS_VLINE);
-	    else if (j == width - 1)
-		waddch (win, box | ACS_VLINE);
-	    else
-		waddch (win, box | ' ');
-    }
-}
-
-/*
- * Draw shadows along the right and bottom edge to give a more 3D look
- * to the boxes
- */
-void
-draw_shadow (WINDOW * win, int y, int x, int height, int width)
-{
-    int i;
-
-    if (has_colors ()) {	/* Whether terminal supports color? */
-	wattrset (win, shadow_attr);
-	wmove (win, y + height, x + 2);
-	for (i = 0; i < width; i++)
-	    waddch (win, winch (win) & A_CHARTEXT);
-	for (i = y + 1; i < y + height + 1; i++) {
-	    wmove (win, i, x + width);
-	    waddch (win, winch (win) & A_CHARTEXT);
-	    waddch (win, winch (win) & A_CHARTEXT);
-	}
-	wnoutrefresh (win);
-    }
-}
-
-/*
- *  Return the position of the first alphabetic character in a string.
- */
-int
-first_alpha(const char *string, const char *exempt)
-{
-	int i, in_paren=0, c;
-
-	for (i = 0; i < strlen(string); i++) {
-		c = tolower(string[i]);
-
-		if (strchr("<[(", c)) ++in_paren;
-		if (strchr(">])", c) && in_paren > 0) --in_paren;
-
-		if ((! in_paren) && isalpha(c) &&
-		     strchr(exempt, c) == 0)
-			return i;
+	for (file = file_list; file; file = file->next) {
+		if (!strcmp(name, file->name))
+			return file;
 	}
 
+	file = malloc(sizeof(*file));
+	memset(file, 0, sizeof(*file));
+	file->name = strdup(name);
+	file->next = file_list;
+	file_list = file;
+	return file;
+}
+
+/* write a dependency file as used by kbuild to track dependencies */
+int file_write_dep(const char *name)
+{
+	struct file *file;
+	FILE *out;
+
+	if (!name)
+		name = ".config.cmd";
+	out = fopen(".config.tmp", "w");
+	if (!out)
+		return 1;
+	fprintf(out, "deps_config := \\\n");
+	for (file = file_list; file; file = file->next) {
+		if (file->next)
+			fprintf(out, "\t%s \\\n", file->name);
+		else
+			fprintf(out, "\t%s\n", file->name);
+	}
+	fprintf(out, "\n.config include/config.h: $(deps_config)\n\n$(deps_config):\n");
+	fclose(out);
+	rename(".config.tmp", name);
 	return 0;
 }
 
-/*
- * Get the first selected item in the dialog_list_item list.
- */
-struct dialog_list_item *
-first_sel_item(int item_no, struct dialog_list_item ** items)
+
+/* Allocate initial growable sting */
+struct gstr str_new(void)
 {
-	int i;
-
-	for (i = 0; i < item_no; i++) {
-		if (items[i]->selected)
-			return items[i];
-	}
-
-	return NULL;
+	struct gstr gs;
+	gs.s = malloc(sizeof(char) * 64);
+	gs.len = 16;
+	strcpy(gs.s, "\0");
+	return gs;
 }
+
+/* Allocate and assign growable string */
+struct gstr str_assign(const char *s)
+{
+	struct gstr gs;
+	gs.s = strdup(s);
+	gs.len = strlen(s) + 1;
+	return gs;
+}
+
+/* Free storage for growable string */
+void str_free(struct gstr *gs)
+{
+	if (gs->s)
+		free(gs->s);
+	gs->s = NULL;
+	gs->len = 0;
+}
+
+/* Append to growable string */
+void str_append(struct gstr *gs, const char *s)
+{
+	size_t l = strlen(gs->s) + strlen(s) + 1;
+	if (l > gs->len) {
+		gs->s   = realloc(gs->s, l);
+		gs->len = l;
+	}
+	strcat(gs->s, s);
+}
+
+/* Append printf formatted string to growable string */
+void str_printf(struct gstr *gs, const char *fmt, ...)
+{
+	va_list ap;
+	char s[10000]; /* big enough... */
+	va_start(ap, fmt);
+	vsnprintf(s, sizeof(s), fmt, ap);
+	str_append(gs, s);
+	va_end(ap);
+}
+
+/* Retreive value of growable string */
+const char *str_get(struct gstr *gs)
+{
+	return gs->s;
+}
+
diff --git a/scripts/config/zconf.tab.c_shipped b/scripts/config/zconf.tab.c_shipped
index bc2225f..be6bd4c 100644
--- a/scripts/config/zconf.tab.c_shipped
+++ b/scripts/config/zconf.tab.c_shipped
@@ -175,6 +175,8 @@
 
 struct symbol *symbol_hash[257];
 
+static struct menu *current_menu, *current_entry;
+
 #define YYERROR_VERBOSE
 
 
@@ -2119,6 +2121,7 @@
 }
 
 #include "lex.zconf.c"
+#include "util.c"
 #include "confdata.c"
 #include "expr.c"
 #include "symbol.c"
diff --git a/scripts/config/zconf.y b/scripts/config/zconf.y
index 658495c..5ebaf0a 100644
--- a/scripts/config/zconf.y
+++ b/scripts/config/zconf.y
@@ -25,6 +25,8 @@
 
 struct symbol *symbol_hash[257];
 
+static struct menu *current_menu, *current_entry;
+
 #define YYERROR_VERBOSE
 %}
 %expect 40
@@ -681,6 +683,7 @@
 }
 
 #include "lex.zconf.c"
+#include "util.c"
 #include "confdata.c"
 #include "expr.c"
 #include "symbol.c"