Преглед изворни кода

- pull kconfig from linux-2.6.21.5

Bernhard Reutner-Fischer пре 18 година
родитељ
комит
a665ed3496
36 измењених фајлова са 10375 додато и 4905 уклоњено
  1. 28 124
      package/config/Makefile
  2. 278 0
      package/config/Makefile.kconfig
  3. 5 0
      package/config/POTFILES.in
  4. 18 0
      package/config/README.buildroot2
  5. 65 21
      package/config/conf.c
  6. 481 91
      package/config/confdata.c
  7. 27 26
      package/config/expr.c
  8. 14 7
      package/config/expr.h
  9. 1636 0
      package/config/gconf.c
  10. 648 0
      package/config/gconf.glade
  11. 326 0
      package/config/images.c
  12. 453 0
      package/config/kconfig-to-buildroot2.patch
  13. 35 0
      package/config/kconfig_load.c
  14. 227 0
      package/config/kxgettext.c
  15. 318 1656
      package/config/lex.zconf.c_shipped
  16. 36 6
      package/config/lkc.h
  17. 5 2
      package/config/lkc_proto.h
  18. 84 0
      package/config/lxdialog/check-lxdialog.sh
  19. 270 317
      package/config/lxdialog/checklist.c
  20. 116 91
      package/config/lxdialog/dialog.h
  21. 196 198
      package/config/lxdialog/inputbox.c
  22. 334 338
      package/config/lxdialog/menubox.c
  23. 316 481
      package/config/lxdialog/textbox.c
  24. 530 265
      package/config/lxdialog/util.c
  25. 76 80
      package/config/lxdialog/yesno.c
  26. 228 277
      package/config/mconf.c
  27. 43 14
      package/config/menu.c
  28. 1753 0
      package/config/qconf.cc
  29. 334 0
      package/config/qconf.h
  30. 109 37
      package/config/symbol.c
  31. 8 5
      package/config/util.c
  32. 46 0
      package/config/zconf.gperf
  33. 242 0
      package/config/zconf.hash.c_shipped
  34. 40 56
      package/config/zconf.l
  35. 859 644
      package/config/zconf.tab.c_shipped
  36. 191 169
      package/config/zconf.y

+ 28 - 124
package/config/Makefile

@@ -1,134 +1,38 @@
-# Makefile for buildroot2
-#
-# Copyright (C) 2002-2005 Erik Andersen <andersen@codepoet.org>
-#
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU Library 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 Library General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Library General Public License
-# along with this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+obj := .
+src := .
+top_srcdir=../../
+top_builddir=../../
+srctree := .
 
 
-# Select the compiler needed to build binaries for your development system
-HOSTCC    = gcc
-HOSTCFLAGS= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
-# Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc.
-LC_ALL:= C
+include Makefile.kconfig
 
 
-all: ncurses conf mconf
+-include .depend
+.depend: $(wildcard *.h *.c)
+	$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) -MM *.c > .depend 2>/dev/null || :
 
 
-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
-ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
-	HOSTNCURSES += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
-else
-ifeq (/usr/local/include/ncurses/ncurses.h, $(wildcard /usr/local/include/ncurses/ncurses.h))
-	HOSTCFLAGS += -I/usr/local/include/ncurses -DCURSES_LOC="<ncurses.h>"
-else
-ifeq (/usr/local/include/ncurses/curses.h, $(wildcard /usr/local/include/ncurses/curses.h))
-	HOSTCFLAGS += -I/usr/local/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
-else
-ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
-	HOSTNCURSES += -DCURSES_LOC="<ncurses.h>"
-else
-	HOSTNCURSES += -DCURSES_LOC="<curses.h>"
-endif
-endif
-endif
-endif
-endif
+__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
+host-csingle    := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m)))
+host-cmulti := $(foreach m,$(__hostprogs),\
+           $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
+host-cobjs  := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
 
 
-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 := lkc.h lkc_proto.h lkc_defs.h 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))
+$(host-csingle): %: %.c
+	$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$@) $(HOST_LOADLIBES) $< -o $@
 
 
-conf: $(CONF_OBJS) $(SHARED_OBJS)
-	$(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@
+$(host-cmulti): %: $(host-cobjs) $(host-cshlib)
+	$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$@) $(HOST_LOADLIBES) $($@-objs) -o $@
 
 
-mconf: $(MCONF_OBJS) $(SHARED_OBJS)
-	$(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@ $(LIBS)
+$(host-cobjs): %.o: %.c
+	$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$@) -c $< -o $@
 
 
-$(CONF_OBJS): %.o : %.c $(SHARED_DEPS)
-	$(HOSTCC) $(HOSTCFLAGS) -I. -c $< -o $@
-
-$(MCONF_OBJS): %.o : %.c $(SHARED_DEPS)
-	$(HOSTCC) $(HOSTCFLAGS) $(HOSTNCURSES) -I. -c $< -o $@
-
-lkc_defs.h: lkc_proto.h
-	@sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
-
-###
-# The following requires flex/bison
-# By default we use the _shipped versions, uncomment the
-# following line if you are modifying the flex/bison src.
-#LKC_GENPARSER := 1
-
-ifdef LKC_GENPARSER
-
-%.tab.c %.tab.h: %.y
-	bison -t -d -v -b $* -p $(notdir $*) $<
-
-lex.%.c: %.l
-	flex -P$(notdir $*) -o$@ $<
-else
-
-lex.zconf.o: lex.zconf.c $(SHARED_DEPS)
-	$(HOSTCC) $(HOSTCFLAGS) -I. -c $< -o $@
-
-lex.zconf.c: lex.zconf.c_shipped
-	cp lex.zconf.c_shipped lex.zconf.c
-
-zconf.tab.o: zconf.tab.c lex.zconf.c confdata.c expr.c symbol.c menu.c $(SHARED_DEPS)
-	$(HOSTCC) $(HOSTCFLAGS) -I. -c $< -o $@
-
-zconf.tab.c: zconf.tab.c_shipped
-	cp zconf.tab.c_shipped zconf.tab.c
-
-zconf.tab.h: zconf.tab.h_shipped
-	cp zconf.tab.h_shipped zconf.tab.h
-endif
-
-.PHONY: ncurses
-
-ncurses:
-	@echo "main() {}" > lxtemp.c
-	@if $(HOSTCC) lxtemp.c $(LIBS) ; then \
-		$(RM) lxtemp.c a.out; \
-	else \
-		$(RM) lxtemp.c; \
-		/bin/echo -e "\007" ;\
-		echo ">> Unable to find the Ncurses libraries." ;\
-		echo ">>" ;\
-		echo ">> You must have Ncurses installed in order" ;\
-		echo ">> to use 'make menuconfig'" ;\
-		echo ">>" ;\
-		echo ">> Maybe you want to try 'make config', which" ;\
-		echo ">> doesn't depend on the Ncurses libraries." ;\
-		echo ;\
-		exit 1 ;\
-	fi
+$(obj)/%:: $(src)/%_shipped
+	$(Q)cat $< > $@
 
 
 clean:
 clean:
-	$(RM) *.o *~ core $(TARGETS) $(MCONF_OBJS) $(CONF_OBJS) \
-		conf mconf zconf.tab.c zconf.tab.h lex.zconf.c lkc_defs.h
+	$(Q)rm -f $(clean-files)
+distclean: clean
+	$(Q)rm -f $(lxdialog) $(conf-objs) $(mconf-objs) $(kxgettext-objs) \
+		$(hostprogs-y) $(qconf-cxxobjs) $(qconf-objs) $(gconf-objs)
 
 
+FORCE:
+.PHONY: FORCE clean distclean

+ 278 - 0
package/config/Makefile.kconfig

@@ -0,0 +1,278 @@
+# ===========================================================================
+# Kernel configuration targets
+# These targets are used from top-level makefile
+
+PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config
+
+xconfig: $(obj)/qconf
+	$< arch/$(ARCH)/Kconfig
+
+gconfig: $(obj)/gconf
+	$< arch/$(ARCH)/Kconfig
+
+menuconfig: $(obj)/mconf
+	$< arch/$(ARCH)/Kconfig
+
+config: $(obj)/conf
+	$< arch/$(ARCH)/Kconfig
+
+oldconfig: $(obj)/conf
+	$< -o arch/$(ARCH)/Kconfig
+
+silentoldconfig: $(obj)/conf
+	$< -s arch/$(ARCH)/Kconfig
+
+update-po-config: $(obj)/kxgettext
+	xgettext --default-domain=linux \
+          --add-comments --keyword=_ --keyword=N_ \
+          --files-from=scripts/kconfig/POTFILES.in \
+          --output scripts/kconfig/config.pot
+	$(Q)ln -fs Kconfig_i386 arch/um/Kconfig_arch
+	$(Q)for i in `ls arch/`; \
+	do \
+	  scripts/kconfig/kxgettext arch/$$i/Kconfig \
+	    | msguniq -o scripts/kconfig/linux_$${i}.pot; \
+	done
+	$(Q)msgcat scripts/kconfig/config.pot \
+	  `find scripts/kconfig/ -type f -name linux_*.pot` \
+	  --output scripts/kconfig/linux_raw.pot
+	$(Q)msguniq --sort-by-file scripts/kconfig/linux_raw.pot \
+	    --output scripts/kconfig/linux.pot
+	$(Q)rm -f arch/um/Kconfig_arch
+	$(Q)rm -f scripts/kconfig/linux_*.pot scripts/kconfig/config.pot
+
+PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig
+
+randconfig: $(obj)/conf
+	$< -r arch/$(ARCH)/Kconfig
+
+allyesconfig: $(obj)/conf
+	$< -y arch/$(ARCH)/Kconfig
+
+allnoconfig: $(obj)/conf
+	$< -n arch/$(ARCH)/Kconfig
+
+allmodconfig: $(obj)/conf
+	$< -m arch/$(ARCH)/Kconfig
+
+defconfig: $(obj)/conf
+ifeq ($(KBUILD_DEFCONFIG),)
+	$< -d arch/$(ARCH)/Kconfig
+else
+	@echo *** Default configuration is based on '$(KBUILD_DEFCONFIG)'
+	$(Q)$< -D arch/$(ARCH)/configs/$(KBUILD_DEFCONFIG) arch/$(ARCH)/Kconfig
+endif
+
+%_defconfig: $(obj)/conf
+	$(Q)$< -D arch/$(ARCH)/configs/$@ arch/$(ARCH)/Kconfig
+
+# Help text used by make help
+help:
+	@echo  '  config	  - Update current config utilising a line-oriented program'
+	@echo  '  menuconfig	  - Update current config utilising a menu based program'
+	@echo  '  xconfig	  - Update current config utilising a QT based front-end'
+	@echo  '  gconfig	  - Update current config utilising a GTK based front-end'
+	@echo  '  oldconfig	  - Update current config utilising a provided .config as base'
+	@echo  '  silentoldconfig - Same as oldconfig, but quietly'
+	@echo  '  randconfig	  - New config with random answer to all options'
+	@echo  '  defconfig	  - New config with default answer to all options'
+	@echo  '  allmodconfig	  - New config selecting modules when possible'
+	@echo  '  allyesconfig	  - New config where all options are accepted with yes'
+	@echo  '  allnoconfig	  - New config where all options are answered with no'
+
+# lxdialog stuff
+check-lxdialog  := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
+
+# Use reursively expanded variables so we do not call gcc unless
+# we really need to do so. (Do not call gcc as part of make mrproper)
+HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
+HOST_LOADLIBES   = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
+
+HOST_EXTRACFLAGS += -DLOCALE
+
+PHONY += $(obj)/dochecklxdialog
+$(obj)/dochecklxdialog:
+	$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES)
+
+always := dochecklxdialog
+
+
+# ===========================================================================
+# Shared Makefile for the various kconfig executables:
+# conf:	  Used for defconfig, oldconfig and related targets
+# mconf:  Used for the mconfig target.
+#         Utilizes the lxdialog package
+# qconf:  Used for the xconfig target
+#         Based on QT which needs to be installed to compile it
+# gconf:  Used for the gconfig target
+#         Based on GTK which needs to be installed to compile it
+# object files used by all kconfig flavours
+
+lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
+lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
+
+conf-objs	:= conf.o  zconf.tab.o
+mconf-objs	:= mconf.o zconf.tab.o $(lxdialog)
+kxgettext-objs	:= kxgettext.o zconf.tab.o
+
+hostprogs-y := conf qconf gconf kxgettext
+
+ifeq ($(MAKECMDGOALS),menuconfig)
+	hostprogs-y += mconf
+endif
+
+ifeq ($(MAKECMDGOALS),xconfig)
+	qconf-target := 1
+endif
+ifeq ($(MAKECMDGOALS),gconfig)
+	gconf-target := 1
+endif
+
+
+ifeq ($(qconf-target),1)
+qconf-cxxobjs	:= qconf.o
+qconf-objs	:= kconfig_load.o zconf.tab.o
+endif
+
+ifeq ($(gconf-target),1)
+gconf-objs	:= gconf.o kconfig_load.o zconf.tab.o
+endif
+
+clean-files	:= lkc_defs.h qconf.moc .tmp_qtcheck \
+		   .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c
+
+# Needed for systems without gettext
+KBUILD_HAVE_NLS := $(shell \
+     if echo "\#include <libintl.h>" | $(HOSTCC) $(HOSTCFLAGS) -E - > /dev/null 2>&1 ; \
+     then echo yes ; \
+     else echo no ; fi)
+ifeq ($(KBUILD_HAVE_NLS),no)
+HOSTCFLAGS	+= -DKBUILD_NO_NLS
+endif
+
+# generated files seem to need this to find local include files
+HOSTCFLAGS_lex.zconf.o	:= -I$(src)
+HOSTCFLAGS_zconf.tab.o	:= -I$(src)
+
+HOSTLOADLIBES_qconf	= $(KC_QT_LIBS) -ldl
+HOSTCXXFLAGS_qconf.o	= $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
+
+HOSTLOADLIBES_gconf	= `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
+HOSTCFLAGS_gconf.o	= `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
+                          -D LKC_DIRECT_LINK
+
+$(obj)/qconf.o: $(obj)/.tmp_qtcheck
+
+ifeq ($(qconf-target),1)
+$(obj)/.tmp_qtcheck: $(src)/Makefile
+-include $(obj)/.tmp_qtcheck
+
+# QT needs some extra effort...
+$(obj)/.tmp_qtcheck:
+	@set -e; echo "  CHECK   qt"; dir=""; pkg=""; \
+	pkg-config --exists qt 2> /dev/null && pkg=qt; \
+	pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \
+	if [ -n "$$pkg" ]; then \
+	  cflags="\$$(shell pkg-config $$pkg --cflags)"; \
+	  libs="\$$(shell pkg-config $$pkg --libs)"; \
+	  moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \
+	  dir="$$(pkg-config $$pkg --variable=prefix)"; \
+	else \
+	  for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \
+	    if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
+	  done; \
+	  if [ -z "$$dir" ]; then \
+	    echo "*"; \
+	    echo "* Unable to find the QT installation. Please make sure that"; \
+	    echo "* the QT development package is correctly installed and"; \
+	    echo "* either install pkg-config or set the QTDIR environment"; \
+	    echo "* variable to the correct location."; \
+	    echo "*"; \
+	    false; \
+	  fi; \
+	  libpath=$$dir/lib; lib=qt; osdir=""; \
+	  $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \
+	    osdir=x$$($(HOSTCXX) -print-multi-os-directory); \
+	  test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \
+	  test -f $$libpath/libqt-mt.so && lib=qt-mt; \
+	  cflags="-I$$dir/include"; \
+	  libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \
+	  moc="$$dir/bin/moc"; \
+	fi; \
+	if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \
+	  echo "*"; \
+	  echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \
+	  echo "*"; \
+	  moc="/usr/bin/moc"; \
+	fi; \
+	echo "KC_QT_CFLAGS=$$cflags" > $@; \
+	echo "KC_QT_LIBS=$$libs" >> $@; \
+	echo "KC_QT_MOC=$$moc" >> $@
+endif
+
+$(obj)/gconf.o: $(obj)/.tmp_gtkcheck
+
+ifeq ($(gconf-target),1)
+-include $(obj)/.tmp_gtkcheck
+
+# GTK needs some extra effort, too...
+$(obj)/.tmp_gtkcheck:
+	@if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then		\
+		if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then			\
+			touch $@;								\
+		else									\
+			echo "*"; 							\
+			echo "* GTK+ is present but version >= 2.0.0 is required.";	\
+			echo "*";							\
+			false;								\
+		fi									\
+	else										\
+		echo "*"; 								\
+		echo "* Unable to find the GTK+ installation. Please make sure that"; 	\
+		echo "* the GTK+ 2.0 development package is correctly installed..."; 	\
+		echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; 		\
+		echo "*"; 								\
+		false;									\
+	fi
+endif
+
+$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c
+
+$(obj)/kconfig_load.o: $(obj)/lkc_defs.h
+
+$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h
+
+$(obj)/gconf.o: $(obj)/lkc_defs.h
+
+$(obj)/%.moc: $(src)/%.h
+	$(KC_QT_MOC) -i $< -o $@
+
+$(obj)/lkc_defs.h: $(src)/lkc_proto.h
+	sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
+
+
+###
+# The following requires flex/bison/gperf
+# By default we use the _shipped versions, uncomment the following line if
+# you are modifying the flex/bison src.
+# LKC_GENPARSER := 1
+
+ifdef LKC_GENPARSER
+
+$(obj)/zconf.tab.c: $(src)/zconf.y
+$(obj)/lex.zconf.c: $(src)/zconf.l
+$(obj)/zconf.hash.c: $(src)/zconf.gperf
+
+%.tab.c: %.y
+	bison -l -b $* -p $(notdir $*) $<
+	cp $@ $@_shipped
+
+lex.%.c: %.l
+	flex -L -P$(notdir $*) -o$@ $<
+	cp $@ $@_shipped
+
+%.hash.c: %.gperf
+	gperf < $< > $@
+	cp $@ $@_shipped
+
+endif

+ 5 - 0
package/config/POTFILES.in

@@ -0,0 +1,5 @@
+scripts/kconfig/mconf.c
+scripts/kconfig/conf.c
+scripts/kconfig/confdata.c
+scripts/kconfig/gconf.c
+scripts/kconfig/qconf.cc

+ 18 - 0
package/config/README.buildroot2

@@ -0,0 +1,18 @@
+This is a copy of the kconfig code in the kernel tweaked to suit Buildroot.
+
+To update:
+	cp -r /usr/src/linux/scripts/kconfig package/config.new
+	cd package/config.new
+	cp /usr/src/linux/Documentation/kbuild/kconfig-language.txt .
+	mv Makefile Makefile.kconfig
+	patch -p1 < ../config/kconfig-to-buildroot.patch
+	cp ../config/README.buildroot2 .
+	cd ..
+	rm -rf config
+	mv config.new config
+
+Then verify the toplevel targets work:
+	config
+	defconfig
+	menuconfig
+	oldconfig

+ 65 - 21
package/config/conf.c

@@ -5,6 +5,7 @@
 
 
 #include <ctype.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <string.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <time.h>
 #include <time.h>
@@ -31,14 +32,14 @@ char *defconfig_file;
 static int indent = 1;
 static int indent = 1;
 static int valid_stdin = 1;
 static int valid_stdin = 1;
 static int conf_cnt;
 static int conf_cnt;
-static signed char line[128];
+static char line[128];
 static struct menu *rootEntry;
 static struct menu *rootEntry;
 
 
-static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
+static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
 
 
-static void strip(signed char *str)
+static void strip(char *str)
 {
 {
-	signed char *p = str;
+	char *p = str;
 	int l;
 	int l;
 
 
 	while ((isspace(*p)))
 	while ((isspace(*p)))
@@ -56,9 +57,9 @@ static void strip(signed char *str)
 static void check_stdin(void)
 static void check_stdin(void)
 {
 {
 	if (!valid_stdin && input_mode == ask_silent) {
 	if (!valid_stdin && input_mode == ask_silent) {
-		printf("aborted!\n\n");
-		printf("Console input/output is redirected. ");
-		printf("Run 'make oldconfig' to update configuration.\n\n");
+		printf(_("aborted!\n\n"));
+		printf(_("Console input/output is redirected. "));
+		printf(_("Run 'make oldconfig' to update configuration.\n\n"));
 		exit(1);
 		exit(1);
 	}
 	}
 }
 }
@@ -82,6 +83,15 @@ static void conf_askvalue(struct symbol *sym, const char *def)
 	}
 	}
 
 
 	switch (input_mode) {
 	switch (input_mode) {
+	case set_no:
+	case set_mod:
+	case set_yes:
+	case set_random:
+		if (sym_has_value(sym)) {
+			printf("%s\n", def);
+			return;
+		}
+		break;
 	case ask_new:
 	case ask_new:
 	case ask_silent:
 	case ask_silent:
 		if (sym_has_value(sym)) {
 		if (sym_has_value(sym)) {
@@ -305,8 +315,7 @@ static int conf_choice(struct menu *menu)
 		printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
 		printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
 		def_sym = sym_get_choice_value(sym);
 		def_sym = sym_get_choice_value(sym);
 		cnt = def = 0;
 		cnt = def = 0;
-		line[0] = '0';
-		line[1] = 0;
+		line[0] = 0;
 		for (child = menu->list; child; child = child->next) {
 		for (child = menu->list; child; child = child->next) {
 			if (!menu_is_visible(child))
 			if (!menu_is_visible(child))
 				continue;
 				continue;
@@ -467,15 +476,14 @@ static void check_conf(struct menu *menu)
 		return;
 		return;
 
 
 	sym = menu->sym;
 	sym = menu->sym;
-	if (sym) {
-		if (sym_is_changable(sym) && !sym_has_value(sym)) {
+	if (sym && !sym_has_value(sym)) {
+		if (sym_is_changable(sym) ||
+		    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
 			if (!conf_cnt++)
 			if (!conf_cnt++)
-				printf("*\n* Restart config...\n*\n");
+				printf(_("*\n* Restart config...\n*\n"));
 			rootEntry = menu_get_parent_menu(menu);
 			rootEntry = menu_get_parent_menu(menu);
 			conf(rootEntry);
 			conf(rootEntry);
 		}
 		}
-		if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)
-			return;
 	}
 	}
 
 
 	for (child = menu->list; child; child = child->next)
 	for (child = menu->list; child; child = child->next)
@@ -504,7 +512,7 @@ int main(int ac, char **av)
 			input_mode = set_default;
 			input_mode = set_default;
 			defconfig_file = av[i++];
 			defconfig_file = av[i++];
 			if (!defconfig_file) {
 			if (!defconfig_file) {
-				printf("%s: No default config file specified\n",
+				printf(_("%s: No default config file specified\n"),
 					av[0]);
 					av[0]);
 				exit(1);
 				exit(1);
 			}
 			}
@@ -524,13 +532,14 @@ int main(int ac, char **av)
 			break;
 			break;
 		case 'h':
 		case 'h':
 		case '?':
 		case '?':
-			printf("%s [-o|-s] config\n", av[0]);
+			fprintf(stderr, "See README for usage info\n");
 			exit(0);
 			exit(0);
 		}
 		}
 	}
 	}
   	name = av[i];
   	name = av[i];
 	if (!name) {
 	if (!name) {
-		printf("%s: configuration file missing\n", av[0]);
+		printf(_("%s: Kconfig file missing\n"), av[0]);
+		exit(1);
 	}
 	}
 	conf_parse(name);
 	conf_parse(name);
 	//zconfdump(stdout);
 	//zconfdump(stdout);
@@ -547,18 +556,39 @@ int main(int ac, char **av)
 		break;
 		break;
 	case ask_silent:
 	case ask_silent:
 		if (stat(".config", &tmpstat)) {
 		if (stat(".config", &tmpstat)) {
-			printf("***\n"
+			printf(_("***\n"
 				"*** You have not yet configured Buildroot!\n"
 				"*** You have not yet configured Buildroot!\n"
 				"***\n"
 				"***\n"
 				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
 				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
 				"*** \"make menuconfig\" or \"make config\").\n"
 				"*** \"make menuconfig\" or \"make config\").\n"
-				"***\n");
+				"***\n"));
 			exit(1);
 			exit(1);
 		}
 		}
 	case ask_all:
 	case ask_all:
 	case ask_new:
 	case ask_new:
 		conf_read(NULL);
 		conf_read(NULL);
 		break;
 		break;
+	case set_no:
+	case set_mod:
+	case set_yes:
+	case set_random:
+		name = getenv("KCONFIG_ALLCONFIG");
+		if (name && !stat(name, &tmpstat)) {
+			conf_read_simple(name, S_DEF_USER);
+			break;
+		}
+		switch (input_mode) {
+		case set_no:	 name = "allno.config"; break;
+		case set_mod:	 name = "allmod.config"; break;
+		case set_yes:	 name = "allyes.config"; break;
+		case set_random: name = "allrandom.config"; break;
+		default: break;
+		}
+		if (!stat(name, &tmpstat))
+			conf_read_simple(name, S_DEF_USER);
+		else if (!stat("all.config", &tmpstat))
+			conf_read_simple("all.config", S_DEF_USER);
+		break;
 	default:
 	default:
 		break;
 		break;
 	}
 	}
@@ -570,14 +600,28 @@ int main(int ac, char **av)
 			input_mode = ask_silent;
 			input_mode = ask_silent;
 			valid_stdin = 1;
 			valid_stdin = 1;
 		}
 		}
-	}
+	} else if (conf_get_changed()) {
+		name = getenv("KCONFIG_NOSILENTUPDATE");
+		if (name && *name) {
+			fprintf(stderr, _("\n*** Buildroot configuration requires explicit update.\n\n"));
+			return 1;
+		}
+	} else
+		goto skip_check;
+
 	do {
 	do {
 		conf_cnt = 0;
 		conf_cnt = 0;
 		check_conf(&rootmenu);
 		check_conf(&rootmenu);
 	} while (conf_cnt);
 	} while (conf_cnt);
 	if (conf_write(NULL)) {
 	if (conf_write(NULL)) {
-		fprintf(stderr, "\n*** Error during writing of the Buildroot configuration.\n\n");
+		fprintf(stderr, _("\n*** Error during writing of the Buildroot configuration.\n\n"));
 		return 1;
 		return 1;
 	}
 	}
+skip_check:
+	if (/*input_mode == ask_silent &&*/ conf_write_autoconf()) {
+		fprintf(stderr, _("\n*** Error during writing of the Buildroot configuration.\n\n"));
+		return 1;
+	}
+
 	return 0;
 	return 0;
 }
 }

+ 481 - 91
package/config/confdata.c

@@ -5,28 +5,46 @@
 
 
 #include <sys/stat.h>
 #include <sys/stat.h>
 #include <ctype.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
 #define LKC_DIRECT_LINK
 #define LKC_DIRECT_LINK
 #include "lkc.h"
 #include "lkc.h"
 
 
-const char conf_def_filename[] = ".config";
+static void conf_warning(const char *fmt, ...)
+	__attribute__ ((format (printf, 1, 2)));
 
 
-const char conf_defname[] = ".defconfig";
+static const char *conf_filename;
+static int conf_lineno, conf_warnings, conf_unsaved;
 
 
-const char *conf_confnames[] = {
-	".config",
-	conf_defname,
-	NULL,
-};
+const char conf_defname[] = "extra/Configs/defconfigs/$ARCH";
 
 
-static char *conf_expand_value(const signed char *in)
+static void conf_warning(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+	conf_warnings++;
+}
+
+const char *conf_get_configname(void)
+{
+	char *name = getenv("KCONFIG_CONFIG");
+
+	return name ? name : ".config";
+}
+
+static char *conf_expand_value(const char *in)
 {
 {
 	struct symbol *sym;
 	struct symbol *sym;
-	const signed char *src;
+	const char *src;
 	static char res_value[SYMBOL_MAXLENGTH];
 	static char res_value[SYMBOL_MAXLENGTH];
 	char *dst, name[SYMBOL_MAXLENGTH];
 	char *dst, name[SYMBOL_MAXLENGTH];
 
 
@@ -65,53 +83,70 @@ char *conf_get_default_confname(void)
 	return name;
 	return name;
 }
 }
 
 
-int conf_read(const char *name)
+int conf_read_simple(const char *name, int def)
 {
 {
 	FILE *in = NULL;
 	FILE *in = NULL;
 	char line[1024];
 	char line[1024];
 	char *p, *p2;
 	char *p, *p2;
-	int lineno = 0;
 	struct symbol *sym;
 	struct symbol *sym;
-	struct property *prop;
-	struct expr *e;
-	int i;
+	int i, def_flags;
 
 
 	if (name) {
 	if (name) {
 		in = zconf_fopen(name);
 		in = zconf_fopen(name);
 	} else {
 	} else {
-		const char **names = conf_confnames;
-		while ((name = *names++)) {
-			name = conf_expand_value(name);
+		struct property *prop;
+
+		name = conf_get_configname();
+		in = zconf_fopen(name);
+		if (in)
+			goto load;
+		sym_add_change_count(1);
+		if (!sym_defconfig_list)
+			return 1;
+
+		for_all_defaults(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);
 			in = zconf_fopen(name);
 			in = zconf_fopen(name);
 			if (in) {
 			if (in) {
-				printf("#\n"
-				       "# using defaults found in %s\n"
-				       "#\n", name);
-				break;
+				printf(_("#\n"
+					 "# using defaults found in %s\n"
+					 "#\n"), name);
+				goto load;
 			}
 			}
 		}
 		}
 	}
 	}
-
 	if (!in)
 	if (!in)
 		return 1;
 		return 1;
 
 
+load:
+	conf_filename = name;
+	conf_lineno = 0;
+	conf_warnings = 0;
+	conf_unsaved = 0;
+
+	def_flags = SYMBOL_DEF << def;
 	for_all_symbols(i, sym) {
 	for_all_symbols(i, sym) {
-		sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
-		sym->flags &= ~SYMBOL_VALID;
+		sym->flags |= SYMBOL_CHANGED;
+		sym->flags &= ~(def_flags|SYMBOL_VALID);
+		if (sym_is_choice(sym))
+			sym->flags |= def_flags;
 		switch (sym->type) {
 		switch (sym->type) {
 		case S_INT:
 		case S_INT:
 		case S_HEX:
 		case S_HEX:
 		case S_STRING:
 		case S_STRING:
-			if (sym->user.val)
-				free(sym->user.val);
+			if (sym->def[def].val)
+				free(sym->def[def].val);
 		default:
 		default:
-			sym->user.val = NULL;
-			sym->user.tri = no;
+			sym->def[def].val = NULL;
+			sym->def[def].tri = no;
 		}
 		}
 	}
 	}
 
 
 	while (fgets(line, sizeof(line), in)) {
 	while (fgets(line, sizeof(line), in)) {
-		lineno++;
+		conf_lineno++;
 		sym = NULL;
 		sym = NULL;
 		switch (line[0]) {
 		switch (line[0]) {
 		case '#':
 		case '#':
@@ -123,54 +158,84 @@ int conf_read(const char *name)
 			*p++ = 0;
 			*p++ = 0;
 			if (strncmp(p, "is not set", 10))
 			if (strncmp(p, "is not set", 10))
 				continue;
 				continue;
-			sym = sym_find(line + 2);
-			if (!sym) {
-				fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
+			if (def == S_DEF_USER) {
+				sym = sym_find(line + 2);
+				if (!sym) {
+					conf_warning("trying to assign nonexistent symbol %s", line + 2);
+					break;
+				}
+			} else {
+				sym = sym_lookup(line + 2, 0);
+				if (sym->type == S_UNKNOWN)
+					sym->type = S_BOOLEAN;
+			}
+			if (sym->flags & def_flags) {
+				conf_warning("trying to reassign symbol %s", sym->name);
 				break;
 				break;
 			}
 			}
 			switch (sym->type) {
 			switch (sym->type) {
 			case S_BOOLEAN:
 			case S_BOOLEAN:
 			case S_TRISTATE:
 			case S_TRISTATE:
-				sym->user.tri = no;
-				sym->flags &= ~SYMBOL_NEW;
+				sym->def[def].tri = no;
+				sym->flags |= def_flags;
 				break;
 				break;
 			default:
 			default:
 				;
 				;
 			}
 			}
 			break;
 			break;
-
 		case 'A' ... 'Z':
 		case 'A' ... 'Z':
 			p = strchr(line, '=');
 			p = strchr(line, '=');
 			if (!p)
 			if (!p)
 				continue;
 				continue;
 			*p++ = 0;
 			*p++ = 0;
 			p2 = strchr(p, '\n');
 			p2 = strchr(p, '\n');
-			if (p2)
-				*p2 = 0;
-			sym = sym_find(line);
-			if (!sym) {
-				fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
+			if (p2) {
+				*p2-- = 0;
+				if (*p2 == '\r')
+					*p2 = 0;
+			}
+			if (def == S_DEF_USER) {
+				sym = sym_find(line);
+				if (!sym) {
+					conf_warning("trying to assign nonexistent symbol %s", line);
+					break;
+				}
+			} else {
+				sym = sym_lookup(line, 0);
+				if (sym->type == S_UNKNOWN)
+					sym->type = S_OTHER;
+			}
+			if (sym->flags & def_flags) {
+				conf_warning("trying to reassign symbol %s", sym->name);
 				break;
 				break;
 			}
 			}
 			switch (sym->type) {
 			switch (sym->type) {
 			case S_TRISTATE:
 			case S_TRISTATE:
 				if (p[0] == 'm') {
 				if (p[0] == 'm') {
-					sym->user.tri = mod;
-					sym->flags &= ~SYMBOL_NEW;
+					sym->def[def].tri = mod;
+					sym->flags |= def_flags;
 					break;
 					break;
 				}
 				}
 			case S_BOOLEAN:
 			case S_BOOLEAN:
 				if (p[0] == 'y') {
 				if (p[0] == 'y') {
-					sym->user.tri = yes;
-					sym->flags &= ~SYMBOL_NEW;
+					sym->def[def].tri = yes;
+					sym->flags |= def_flags;
 					break;
 					break;
 				}
 				}
 				if (p[0] == 'n') {
 				if (p[0] == 'n') {
-					sym->user.tri = no;
-					sym->flags &= ~SYMBOL_NEW;
+					sym->def[def].tri = no;
+					sym->flags |= def_flags;
 					break;
 					break;
 				}
 				}
+				conf_warning("symbol value '%s' invalid for %s", p, sym->name);
 				break;
 				break;
+			case S_OTHER:
+				if (*p != '"') {
+					for (p2 = p; *p2 && !isspace(*p2); p2++)
+						;
+					sym->type = S_STRING;
+					goto done;
+				}
 			case S_STRING:
 			case S_STRING:
 				if (*p++ != '"')
 				if (*p++ != '"')
 					break;
 					break;
@@ -182,62 +247,105 @@ int conf_read(const char *name)
 					memmove(p2, p2 + 1, strlen(p2));
 					memmove(p2, p2 + 1, strlen(p2));
 				}
 				}
 				if (!p2) {
 				if (!p2) {
-					fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
-					exit(1);
+					conf_warning("invalid string found");
+					continue;
 				}
 				}
 			case S_INT:
 			case S_INT:
 			case S_HEX:
 			case S_HEX:
+			done:
 				if (sym_string_valid(sym, p)) {
 				if (sym_string_valid(sym, p)) {
-					sym->user.val = strdup(p);
-					sym->flags &= ~SYMBOL_NEW;
+					sym->def[def].val = strdup(p);
+					sym->flags |= def_flags;
 				} else {
 				} else {
-					fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
-					exit(1);
+					conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+					continue;
 				}
 				}
 				break;
 				break;
 			default:
 			default:
 				;
 				;
 			}
 			}
 			break;
 			break;
+		case '\r':
 		case '\n':
 		case '\n':
 			break;
 			break;
 		default:
 		default:
+			conf_warning("unexpected data");
 			continue;
 			continue;
 		}
 		}
 		if (sym && sym_is_choice_value(sym)) {
 		if (sym && sym_is_choice_value(sym)) {
 			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
 			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
-			switch (sym->user.tri) {
+			switch (sym->def[def].tri) {
 			case no:
 			case no:
 				break;
 				break;
 			case mod:
 			case mod:
-				if (cs->user.tri == yes)
-					/* warn? */;
+				if (cs->def[def].tri == yes) {
+					conf_warning("%s creates inconsistent choice state", sym->name);
+					cs->flags &= ~def_flags;
+				}
 				break;
 				break;
 			case yes:
 			case yes:
-				if (cs->user.tri != no)
-					/* warn? */;
-				cs->user.val = sym;
+				if (cs->def[def].tri != no) {
+					conf_warning("%s creates inconsistent choice state", sym->name);
+					cs->flags &= ~def_flags;
+				} else
+					cs->def[def].val = sym;
 				break;
 				break;
 			}
 			}
-			cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
-			cs->flags &= ~SYMBOL_NEW;
+			cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri);
 		}
 		}
 	}
 	}
 	fclose(in);
 	fclose(in);
 
 
 	if (modules_sym)
 	if (modules_sym)
 		sym_calc_value(modules_sym);
 		sym_calc_value(modules_sym);
+	return 0;
+}
+
+int conf_read(const char *name)
+{
+	struct symbol *sym;
+	struct property *prop;
+	struct expr *e;
+	int i, flags;
+
+	sym_set_change_count(0);
+
+	if (conf_read_simple(name, S_DEF_USER))
+		return 1;
+
 	for_all_symbols(i, sym) {
 	for_all_symbols(i, sym) {
 		sym_calc_value(sym);
 		sym_calc_value(sym);
+		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
+			goto sym_ok;
+		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
+			/* check that calculated value agrees with saved value */
+			switch (sym->type) {
+			case S_BOOLEAN:
+			case S_TRISTATE:
+				if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
+					break;
+				if (!sym_is_choice(sym))
+					goto sym_ok;
+			default:
+				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
+					goto sym_ok;
+				break;
+			}
+		} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
+			/* no previous value and not saved */
+			goto sym_ok;
+		conf_unsaved++;
+		/* maybe print value in verbose mode... */
+	sym_ok:
 		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
 		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
 			if (sym->visible == no)
 			if (sym->visible == no)
-				sym->flags |= SYMBOL_NEW;
+				sym->flags &= ~SYMBOL_DEF_USER;
 			switch (sym->type) {
 			switch (sym->type) {
 			case S_STRING:
 			case S_STRING:
 			case S_INT:
 			case S_INT:
 			case S_HEX:
 			case S_HEX:
-				if (!sym_string_within_range(sym, sym->user.val))
-					sym->flags |= SYMBOL_NEW;
+				if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val))
+					sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
 			default:
 			default:
 				break;
 				break;
 			}
 			}
@@ -245,12 +353,14 @@ int conf_read(const char *name)
 		if (!sym_is_choice(sym))
 		if (!sym_is_choice(sym))
 			continue;
 			continue;
 		prop = sym_get_choice_prop(sym);
 		prop = sym_get_choice_prop(sym);
+		flags = sym->flags;
 		for (e = prop->expr; e; e = e->left.expr)
 		for (e = prop->expr; e; e = e->left.expr)
 			if (e->right.sym->visible != no)
 			if (e->right.sym->visible != no)
-				sym->flags |= e->right.sym->flags & SYMBOL_NEW;
+				flags &= e->right.sym->flags;
+		sym->flags &= flags | ~SYMBOL_DEF_USER;
 	}
 	}
 
 
-	sym_change_count = 1;
+	sym_add_change_count(conf_warnings || conf_unsaved);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -264,6 +374,9 @@ int conf_write(const char *name)
 	char dirname[128], tmpname[128], newname[128];
 	char dirname[128], tmpname[128], newname[128];
 	int type, l;
 	int type, l;
 	const char *str;
 	const char *str;
+	time_t now;
+	int use_timestamp = 1;
+	char *env;
 
 
 	dirname[0] = 0;
 	dirname[0] = 0;
 	if (name && name[0]) {
 	if (name && name[0]) {
@@ -273,7 +386,7 @@ int conf_write(const char *name)
 		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
 		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
 			strcpy(dirname, name);
 			strcpy(dirname, name);
 			strcat(dirname, "/");
 			strcat(dirname, "/");
-			basename = conf_def_filename;
+			basename = conf_get_configname();
 		} else if ((slash = strrchr(name, '/'))) {
 		} else if ((slash = strrchr(name, '/'))) {
 			int size = slash - name + 1;
 			int size = slash - name + 1;
 			memcpy(dirname, name, size);
 			memcpy(dirname, name, size);
@@ -281,21 +394,39 @@ int conf_write(const char *name)
 			if (slash[1])
 			if (slash[1])
 				basename = slash + 1;
 				basename = slash + 1;
 			else
 			else
-				basename = conf_def_filename;
+				basename = conf_get_configname();
 		} else
 		} else
 			basename = name;
 			basename = name;
 	} else
 	} else
-		basename = conf_def_filename;
+		basename = conf_get_configname();
 
 
-	sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
-	out = fopen(newname, "w");
+	sprintf(newname, "%s%s", dirname, basename);
+	env = getenv("KCONFIG_OVERWRITECONFIG");
+	if (!env || !*env) {
+		sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
+		out = fopen(tmpname, "w");
+	} else {
+		*tmpname = 0;
+		out = fopen(newname, "w");
+	}
 	if (!out)
 	if (!out)
 		return 1;
 		return 1;
-	fprintf(out, "#\n"
-		     "# Automatically generated make config: don't edit\n"
-		     "#\n");
 
 
-	if (!sym_change_count)
+	sym = sym_lookup("VERSION", 0);
+	sym_calc_value(sym);
+	time(&now);
+	env = getenv("KCONFIG_NOTIMESTAMP");
+	if (env && *env)
+		use_timestamp = 0;
+
+	fprintf(out, _("#\n"
+		       "# Automatically generated make config: don't edit\n"
+		       "%s%s"
+		       "#\n"),
+		     use_timestamp ? "# " : "",
+		     use_timestamp ? ctime(&now) : "");
+
+	if (!conf_get_changed())
 		sym_clear_all_valid();
 		sym_clear_all_valid();
 
 
 	menu = rootmenu.list;
 	menu = rootmenu.list;
@@ -336,20 +467,18 @@ int conf_write(const char *name)
 				}
 				}
 				break;
 				break;
 			case S_STRING:
 			case S_STRING:
-				// fix me
 				str = sym_get_string_value(sym);
 				str = sym_get_string_value(sym);
 				fprintf(out, "%s=\"", sym->name);
 				fprintf(out, "%s=\"", sym->name);
-				do {
+				while (1) {
 					l = strcspn(str, "\"\\");
 					l = strcspn(str, "\"\\");
 					if (l) {
 					if (l) {
 						fwrite(str, l, 1, out);
 						fwrite(str, l, 1, out);
+						str += l;
 					}
 					}
-					str += l;
-					while (*str == '\\' || *str == '"') {
-						fprintf(out, "\\%c", *str);
-						str++;
-					}
-				} while (*str);
+					if (!*str)
+						break;
+					fprintf(out, "\\%c", *str++);
+				}
 				fputs("\"\n", out);
 				fputs("\"\n", out);
 				break;
 				break;
 			case S_HEX:
 			case S_HEX:
@@ -380,18 +509,279 @@ int conf_write(const char *name)
 		}
 		}
 	}
 	}
 	fclose(out);
 	fclose(out);
-	file_write_dep(NULL);
-	if (!name || basename != conf_def_filename) {
-		if (!name)
-			name = conf_def_filename;
-		sprintf(tmpname, "%s.old", name);
-		rename(name, tmpname);
+
+	if (*tmpname) {
+		strcat(dirname, basename);
+		strcat(dirname, ".old");
+		rename(newname, dirname);
+		if (rename(tmpname, newname))
+			return 1;
+	}
+
+	printf(_("#\n"
+		 "# configuration written to %s\n"
+		 "#\n"), newname);
+
+	sym_set_change_count(0);
+
+	return 0;
+}
+
+int conf_split_config(void)
+{
+	char *name, path[128];
+	char *s, *d, c;
+	struct symbol *sym;
+	struct stat sb;
+	int res, i, fd;
+
+	name = getenv("KCONFIG_AUTOCONFIG");
+	if (!name)
+		name = "include/config/auto.conf";
+	conf_read_simple(name, S_DEF_AUTO);
+
+	if (chdir("include/config"))
+		return 1;
+
+	res = 0;
+	for_all_symbols(i, sym) {
+		sym_calc_value(sym);
+		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
+			continue;
+		if (sym->flags & SYMBOL_WRITE) {
+			if (sym->flags & SYMBOL_DEF_AUTO) {
+				/*
+				 * symbol has old and new value,
+				 * so compare them...
+				 */
+				switch (sym->type) {
+				case S_BOOLEAN:
+				case S_TRISTATE:
+					if (sym_get_tristate_value(sym) ==
+					    sym->def[S_DEF_AUTO].tri)
+						continue;
+					break;
+				case S_STRING:
+				case S_HEX:
+				case S_INT:
+					if (!strcmp(sym_get_string_value(sym),
+						    sym->def[S_DEF_AUTO].val))
+						continue;
+					break;
+				default:
+					break;
+				}
+			} else {
+				/*
+				 * If there is no old value, only 'no' (unset)
+				 * is allowed as new value.
+				 */
+				switch (sym->type) {
+				case S_BOOLEAN:
+				case S_TRISTATE:
+					if (sym_get_tristate_value(sym) == no)
+						continue;
+					break;
+				default:
+					break;
+				}
+			}
+		} else if (!(sym->flags & SYMBOL_DEF_AUTO))
+			/* There is neither an old nor a new value. */
+			continue;
+		/* else
+		 *	There is an old value, but no new value ('no' (unset)
+		 *	isn't saved in auto.conf, so the old value is always
+		 *	different from 'no').
+		 */
+
+		/* Replace all '_' and append ".h" */
+		s = sym->name;
+		d = path;
+		while ((c = *s++)) {
+			c = tolower(c);
+			*d++ = (c == '_') ? '/' : c;
+		}
+		strcpy(d, ".h");
+
+		/* Assume directory path already exists. */
+		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+		if (fd == -1) {
+			if (errno != ENOENT) {
+				res = 1;
+				break;
+			}
+			/*
+			 * Create directory components,
+			 * unless they exist already.
+			 */
+			d = path;
+			while ((d = strchr(d, '/'))) {
+				*d = 0;
+				if (stat(path, &sb) && mkdir(path, 0755)) {
+					res = 1;
+					goto out;
+				}
+				*d++ = '/';
+			}
+			/* Try it again. */
+			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+			if (fd == -1) {
+				res = 1;
+				break;
+			}
+		}
+		close(fd);
 	}
 	}
-	sprintf(tmpname, "%s%s", dirname, basename);
-	if (rename(newname, tmpname))
+out:
+	if (chdir("../.."))
 		return 1;
 		return 1;
 
 
-	sym_change_count = 0;
+	return res;
+}
+
+int conf_write_autoconf(void)
+{
+	struct symbol *sym;
+	const char *str;
+	char *name;
+	FILE *out, *out_h;
+	time_t now;
+	int i, l;
 
 
 	return 0;
 	return 0;
+
+	sym_clear_all_valid();
+
+	file_write_dep("include/config/auto.conf.cmd");
+
+	if (conf_split_config())
+		return 1;
+
+	out = fopen(".tmpconfig", "w");
+	if (!out)
+		return 1;
+
+	out_h = fopen(".tmpconfig.h", "w");
+	if (!out_h) {
+		fclose(out);
+		return 1;
+	}
+
+	sym = sym_lookup("VERSION", 0);
+	sym_calc_value(sym);
+	time(&now);
+	fprintf(out, "#\n"
+		     "# Automatically generated make config: don't edit\n"
+		     "# %s"
+		     "#\n",
+		     ctime(&now));
+	fprintf(out_h, "/*\n"
+		       " * Automatically generated C config: don't edit\n"
+		       " * %s"
+		       " */\n",
+		       ctime(&now));
+
+	for_all_symbols(i, sym) {
+		sym_calc_value(sym);
+		if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
+			continue;
+		switch (sym->type) {
+		case S_BOOLEAN:
+		case S_TRISTATE:
+			switch (sym_get_tristate_value(sym)) {
+			case no:
+				break;
+			case mod:
+				fprintf(out, "%s=m\n", sym->name);
+				fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
+				break;
+			case yes:
+				fprintf(out, "%s=y\n", sym->name);
+				fprintf(out_h, "#define %s 1\n", sym->name);
+				break;
+			}
+			break;
+		case S_STRING:
+			str = sym_get_string_value(sym);
+			fprintf(out, "%s=\"", sym->name);
+			fprintf(out_h, "#define %s \"", sym->name);
+			while (1) {
+				l = strcspn(str, "\"\\");
+				if (l) {
+					fwrite(str, l, 1, out);
+					fwrite(str, l, 1, out_h);
+					str += l;
+				}
+				if (!*str)
+					break;
+				fprintf(out, "\\%c", *str);
+				fprintf(out_h, "\\%c", *str);
+				str++;
+			}
+			fputs("\"\n", out);
+			fputs("\"\n", out_h);
+			break;
+		case S_HEX:
+			str = sym_get_string_value(sym);
+			if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
+				fprintf(out, "%s=%s\n", sym->name, str);
+				fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
+				break;
+			}
+		case S_INT:
+			str = sym_get_string_value(sym);
+			fprintf(out, "%s=%s\n", sym->name, str);
+			fprintf(out_h, "#define %s %s\n", sym->name, str);
+			break;
+		default:
+			break;
+		}
+	}
+	fclose(out);
+	fclose(out_h);
+
+	name = getenv("KCONFIG_AUTOHEADER");
+	if (!name)
+		name = "include/linux/autoconf.h";
+	if (rename(".tmpconfig.h", name))
+		return 1;
+	name = getenv("KCONFIG_AUTOCONFIG");
+	if (!name)
+		name = "include/config/auto.conf";
+	/*
+	 * This must be the last step, kbuild has a dependency on auto.conf
+	 * and this marks the successful completion of the previous steps.
+	 */
+	if (rename(".tmpconfig", name))
+		return 1;
+
+	return 0;
+}
+
+static int sym_change_count;
+static void (*conf_changed_callback)(void);
+
+void sym_set_change_count(int count)
+{
+	int _sym_change_count = sym_change_count;
+	sym_change_count = count;
+	if (conf_changed_callback &&
+	    (bool)_sym_change_count != (bool)count)
+		conf_changed_callback();
+}
+
+void sym_add_change_count(int count)
+{
+	sym_set_change_count(count + sym_change_count);
+}
+
+bool conf_get_changed(void)
+{
+	return sym_change_count;
+}
+
+void conf_set_changed_callback(void (*fn)(void))
+{
+	conf_changed_callback = fn;
 }
 }

+ 27 - 26
package/config/expr.c

@@ -145,7 +145,8 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
 		return;
 		return;
 	}
 	}
 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
-	    e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO)))
+	    e1->left.sym == e2->left.sym &&
+	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
 		return;
 		return;
 	if (!expr_eq(e1, e2))
 	if (!expr_eq(e1, e2))
 		return;
 		return;
@@ -1012,73 +1013,73 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2)
 #endif
 #endif
 }
 }
 
 
-void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken)
+void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
 {
 {
 	if (!e) {
 	if (!e) {
-		fn(data, "y");
+		fn(data, NULL, "y");
 		return;
 		return;
 	}
 	}
 
 
 	if (expr_compare_type(prevtoken, e->type) > 0)
 	if (expr_compare_type(prevtoken, e->type) > 0)
-		fn(data, "(");
+		fn(data, NULL, "(");
 	switch (e->type) {
 	switch (e->type) {
 	case E_SYMBOL:
 	case E_SYMBOL:
 		if (e->left.sym->name)
 		if (e->left.sym->name)
-			fn(data, e->left.sym->name);
+			fn(data, e->left.sym, e->left.sym->name);
 		else
 		else
-			fn(data, "<choice>");
+			fn(data, NULL, "<choice>");
 		break;
 		break;
 	case E_NOT:
 	case E_NOT:
-		fn(data, "!");
+		fn(data, NULL, "!");
 		expr_print(e->left.expr, fn, data, E_NOT);
 		expr_print(e->left.expr, fn, data, E_NOT);
 		break;
 		break;
 	case E_EQUAL:
 	case E_EQUAL:
-		fn(data, e->left.sym->name);
-		fn(data, "=");
-		fn(data, e->right.sym->name);
+		fn(data, e->left.sym, e->left.sym->name);
+		fn(data, NULL, "=");
+		fn(data, e->right.sym, e->right.sym->name);
 		break;
 		break;
 	case E_UNEQUAL:
 	case E_UNEQUAL:
-		fn(data, e->left.sym->name);
-		fn(data, "!=");
-		fn(data, e->right.sym->name);
+		fn(data, e->left.sym, e->left.sym->name);
+		fn(data, NULL, "!=");
+		fn(data, e->right.sym, e->right.sym->name);
 		break;
 		break;
 	case E_OR:
 	case E_OR:
 		expr_print(e->left.expr, fn, data, E_OR);
 		expr_print(e->left.expr, fn, data, E_OR);
-		fn(data, " || ");
+		fn(data, NULL, " || ");
 		expr_print(e->right.expr, fn, data, E_OR);
 		expr_print(e->right.expr, fn, data, E_OR);
 		break;
 		break;
 	case E_AND:
 	case E_AND:
 		expr_print(e->left.expr, fn, data, E_AND);
 		expr_print(e->left.expr, fn, data, E_AND);
-		fn(data, " && ");
+		fn(data, NULL, " && ");
 		expr_print(e->right.expr, fn, data, E_AND);
 		expr_print(e->right.expr, fn, data, E_AND);
 		break;
 		break;
 	case E_CHOICE:
 	case E_CHOICE:
-		fn(data, e->right.sym->name);
+		fn(data, e->right.sym, e->right.sym->name);
 		if (e->left.expr) {
 		if (e->left.expr) {
-			fn(data, " ^ ");
+			fn(data, NULL, " ^ ");
 			expr_print(e->left.expr, fn, data, E_CHOICE);
 			expr_print(e->left.expr, fn, data, E_CHOICE);
 		}
 		}
 		break;
 		break;
 	case E_RANGE:
 	case E_RANGE:
-		fn(data, "[");
-		fn(data, e->left.sym->name);
-		fn(data, " ");
-		fn(data, e->right.sym->name);
-		fn(data, "]");
+		fn(data, NULL, "[");
+		fn(data, e->left.sym, e->left.sym->name);
+		fn(data, NULL, " ");
+		fn(data, e->right.sym, e->right.sym->name);
+		fn(data, NULL, "]");
 		break;
 		break;
 	default:
 	default:
 	  {
 	  {
 		char buf[32];
 		char buf[32];
 		sprintf(buf, "<unknown type %d>", e->type);
 		sprintf(buf, "<unknown type %d>", e->type);
-		fn(data, buf);
+		fn(data, NULL, buf);
 		break;
 		break;
 	  }
 	  }
 	}
 	}
 	if (expr_compare_type(prevtoken, e->type) > 0)
 	if (expr_compare_type(prevtoken, e->type) > 0)
-		fn(data, ")");
+		fn(data, NULL, ")");
 }
 }
 
 
-static void expr_print_file_helper(void *data, const char *str)
+static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
 {
 {
 	fwrite(str, strlen(str), 1, data);
 	fwrite(str, strlen(str), 1, data);
 }
 }
@@ -1088,7 +1089,7 @@ void expr_fprint(struct expr *e, FILE *out)
 	expr_print(e, expr_print_file_helper, out, E_NONE);
 	expr_print(e, expr_print_file_helper, out, E_NONE);
 }
 }
 
 
-static void expr_print_gstr_helper(void *data, const char *str)
+static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
 {
 {
 	str_append((struct gstr*)data, str);
 	str_append((struct gstr*)data, str);
 }
 }

+ 14 - 7
package/config/expr.h

@@ -63,12 +63,18 @@ enum symbol_type {
 	S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
 	S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
 };
 };
 
 
+enum {
+	S_DEF_USER,		/* main user value */
+	S_DEF_AUTO,
+};
+
 struct symbol {
 struct symbol {
 	struct symbol *next;
 	struct symbol *next;
 	char *name;
 	char *name;
 	char *help;
 	char *help;
 	enum symbol_type type;
 	enum symbol_type type;
-	struct symbol_value curr, user;
+	struct symbol_value curr;
+	struct symbol_value def[4];
 	tristate visible;
 	tristate visible;
 	int flags;
 	int flags;
 	struct property *prop;
 	struct property *prop;
@@ -78,10 +84,7 @@ struct symbol {
 
 
 #define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
 #define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
 
 
-#define SYMBOL_YES		0x0001
-#define SYMBOL_MOD		0x0002
-#define SYMBOL_NO		0x0004
-#define SYMBOL_CONST		0x0007
+#define SYMBOL_CONST		0x0001
 #define SYMBOL_CHECK		0x0008
 #define SYMBOL_CHECK		0x0008
 #define SYMBOL_CHOICE		0x0010
 #define SYMBOL_CHOICE		0x0010
 #define SYMBOL_CHOICEVAL	0x0020
 #define SYMBOL_CHOICEVAL	0x0020
@@ -90,11 +93,14 @@ struct symbol {
 #define SYMBOL_OPTIONAL		0x0100
 #define SYMBOL_OPTIONAL		0x0100
 #define SYMBOL_WRITE		0x0200
 #define SYMBOL_WRITE		0x0200
 #define SYMBOL_CHANGED		0x0400
 #define SYMBOL_CHANGED		0x0400
-#define SYMBOL_NEW		0x0800
 #define SYMBOL_AUTO		0x1000
 #define SYMBOL_AUTO		0x1000
 #define SYMBOL_CHECKED		0x2000
 #define SYMBOL_CHECKED		0x2000
-#define SYMBOL_CHECK_DONE	0x4000
 #define SYMBOL_WARNED		0x8000
 #define SYMBOL_WARNED		0x8000
+#define SYMBOL_DEF		0x10000
+#define SYMBOL_DEF_USER		0x10000
+#define SYMBOL_DEF_AUTO		0x20000
+#define SYMBOL_DEF3		0x40000
+#define SYMBOL_DEF4		0x80000
 
 
 #define SYMBOL_MAXLENGTH	256
 #define SYMBOL_MAXLENGTH	256
 #define SYMBOL_HASHSIZE		257
 #define SYMBOL_HASHSIZE		257
@@ -150,6 +156,7 @@ struct file *lookup_file(const char *name);
 
 
 extern struct symbol symbol_yes, symbol_no, symbol_mod;
 extern struct symbol symbol_yes, symbol_no, symbol_mod;
 extern struct symbol *modules_sym;
 extern struct symbol *modules_sym;
+extern struct symbol *sym_defconfig_list;
 extern int cdebug;
 extern int cdebug;
 struct expr *expr_alloc_symbol(struct symbol *sym);
 struct expr *expr_alloc_symbol(struct symbol *sym);
 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);

+ 1636 - 0
package/config/gconf.c

@@ -0,0 +1,1636 @@
+/* Hey EMACS -*- linux-c -*- */
+/*
+ *
+ * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "lkc.h"
+#include "images.c"
+
+#include <glade/glade.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdlib.h>
+
+//#define DEBUG
+
+enum {
+	SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
+};
+
+static gint view_mode = FULL_VIEW;
+static gboolean show_name = TRUE;
+static gboolean show_range = TRUE;
+static gboolean show_value = TRUE;
+static gboolean show_all = FALSE;
+static gboolean show_debug = FALSE;
+static gboolean resizeable = FALSE;
+
+static char nohelp_text[] =
+    N_("Sorry, no help available for this option yet.\n");
+
+GtkWidget *main_wnd = NULL;
+GtkWidget *tree1_w = NULL;	// left  frame
+GtkWidget *tree2_w = NULL;	// right frame
+GtkWidget *text_w = NULL;
+GtkWidget *hpaned = NULL;
+GtkWidget *vpaned = NULL;
+GtkWidget *back_btn = NULL;
+GtkWidget *save_btn = NULL;
+GtkWidget *save_menu_item = NULL;
+
+GtkTextTag *tag1, *tag2;
+GdkColor color;
+
+GtkTreeStore *tree1, *tree2, *tree;
+GtkTreeModel *model1, *model2;
+static GtkTreeIter *parents[256];
+static gint indent;
+
+static struct menu *current; // current node for SINGLE view
+static struct menu *browsed; // browsed node for SPLIT view
+
+enum {
+	COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
+	COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
+	COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
+	COL_NUMBER
+};
+
+static void display_list(void);
+static void display_tree(struct menu *menu);
+static void display_tree_part(void);
+static void update_tree(struct menu *src, GtkTreeIter * dst);
+static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
+static gchar **fill_row(struct menu *menu);
+static void conf_changed(void);
+
+/* Helping/Debugging Functions */
+
+
+const char *dbg_print_stype(int val)
+{
+	static char buf[256];
+
+	bzero(buf, 256);
+
+	if (val == S_UNKNOWN)
+		strcpy(buf, "unknown");
+	if (val == S_BOOLEAN)
+		strcpy(buf, "boolean");
+	if (val == S_TRISTATE)
+		strcpy(buf, "tristate");
+	if (val == S_INT)
+		strcpy(buf, "int");
+	if (val == S_HEX)
+		strcpy(buf, "hex");
+	if (val == S_STRING)
+		strcpy(buf, "string");
+	if (val == S_OTHER)
+		strcpy(buf, "other");
+
+#ifdef DEBUG
+	printf("%s", buf);
+#endif
+
+	return buf;
+}
+
+const char *dbg_print_flags(int val)
+{
+	static char buf[256];
+
+	bzero(buf, 256);
+
+	if (val & SYMBOL_CONST)
+		strcat(buf, "const/");
+	if (val & SYMBOL_CHECK)
+		strcat(buf, "check/");
+	if (val & SYMBOL_CHOICE)
+		strcat(buf, "choice/");
+	if (val & SYMBOL_CHOICEVAL)
+		strcat(buf, "choiceval/");
+	if (val & SYMBOL_PRINTED)
+		strcat(buf, "printed/");
+	if (val & SYMBOL_VALID)
+		strcat(buf, "valid/");
+	if (val & SYMBOL_OPTIONAL)
+		strcat(buf, "optional/");
+	if (val & SYMBOL_WRITE)
+		strcat(buf, "write/");
+	if (val & SYMBOL_CHANGED)
+		strcat(buf, "changed/");
+	if (val & SYMBOL_AUTO)
+		strcat(buf, "auto/");
+
+	buf[strlen(buf) - 1] = '\0';
+#ifdef DEBUG
+	printf("%s", buf);
+#endif
+
+	return buf;
+}
+
+const char *dbg_print_ptype(int val)
+{
+	static char buf[256];
+
+	bzero(buf, 256);
+
+	if (val == P_UNKNOWN)
+		strcpy(buf, "unknown");
+	if (val == P_PROMPT)
+		strcpy(buf, "prompt");
+	if (val == P_COMMENT)
+		strcpy(buf, "comment");
+	if (val == P_MENU)
+		strcpy(buf, "menu");
+	if (val == P_DEFAULT)
+		strcpy(buf, "default");
+	if (val == P_CHOICE)
+		strcpy(buf, "choice");
+
+#ifdef DEBUG
+	printf("%s", buf);
+#endif
+
+	return buf;
+}
+
+
+void replace_button_icon(GladeXML * xml, GdkDrawable * window,
+			 GtkStyle * style, gchar * btn_name, gchar ** xpm)
+{
+	GdkPixmap *pixmap;
+	GdkBitmap *mask;
+	GtkToolButton *button;
+	GtkWidget *image;
+
+	pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
+					      &style->bg[GTK_STATE_NORMAL],
+					      xpm);
+
+	button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
+	image = gtk_image_new_from_pixmap(pixmap, mask);
+	gtk_widget_show(image);
+	gtk_tool_button_set_icon_widget(button, image);
+}
+
+/* Main Window Initialization */
+void init_main_window(const gchar * glade_file)
+{
+	GladeXML *xml;
+	GtkWidget *widget;
+	GtkTextBuffer *txtbuf;
+	char title[256];
+	GtkStyle *style;
+
+	xml = glade_xml_new(glade_file, "window1", NULL);
+	if (!xml)
+		g_error(_("GUI loading failed !\n"));
+	glade_xml_signal_autoconnect(xml);
+
+	main_wnd = glade_xml_get_widget(xml, "window1");
+	hpaned = glade_xml_get_widget(xml, "hpaned1");
+	vpaned = glade_xml_get_widget(xml, "vpaned1");
+	tree1_w = glade_xml_get_widget(xml, "treeview1");
+	tree2_w = glade_xml_get_widget(xml, "treeview2");
+	text_w = glade_xml_get_widget(xml, "textview3");
+
+	back_btn = glade_xml_get_widget(xml, "button1");
+	gtk_widget_set_sensitive(back_btn, FALSE);
+
+	widget = glade_xml_get_widget(xml, "show_name1");
+	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+				       show_name);
+
+	widget = glade_xml_get_widget(xml, "show_range1");
+	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+				       show_range);
+
+	widget = glade_xml_get_widget(xml, "show_data1");
+	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+				       show_value);
+
+	save_btn = glade_xml_get_widget(xml, "button3");
+	save_menu_item = glade_xml_get_widget(xml, "save1");
+	conf_set_changed_callback(conf_changed);
+
+	style = gtk_widget_get_style(main_wnd);
+	widget = glade_xml_get_widget(xml, "toolbar1");
+
+#if 0	/* Use stock Gtk icons instead */
+	replace_button_icon(xml, main_wnd->window, style,
+			    "button1", (gchar **) xpm_back);
+	replace_button_icon(xml, main_wnd->window, style,
+			    "button2", (gchar **) xpm_load);
+	replace_button_icon(xml, main_wnd->window, style,
+			    "button3", (gchar **) xpm_save);
+#endif
+	replace_button_icon(xml, main_wnd->window, style,
+			    "button4", (gchar **) xpm_single_view);
+	replace_button_icon(xml, main_wnd->window, style,
+			    "button5", (gchar **) xpm_split_view);
+	replace_button_icon(xml, main_wnd->window, style,
+			    "button6", (gchar **) xpm_tree_view);
+
+#if 0
+	switch (view_mode) {
+	case SINGLE_VIEW:
+		widget = glade_xml_get_widget(xml, "button4");
+		g_signal_emit_by_name(widget, "clicked");
+		break;
+	case SPLIT_VIEW:
+		widget = glade_xml_get_widget(xml, "button5");
+		g_signal_emit_by_name(widget, "clicked");
+		break;
+	case FULL_VIEW:
+		widget = glade_xml_get_widget(xml, "button6");
+		g_signal_emit_by_name(widget, "clicked");
+		break;
+	}
+#endif
+	txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+	tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
+					  "foreground", "red",
+					  "weight", PANGO_WEIGHT_BOLD,
+					  NULL);
+	tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
+					  /*"style", PANGO_STYLE_OBLIQUE, */
+					  NULL);
+
+	sprintf(title, _("Buildroot v%s Configuration"),
+		getenv("VERSION"));
+	gtk_window_set_title(GTK_WINDOW(main_wnd), title);
+
+	gtk_widget_show(main_wnd);
+}
+
+void init_tree_model(void)
+{
+	gint i;
+
+	tree = tree2 = gtk_tree_store_new(COL_NUMBER,
+					  G_TYPE_STRING, G_TYPE_STRING,
+					  G_TYPE_STRING, G_TYPE_STRING,
+					  G_TYPE_STRING, G_TYPE_STRING,
+					  G_TYPE_POINTER, GDK_TYPE_COLOR,
+					  G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+					  G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+					  G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+					  G_TYPE_BOOLEAN);
+	model2 = GTK_TREE_MODEL(tree2);
+
+	for (parents[0] = NULL, i = 1; i < 256; i++)
+		parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
+
+	tree1 = gtk_tree_store_new(COL_NUMBER,
+				   G_TYPE_STRING, G_TYPE_STRING,
+				   G_TYPE_STRING, G_TYPE_STRING,
+				   G_TYPE_STRING, G_TYPE_STRING,
+				   G_TYPE_POINTER, GDK_TYPE_COLOR,
+				   G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+				   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+				   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+				   G_TYPE_BOOLEAN);
+	model1 = GTK_TREE_MODEL(tree1);
+}
+
+void init_left_tree(void)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
+	GtkCellRenderer *renderer;
+	GtkTreeSelection *sel;
+	GtkTreeViewColumn *column;
+
+	gtk_tree_view_set_model(view, model1);
+	gtk_tree_view_set_headers_visible(view, TRUE);
+	gtk_tree_view_set_rules_hint(view, FALSE);
+
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_append_column(view, column);
+	gtk_tree_view_column_set_title(column, _("Options"));
+
+	renderer = gtk_cell_renderer_toggle_new();
+	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+					renderer, FALSE);
+	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+					    renderer,
+					    "active", COL_BTNACT,
+					    "inconsistent", COL_BTNINC,
+					    "visible", COL_BTNVIS,
+					    "radio", COL_BTNRAD, NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+					renderer, FALSE);
+	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+					    renderer,
+					    "text", COL_OPTION,
+					    "foreground-gdk",
+					    COL_COLOR, NULL);
+
+	sel = gtk_tree_view_get_selection(view);
+	gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+	gtk_widget_realize(tree1_w);
+}
+
+static void renderer_edited(GtkCellRendererText * cell,
+			    const gchar * path_string,
+			    const gchar * new_text, gpointer user_data);
+static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
+			     gchar * arg1, gpointer user_data);
+
+void init_right_tree(void)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
+	GtkCellRenderer *renderer;
+	GtkTreeSelection *sel;
+	GtkTreeViewColumn *column;
+	gint i;
+
+	gtk_tree_view_set_model(view, model2);
+	gtk_tree_view_set_headers_visible(view, TRUE);
+	gtk_tree_view_set_rules_hint(view, FALSE);
+
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_append_column(view, column);
+	gtk_tree_view_column_set_title(column, _("Options"));
+
+	renderer = gtk_cell_renderer_pixbuf_new();
+	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+					renderer, FALSE);
+	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+					    renderer,
+					    "pixbuf", COL_PIXBUF,
+					    "visible", COL_PIXVIS, NULL);
+	renderer = gtk_cell_renderer_toggle_new();
+	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+					renderer, FALSE);
+	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+					    renderer,
+					    "active", COL_BTNACT,
+					    "inconsistent", COL_BTNINC,
+					    "visible", COL_BTNVIS,
+					    "radio", COL_BTNRAD, NULL);
+	/*g_signal_connect(G_OBJECT(renderer), "toggled",
+	   G_CALLBACK(renderer_toggled), NULL); */
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+					renderer, FALSE);
+	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+					    renderer,
+					    "text", COL_OPTION,
+					    "foreground-gdk",
+					    COL_COLOR, NULL);
+
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    _("Name"), renderer,
+						    "text", COL_NAME,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    "N", renderer,
+						    "text", COL_NO,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    "M", renderer,
+						    "text", COL_MOD,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    "Y", renderer,
+						    "text", COL_YES,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(view, -1,
+						    _("Value"), renderer,
+						    "text", COL_VALUE,
+						    "editable",
+						    COL_EDIT,
+						    "foreground-gdk",
+						    COL_COLOR, NULL);
+	g_signal_connect(G_OBJECT(renderer), "edited",
+			 G_CALLBACK(renderer_edited), NULL);
+
+	column = gtk_tree_view_get_column(view, COL_NAME);
+	gtk_tree_view_column_set_visible(column, show_name);
+	column = gtk_tree_view_get_column(view, COL_NO);
+	gtk_tree_view_column_set_visible(column, show_range);
+	column = gtk_tree_view_get_column(view, COL_MOD);
+	gtk_tree_view_column_set_visible(column, show_range);
+	column = gtk_tree_view_get_column(view, COL_YES);
+	gtk_tree_view_column_set_visible(column, show_range);
+	column = gtk_tree_view_get_column(view, COL_VALUE);
+	gtk_tree_view_column_set_visible(column, show_value);
+
+	if (resizeable) {
+		for (i = 0; i < COL_VALUE; i++) {
+			column = gtk_tree_view_get_column(view, i);
+			gtk_tree_view_column_set_resizable(column, TRUE);
+		}
+	}
+
+	sel = gtk_tree_view_get_selection(view);
+	gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+}
+
+
+/* Utility Functions */
+
+
+static void text_insert_help(struct menu *menu)
+{
+	GtkTextBuffer *buffer;
+	GtkTextIter start, end;
+	const char *prompt = menu_get_prompt(menu);
+	gchar *name;
+	const char *help = _(nohelp_text);
+
+	if (!menu->sym)
+		help = "";
+	else if (menu->sym->help)
+		help = _(menu->sym->help);
+
+	if (menu->sym && menu->sym->name)
+		name = g_strdup_printf(_(menu->sym->name));
+	else
+		name = g_strdup("");
+
+	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+	gtk_text_buffer_get_bounds(buffer, &start, &end);
+	gtk_text_buffer_delete(buffer, &start, &end);
+	gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
+					 NULL);
+	gtk_text_buffer_insert_at_cursor(buffer, " ", 1);
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1,
+					 NULL);
+	gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2,
+					 NULL);
+}
+
+
+static void text_insert_msg(const char *title, const char *message)
+{
+	GtkTextBuffer *buffer;
+	GtkTextIter start, end;
+	const char *msg = message;
+
+	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+	gtk_text_buffer_get_bounds(buffer, &start, &end);
+	gtk_text_buffer_delete(buffer, &start, &end);
+	gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
+					 NULL);
+	gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
+					 NULL);
+}
+
+
+/* Main Windows Callbacks */
+
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
+gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
+				 gpointer user_data)
+{
+	GtkWidget *dialog, *label;
+	gint result;
+
+	if (!conf_get_changed())
+		return FALSE;
+
+	dialog = gtk_dialog_new_with_buttons(_("Warning !"),
+					     GTK_WINDOW(main_wnd),
+					     (GtkDialogFlags)
+					     (GTK_DIALOG_MODAL |
+					      GTK_DIALOG_DESTROY_WITH_PARENT),
+					     GTK_STOCK_OK,
+					     GTK_RESPONSE_YES,
+					     GTK_STOCK_NO,
+					     GTK_RESPONSE_NO,
+					     GTK_STOCK_CANCEL,
+					     GTK_RESPONSE_CANCEL, NULL);
+	gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+					GTK_RESPONSE_CANCEL);
+
+	label = gtk_label_new(_("\nSave configuration ?\n"));
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+	gtk_widget_show(label);
+
+	result = gtk_dialog_run(GTK_DIALOG(dialog));
+	switch (result) {
+	case GTK_RESPONSE_YES:
+		on_save_activate(NULL, NULL);
+		return FALSE;
+	case GTK_RESPONSE_NO:
+		return FALSE;
+	case GTK_RESPONSE_CANCEL:
+	case GTK_RESPONSE_DELETE_EVENT:
+	default:
+		gtk_widget_destroy(dialog);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
+void on_window1_destroy(GtkObject * object, gpointer user_data)
+{
+	gtk_main_quit();
+}
+
+
+void
+on_window1_size_request(GtkWidget * widget,
+			GtkRequisition * requisition, gpointer user_data)
+{
+	static gint old_h;
+	gint w, h;
+
+	if (widget->window == NULL)
+		gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
+	else
+		gdk_window_get_size(widget->window, &w, &h);
+
+	if (h == old_h)
+		return;
+	old_h = h;
+
+	gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
+}
+
+
+/* Menu & Toolbar Callbacks */
+
+
+static void
+load_filename(GtkFileSelection * file_selector, gpointer user_data)
+{
+	const gchar *fn;
+
+	fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
+					     (user_data));
+
+	if (conf_read(fn))
+		text_insert_msg(_("Error"), _("Unable to load configuration !"));
+	else
+		display_tree(&rootmenu);
+}
+
+void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *fs;
+
+	fs = gtk_file_selection_new(_("Load file..."));
+	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
+			 "clicked",
+			 G_CALLBACK(load_filename), (gpointer) fs);
+	g_signal_connect_swapped(GTK_OBJECT
+				 (GTK_FILE_SELECTION(fs)->ok_button),
+				 "clicked", G_CALLBACK(gtk_widget_destroy),
+				 (gpointer) fs);
+	g_signal_connect_swapped(GTK_OBJECT
+				 (GTK_FILE_SELECTION(fs)->cancel_button),
+				 "clicked", G_CALLBACK(gtk_widget_destroy),
+				 (gpointer) fs);
+	gtk_widget_show(fs);
+}
+
+
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	if (conf_write(NULL))
+		text_insert_msg(_("Error"), _("Unable to save configuration !"));
+}
+
+
+static void
+store_filename(GtkFileSelection * file_selector, gpointer user_data)
+{
+	const gchar *fn;
+
+	fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
+					     (user_data));
+
+	if (conf_write(fn))
+		text_insert_msg(_("Error"), _("Unable to save configuration !"));
+
+	gtk_widget_destroy(GTK_WIDGET(user_data));
+}
+
+void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *fs;
+
+	fs = gtk_file_selection_new(_("Save file as..."));
+	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
+			 "clicked",
+			 G_CALLBACK(store_filename), (gpointer) fs);
+	g_signal_connect_swapped(GTK_OBJECT
+				 (GTK_FILE_SELECTION(fs)->ok_button),
+				 "clicked", G_CALLBACK(gtk_widget_destroy),
+				 (gpointer) fs);
+	g_signal_connect_swapped(GTK_OBJECT
+				 (GTK_FILE_SELECTION(fs)->cancel_button),
+				 "clicked", G_CALLBACK(gtk_widget_destroy),
+				 (gpointer) fs);
+	gtk_widget_show(fs);
+}
+
+
+void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	if (!on_window1_delete_event(NULL, NULL, NULL))
+		gtk_widget_destroy(GTK_WIDGET(main_wnd));
+}
+
+
+void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkTreeViewColumn *col;
+
+	show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_name);
+}
+
+
+void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkTreeViewColumn *col;
+
+	show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_range);
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_range);
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_range);
+
+}
+
+
+void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkTreeViewColumn *col;
+
+	show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
+	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
+	if (col)
+		gtk_tree_view_column_set_visible(col, show_value);
+}
+
+
+void
+on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
+
+	gtk_tree_store_clear(tree2);
+	display_tree(&rootmenu);	// instead of update_tree to speed-up
+}
+
+
+void
+on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
+	update_tree(&rootmenu, NULL);
+}
+
+
+void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *dialog;
+	const gchar *intro_text = _(
+	    "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
+	    "for Linux.\n"
+	    "For each option, a blank box indicates the feature is disabled, a\n"
+	    "check indicates it is enabled, and a dot indicates that it is to\n"
+	    "be compiled as a module.  Clicking on the box will cycle through the three states.\n"
+	    "\n"
+	    "If you do not see an option (e.g., a device driver) that you\n"
+	    "believe should be present, try turning on Show All Options\n"
+	    "under the Options menu.\n"
+	    "Although there is no cross reference yet to help you figure out\n"
+	    "what other options must be enabled to support the option you\n"
+	    "are interested in, you can still view the help of a grayed-out\n"
+	    "option.\n"
+	    "\n"
+	    "Toggling Show Debug Info under the Options menu will show \n"
+	    "the dependencies, which you can then match by examining other options.");
+
+	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+					GTK_DIALOG_DESTROY_WITH_PARENT,
+					GTK_MESSAGE_INFO,
+					GTK_BUTTONS_CLOSE, intro_text);
+	g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+				 G_CALLBACK(gtk_widget_destroy),
+				 GTK_OBJECT(dialog));
+	gtk_widget_show_all(dialog);
+}
+
+
+void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *dialog;
+	const gchar *about_text =
+	    _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
+	      "Based on the source code from Roman Zippel.\n");
+
+	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+					GTK_DIALOG_DESTROY_WITH_PARENT,
+					GTK_MESSAGE_INFO,
+					GTK_BUTTONS_CLOSE, about_text);
+	g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+				 G_CALLBACK(gtk_widget_destroy),
+				 GTK_OBJECT(dialog));
+	gtk_widget_show_all(dialog);
+}
+
+
+void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+	GtkWidget *dialog;
+	const gchar *license_text =
+	    _("gkc is released under the terms of the GNU GPL v2.\n"
+	      "For more information, please see the source code or\n"
+	      "visit http://www.fsf.org/licenses/licenses.html\n");
+
+	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+					GTK_DIALOG_DESTROY_WITH_PARENT,
+					GTK_MESSAGE_INFO,
+					GTK_BUTTONS_CLOSE, license_text);
+	g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+				 G_CALLBACK(gtk_widget_destroy),
+				 GTK_OBJECT(dialog));
+	gtk_widget_show_all(dialog);
+}
+
+
+void on_back_clicked(GtkButton * button, gpointer user_data)
+{
+	enum prop_type ptype;
+
+	current = current->parent;
+	ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
+	if (ptype != P_MENU)
+		current = current->parent;
+	display_tree_part();
+
+	if (current == &rootmenu)
+		gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_load_clicked(GtkButton * button, gpointer user_data)
+{
+	on_load1_activate(NULL, user_data);
+}
+
+
+void on_single_clicked(GtkButton * button, gpointer user_data)
+{
+	view_mode = SINGLE_VIEW;
+	gtk_paned_set_position(GTK_PANED(hpaned), 0);
+	gtk_widget_hide(tree1_w);
+	current = &rootmenu;
+	display_tree_part();
+}
+
+
+void on_split_clicked(GtkButton * button, gpointer user_data)
+{
+	gint w, h;
+	view_mode = SPLIT_VIEW;
+	gtk_widget_show(tree1_w);
+	gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
+	gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
+	if (tree2)
+		gtk_tree_store_clear(tree2);
+	display_list();
+
+	/* Disable back btn, like in full mode. */
+	gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_full_clicked(GtkButton * button, gpointer user_data)
+{
+	view_mode = FULL_VIEW;
+	gtk_paned_set_position(GTK_PANED(hpaned), 0);
+	gtk_widget_hide(tree1_w);
+	if (tree2)
+		gtk_tree_store_clear(tree2);
+	display_tree(&rootmenu);
+	gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_collapse_clicked(GtkButton * button, gpointer user_data)
+{
+	gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
+}
+
+
+void on_expand_clicked(GtkButton * button, gpointer user_data)
+{
+	gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
+
+
+/* CTree Callbacks */
+
+/* Change hex/int/string value in the cell */
+static void renderer_edited(GtkCellRendererText * cell,
+			    const gchar * path_string,
+			    const gchar * new_text, gpointer user_data)
+{
+	GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
+	GtkTreeIter iter;
+	const char *old_def, *new_def;
+	struct menu *menu;
+	struct symbol *sym;
+
+	if (!gtk_tree_model_get_iter(model2, &iter, path))
+		return;
+
+	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+	sym = menu->sym;
+
+	gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
+	new_def = new_text;
+
+	sym_set_string_value(sym, new_def);
+
+	update_tree(&rootmenu, NULL);
+
+	gtk_tree_path_free(path);
+}
+
+/* Change the value of a symbol and update the tree */
+static void change_sym_value(struct menu *menu, gint col)
+{
+	struct symbol *sym = menu->sym;
+	tristate oldval, newval;
+
+	if (!sym)
+		return;
+
+	if (col == COL_NO)
+		newval = no;
+	else if (col == COL_MOD)
+		newval = mod;
+	else if (col == COL_YES)
+		newval = yes;
+	else
+		return;
+
+	switch (sym_get_type(sym)) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		oldval = sym_get_tristate_value(sym);
+		if (!sym_tristate_within_range(sym, newval))
+			newval = yes;
+		sym_set_tristate_value(sym, newval);
+		if (view_mode == FULL_VIEW)
+			update_tree(&rootmenu, NULL);
+		else if (view_mode == SPLIT_VIEW) {
+			update_tree(browsed, NULL);
+			display_list();
+		}
+		else if (view_mode == SINGLE_VIEW)
+			display_tree_part();	//fixme: keep exp/coll
+		break;
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+	default:
+		break;
+	}
+}
+
+static void toggle_sym_value(struct menu *menu)
+{
+	if (!menu->sym)
+		return;
+
+	sym_toggle_tristate_value(menu->sym);
+	if (view_mode == FULL_VIEW)
+		update_tree(&rootmenu, NULL);
+	else if (view_mode == SPLIT_VIEW) {
+		update_tree(browsed, NULL);
+		display_list();
+	}
+	else if (view_mode == SINGLE_VIEW)
+		display_tree_part();	//fixme: keep exp/coll
+}
+
+static void renderer_toggled(GtkCellRendererToggle * cell,
+			     gchar * path_string, gpointer user_data)
+{
+	GtkTreePath *path, *sel_path = NULL;
+	GtkTreeIter iter, sel_iter;
+	GtkTreeSelection *sel;
+	struct menu *menu;
+
+	path = gtk_tree_path_new_from_string(path_string);
+	if (!gtk_tree_model_get_iter(model2, &iter, path))
+		return;
+
+	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
+	if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
+		sel_path = gtk_tree_model_get_path(model2, &sel_iter);
+	if (!sel_path)
+		goto out1;
+	if (gtk_tree_path_compare(path, sel_path))
+		goto out2;
+
+	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+	toggle_sym_value(menu);
+
+      out2:
+	gtk_tree_path_free(sel_path);
+      out1:
+	gtk_tree_path_free(path);
+}
+
+static gint column2index(GtkTreeViewColumn * column)
+{
+	gint i;
+
+	for (i = 0; i < COL_NUMBER; i++) {
+		GtkTreeViewColumn *col;
+
+		col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
+		if (col == column)
+			return i;
+	}
+
+	return -1;
+}
+
+
+/* User click: update choice (full) or goes down (single) */
+gboolean
+on_treeview2_button_press_event(GtkWidget * widget,
+				GdkEventButton * event, gpointer user_data)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(widget);
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+	GtkTreeIter iter;
+	struct menu *menu;
+	gint col;
+
+#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
+	gint tx = (gint) event->x;
+	gint ty = (gint) event->y;
+	gint cx, cy;
+
+	gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
+				      &cy);
+#else
+	gtk_tree_view_get_cursor(view, &path, &column);
+#endif
+	if (path == NULL)
+		return FALSE;
+
+	if (!gtk_tree_model_get_iter(model2, &iter, path))
+		return FALSE;
+	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+
+	col = column2index(column);
+	if (event->type == GDK_2BUTTON_PRESS) {
+		enum prop_type ptype;
+		ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+
+		if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
+			// goes down into menu
+			current = menu;
+			display_tree_part();
+			gtk_widget_set_sensitive(back_btn, TRUE);
+		} else if ((col == COL_OPTION)) {
+			toggle_sym_value(menu);
+			gtk_tree_view_expand_row(view, path, TRUE);
+		}
+	} else {
+		if (col == COL_VALUE) {
+			toggle_sym_value(menu);
+			gtk_tree_view_expand_row(view, path, TRUE);
+		} else if (col == COL_NO || col == COL_MOD
+			   || col == COL_YES) {
+			change_sym_value(menu, col);
+			gtk_tree_view_expand_row(view, path, TRUE);
+		}
+	}
+
+	return FALSE;
+}
+
+/* Key pressed: update choice */
+gboolean
+on_treeview2_key_press_event(GtkWidget * widget,
+			     GdkEventKey * event, gpointer user_data)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(widget);
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+	GtkTreeIter iter;
+	struct menu *menu;
+	gint col;
+
+	gtk_tree_view_get_cursor(view, &path, &column);
+	if (path == NULL)
+		return FALSE;
+
+	if (event->keyval == GDK_space) {
+		if (gtk_tree_view_row_expanded(view, path))
+			gtk_tree_view_collapse_row(view, path);
+		else
+			gtk_tree_view_expand_row(view, path, FALSE);
+		return TRUE;
+	}
+	if (event->keyval == GDK_KP_Enter) {
+	}
+	if (widget == tree1_w)
+		return FALSE;
+
+	gtk_tree_model_get_iter(model2, &iter, path);
+	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+
+	if (!strcasecmp(event->string, "n"))
+		col = COL_NO;
+	else if (!strcasecmp(event->string, "m"))
+		col = COL_MOD;
+	else if (!strcasecmp(event->string, "y"))
+		col = COL_YES;
+	else
+		col = -1;
+	change_sym_value(menu, col);
+
+	return FALSE;
+}
+
+
+/* Row selection changed: update help */
+void
+on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
+{
+	GtkTreeSelection *selection;
+	GtkTreeIter iter;
+	struct menu *menu;
+
+	selection = gtk_tree_view_get_selection(treeview);
+	if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
+		gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+		text_insert_help(menu);
+	}
+}
+
+
+/* User click: display sub-tree in the right frame. */
+gboolean
+on_treeview1_button_press_event(GtkWidget * widget,
+				GdkEventButton * event, gpointer user_data)
+{
+	GtkTreeView *view = GTK_TREE_VIEW(widget);
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+	GtkTreeIter iter;
+	struct menu *menu;
+
+	gint tx = (gint) event->x;
+	gint ty = (gint) event->y;
+	gint cx, cy;
+
+	gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
+				      &cy);
+	if (path == NULL)
+		return FALSE;
+
+	gtk_tree_model_get_iter(model1, &iter, path);
+	gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
+
+	if (event->type == GDK_2BUTTON_PRESS) {
+		toggle_sym_value(menu);
+		current = menu;
+		display_tree_part();
+	} else {
+		browsed = menu;
+		display_tree_part();
+	}
+
+	gtk_widget_realize(tree2_w);
+	gtk_tree_view_set_cursor(view, path, NULL, FALSE);
+	gtk_widget_grab_focus(tree2_w);
+
+	return FALSE;
+}
+
+
+/* Fill a row of strings */
+static gchar **fill_row(struct menu *menu)
+{
+	static gchar *row[COL_NUMBER];
+	struct symbol *sym = menu->sym;
+	const char *def;
+	int stype;
+	tristate val;
+	enum prop_type ptype;
+	int i;
+
+	for (i = COL_OPTION; i <= COL_COLOR; i++)
+		g_free(row[i]);
+	bzero(row, sizeof(row));
+
+	row[COL_OPTION] =
+	    g_strdup_printf("%s %s", menu_get_prompt(menu),
+			    sym && sym_has_value(sym) ? "(NEW)" : "");
+
+	if (show_all && !menu_is_visible(menu))
+		row[COL_COLOR] = g_strdup("DarkGray");
+	else
+		row[COL_COLOR] = g_strdup("Black");
+
+	ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+	switch (ptype) {
+	case P_MENU:
+		row[COL_PIXBUF] = (gchar *) xpm_menu;
+		if (view_mode == SINGLE_VIEW)
+			row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
+		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+		break;
+	case P_COMMENT:
+		row[COL_PIXBUF] = (gchar *) xpm_void;
+		row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
+		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+		break;
+	default:
+		row[COL_PIXBUF] = (gchar *) xpm_void;
+		row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
+		row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
+		break;
+	}
+
+	if (!sym)
+		return row;
+	row[COL_NAME] = g_strdup(sym->name);
+
+	sym_calc_value(sym);
+	sym->flags &= ~SYMBOL_CHANGED;
+
+	if (sym_is_choice(sym)) {	// parse childs for getting final value
+		struct menu *child;
+		struct symbol *def_sym = sym_get_choice_value(sym);
+		struct menu *def_menu = NULL;
+
+		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+
+		for (child = menu->list; child; child = child->next) {
+			if (menu_is_visible(child)
+			    && child->sym == def_sym)
+				def_menu = child;
+		}
+
+		if (def_menu)
+			row[COL_VALUE] =
+			    g_strdup(menu_get_prompt(def_menu));
+	}
+	if (sym->flags & SYMBOL_CHOICEVAL)
+		row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
+
+	stype = sym_get_type(sym);
+	switch (stype) {
+	case S_BOOLEAN:
+		if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
+			row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
+		if (sym_is_choice(sym))
+			break;
+	case S_TRISTATE:
+		val = sym_get_tristate_value(sym);
+		switch (val) {
+		case no:
+			row[COL_NO] = g_strdup("N");
+			row[COL_VALUE] = g_strdup("N");
+			row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
+			row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
+			break;
+		case mod:
+			row[COL_MOD] = g_strdup("M");
+			row[COL_VALUE] = g_strdup("M");
+			row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
+			break;
+		case yes:
+			row[COL_YES] = g_strdup("Y");
+			row[COL_VALUE] = g_strdup("Y");
+			row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
+			row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
+			break;
+		}
+
+		if (val != no && sym_tristate_within_range(sym, no))
+			row[COL_NO] = g_strdup("_");
+		if (val != mod && sym_tristate_within_range(sym, mod))
+			row[COL_MOD] = g_strdup("_");
+		if (val != yes && sym_tristate_within_range(sym, yes))
+			row[COL_YES] = g_strdup("_");
+		break;
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		def = sym_get_string_value(sym);
+		row[COL_VALUE] = g_strdup(def);
+		row[COL_EDIT] = GINT_TO_POINTER(TRUE);
+		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+		break;
+	}
+
+	return row;
+}
+
+
+/* Set the node content with a row of strings */
+static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
+{
+	GdkColor color;
+	gboolean success;
+	GdkPixbuf *pix;
+
+	pix = gdk_pixbuf_new_from_xpm_data((const char **)
+					   row[COL_PIXBUF]);
+
+	gdk_color_parse(row[COL_COLOR], &color);
+	gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
+				  FALSE, FALSE, &success);
+
+	gtk_tree_store_set(tree, node,
+			   COL_OPTION, row[COL_OPTION],
+			   COL_NAME, row[COL_NAME],
+			   COL_NO, row[COL_NO],
+			   COL_MOD, row[COL_MOD],
+			   COL_YES, row[COL_YES],
+			   COL_VALUE, row[COL_VALUE],
+			   COL_MENU, (gpointer) menu,
+			   COL_COLOR, &color,
+			   COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
+			   COL_PIXBUF, pix,
+			   COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
+			   COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
+			   COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
+			   COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
+			   COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
+			   -1);
+
+	g_object_unref(pix);
+}
+
+
+/* Add a node to the tree */
+static void place_node(struct menu *menu, char **row)
+{
+	GtkTreeIter *parent = parents[indent - 1];
+	GtkTreeIter *node = parents[indent];
+
+	gtk_tree_store_append(tree, node, parent);
+	set_node(node, menu, row);
+}
+
+
+/* Find a node in the GTK+ tree */
+static GtkTreeIter found;
+
+/*
+ * Find a menu in the GtkTree starting at parent.
+ */
+GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
+				    struct menu *tofind)
+{
+	GtkTreeIter iter;
+	GtkTreeIter *child = &iter;
+	gboolean valid;
+	GtkTreeIter *ret;
+
+	valid = gtk_tree_model_iter_children(model2, child, parent);
+	while (valid) {
+		struct menu *menu;
+
+		gtk_tree_model_get(model2, child, 6, &menu, -1);
+
+		if (menu == tofind) {
+			memcpy(&found, child, sizeof(GtkTreeIter));
+			return &found;
+		}
+
+		ret = gtktree_iter_find_node(child, tofind);
+		if (ret)
+			return ret;
+
+		valid = gtk_tree_model_iter_next(model2, child);
+	}
+
+	return NULL;
+}
+
+
+/*
+ * Update the tree by adding/removing entries
+ * Does not change other nodes
+ */
+static void update_tree(struct menu *src, GtkTreeIter * dst)
+{
+	struct menu *child1;
+	GtkTreeIter iter, tmp;
+	GtkTreeIter *child2 = &iter;
+	gboolean valid;
+	GtkTreeIter *sibling;
+	struct symbol *sym;
+	struct property *prop;
+	struct menu *menu1, *menu2;
+
+	if (src == &rootmenu)
+		indent = 1;
+
+	valid = gtk_tree_model_iter_children(model2, child2, dst);
+	for (child1 = src->list; child1; child1 = child1->next) {
+
+		prop = child1->prompt;
+		sym = child1->sym;
+
+	      reparse:
+		menu1 = child1;
+		if (valid)
+			gtk_tree_model_get(model2, child2, COL_MENU,
+					   &menu2, -1);
+		else
+			menu2 = NULL;	// force adding of a first child
+
+#ifdef DEBUG
+		printf("%*c%s | %s\n", indent, ' ',
+		       menu1 ? menu_get_prompt(menu1) : "nil",
+		       menu2 ? menu_get_prompt(menu2) : "nil");
+#endif
+
+		if (!menu_is_visible(child1) && !show_all) {	// remove node
+			if (gtktree_iter_find_node(dst, menu1) != NULL) {
+				memcpy(&tmp, child2, sizeof(GtkTreeIter));
+				valid = gtk_tree_model_iter_next(model2,
+								 child2);
+				gtk_tree_store_remove(tree2, &tmp);
+				if (!valid)
+					return;	// next parent
+				else
+					goto reparse;	// next child
+			} else
+				continue;
+		}
+
+		if (menu1 != menu2) {
+			if (gtktree_iter_find_node(dst, menu1) == NULL) {	// add node
+				if (!valid && !menu2)
+					sibling = NULL;
+				else
+					sibling = child2;
+				gtk_tree_store_insert_before(tree2,
+							     child2,
+							     dst, sibling);
+				set_node(child2, menu1, fill_row(menu1));
+				if (menu2 == NULL)
+					valid = TRUE;
+			} else {	// remove node
+				memcpy(&tmp, child2, sizeof(GtkTreeIter));
+				valid = gtk_tree_model_iter_next(model2,
+								 child2);
+				gtk_tree_store_remove(tree2, &tmp);
+				if (!valid)
+					return;	// next parent
+				else
+					goto reparse;	// next child
+			}
+		} else if (sym && (sym->flags & SYMBOL_CHANGED)) {
+			set_node(child2, menu1, fill_row(menu1));
+		}
+
+		indent++;
+		update_tree(child1, child2);
+		indent--;
+
+		valid = gtk_tree_model_iter_next(model2, child2);
+	}
+}
+
+
+/* Display the whole tree (single/split/full view) */
+static void display_tree(struct menu *menu)
+{
+	struct symbol *sym;
+	struct property *prop;
+	struct menu *child;
+	enum prop_type ptype;
+
+	if (menu == &rootmenu) {
+		indent = 1;
+		current = &rootmenu;
+	}
+
+	for (child = menu->list; child; child = child->next) {
+		prop = child->prompt;
+		sym = child->sym;
+		ptype = prop ? prop->type : P_UNKNOWN;
+
+		if (sym)
+			sym->flags &= ~SYMBOL_CHANGED;
+
+		if ((view_mode == SPLIT_VIEW)
+		    && !(child->flags & MENU_ROOT) && (tree == tree1))
+			continue;
+
+		if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
+		    && (tree == tree2))
+			continue;
+
+		if (menu_is_visible(child) || show_all)
+			place_node(child, fill_row(child));
+#ifdef DEBUG
+		printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
+		printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
+		dbg_print_ptype(ptype);
+		printf(" | ");
+		if (sym) {
+			dbg_print_stype(sym->type);
+			printf(" | ");
+			dbg_print_flags(sym->flags);
+			printf("\n");
+		} else
+			printf("\n");
+#endif
+		if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
+		    && (tree == tree2))
+			continue;
+/*
+                if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
+		    || (view_mode == FULL_VIEW)
+		    || (view_mode == SPLIT_VIEW))*/
+		if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
+		    || (view_mode == FULL_VIEW)
+		    || (view_mode == SPLIT_VIEW)) {
+			indent++;
+			display_tree(child);
+			indent--;
+		}
+	}
+}
+
+/* Display a part of the tree starting at current node (single/split view) */
+static void display_tree_part(void)
+{
+	if (tree2)
+		gtk_tree_store_clear(tree2);
+	if (view_mode == SINGLE_VIEW)
+		display_tree(current);
+	else if (view_mode == SPLIT_VIEW)
+		display_tree(browsed);
+	gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
+
+/* Display the list in the left frame (split view) */
+static void display_list(void)
+{
+	if (tree1)
+		gtk_tree_store_clear(tree1);
+
+	tree = tree1;
+	display_tree(&rootmenu);
+	gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
+	tree = tree2;
+}
+
+void fixup_rootmenu(struct menu *menu)
+{
+	struct menu *child;
+	static int menu_cnt = 0;
+
+	menu->flags |= MENU_ROOT;
+	for (child = menu->list; child; child = child->next) {
+		if (child->prompt && child->prompt->type == P_MENU) {
+			menu_cnt++;
+			fixup_rootmenu(child);
+			menu_cnt--;
+		} else if (!menu_cnt)
+			fixup_rootmenu(child);
+	}
+}
+
+
+/* Main */
+int main(int ac, char *av[])
+{
+	const char *name;
+	char *env;
+	gchar *glade_file;
+
+#ifndef LKC_DIRECT_LINK
+	kconfig_load();
+#endif
+
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	bind_textdomain_codeset(PACKAGE, "UTF-8");
+	textdomain(PACKAGE);
+
+	/* GTK stuffs */
+	gtk_set_locale();
+	gtk_init(&ac, &av);
+	glade_init();
+
+	//add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
+	//add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
+
+	/* Determine GUI path */
+	env = getenv(SRCTREE);
+	if (env)
+		glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
+	else if (av[0][0] == '/')
+		glade_file = g_strconcat(av[0], ".glade", NULL);
+	else
+		glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
+
+	/* Load the interface and connect signals */
+	init_main_window(glade_file);
+	init_tree_model();
+	init_left_tree();
+	init_right_tree();
+
+	/* Conf stuffs */
+	if (ac > 1 && av[1][0] == '-') {
+		switch (av[1][1]) {
+		case 'a':
+			//showAll = 1;
+			break;
+		case 'h':
+		case '?':
+			printf("%s <config>\n", av[0]);
+			exit(0);
+		}
+		name = av[2];
+	} else
+		name = av[1];
+
+	conf_parse(name);
+	fixup_rootmenu(&rootmenu);
+	conf_read(NULL);
+
+	switch (view_mode) {
+	case SINGLE_VIEW:
+		display_tree_part();
+		break;
+	case SPLIT_VIEW:
+		display_list();
+		break;
+	case FULL_VIEW:
+		display_tree(&rootmenu);
+		break;
+	}
+
+	gtk_main();
+
+	return 0;
+}
+
+static void conf_changed(void)
+{
+	bool changed = conf_get_changed();
+	gtk_widget_set_sensitive(save_btn, changed);
+	gtk_widget_set_sensitive(save_menu_item, changed);
+}

+ 648 - 0
package/config/gconf.glade

@@ -0,0 +1,648 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="window1">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Gtk Buildroot Configurator</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="default_width">640</property>
+  <property name="default_height">480</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <signal name="destroy" handler="on_window1_destroy" object="window1"/>
+  <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/>
+  <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/>
+
+  <child>
+    <widget class="GtkVBox" id="vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child>
+	<widget class="GtkMenuBar" id="menubar1">
+	  <property name="visible">True</property>
+
+	  <child>
+	    <widget class="GtkMenuItem" id="file1">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">_File</property>
+	      <property name="use_underline">True</property>
+
+	      <child>
+		<widget class="GtkMenu" id="file1_menu">
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="load1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Load a config file</property>
+		      <property name="label" translatable="yes">_Load</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_load1_activate"/>
+		      <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image39">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-open</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="save1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Save the config in .config</property>
+		      <property name="label" translatable="yes">_Save</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_save_activate"/>
+		      <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image40">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-save</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="save_as1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Save the config in a file</property>
+		      <property name="label" translatable="yes">Save _as</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_save_as1_activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image41">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-save-as</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkSeparatorMenuItem" id="separator1">
+		      <property name="visible">True</property>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="quit1">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">_Quit</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_quit1_activate"/>
+		      <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image42">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-quit</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkMenuItem" id="options1">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">_Options</property>
+	      <property name="use_underline">True</property>
+
+	      <child>
+		<widget class="GtkMenu" id="options1_menu">
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_name1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show name</property>
+		      <property name="label" translatable="yes">Show _name</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_name1_activate"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_range1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
+		      <property name="label" translatable="yes">Show _range</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_range1_activate"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_data1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show value of the option</property>
+		      <property name="label" translatable="yes">Show _data</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_data1_activate"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkSeparatorMenuItem" id="separator2">
+		      <property name="visible">True</property>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_all_options1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show all options</property>
+		      <property name="label" translatable="yes">Show all _options</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_all_options1_activate"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkCheckMenuItem" id="show_debug_info1">
+		      <property name="visible">True</property>
+		      <property name="tooltip" translatable="yes">Show masked options</property>
+		      <property name="label" translatable="yes">Show _debug info</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="on_show_debug_info1_activate"/>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkMenuItem" id="help1">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">_Help</property>
+	      <property name="use_underline">True</property>
+
+	      <child>
+		<widget class="GtkMenu" id="help1_menu">
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="introduction1">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">_Introduction</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+		      <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image43">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-dialog-question</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="about1">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">_About</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+		      <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image44">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-properties</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkImageMenuItem" id="license1">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">_License</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+
+		      <child internal-child="image">
+			<widget class="GtkImage" id="image45">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-justify-fill</property>
+			  <property name="icon_size">1</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHandleBox" id="handlebox1">
+	  <property name="visible">True</property>
+	  <property name="shadow_type">GTK_SHADOW_OUT</property>
+	  <property name="handle_position">GTK_POS_LEFT</property>
+	  <property name="snap_edge">GTK_POS_TOP</property>
+
+	  <child>
+	    <widget class="GtkToolbar" id="toolbar1">
+	      <property name="visible">True</property>
+	      <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+	      <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
+	      <property name="tooltips">True</property>
+	      <property name="show_arrow">True</property>
+
+	      <child>
+		<widget class="GtkToolButton" id="button1">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
+		  <property name="label" translatable="yes">Back</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_id">gtk-undo</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+		  <signal name="clicked" handler="on_back_clicked"/>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolItem" id="toolitem1">
+		  <property name="visible">True</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+
+		  <child>
+		    <widget class="GtkVSeparator" id="vseparator1">
+		      <property name="visible">True</property>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolButton" id="button2">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Load a config file</property>
+		  <property name="label" translatable="yes">Load</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_id">gtk-open</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+		  <signal name="clicked" handler="on_load_clicked"/>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolButton" id="button3">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Save a config file</property>
+		  <property name="label" translatable="yes">Save</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_id">gtk-save</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+		  <signal name="clicked" handler="on_save_activate"/>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolItem" id="toolitem2">
+		  <property name="visible">True</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+
+		  <child>
+		    <widget class="GtkVSeparator" id="vseparator2">
+		      <property name="visible">True</property>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolButton" id="button4">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Single view</property>
+		  <property name="label" translatable="yes">Single</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_id">gtk-missing-image</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+		  <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolButton" id="button5">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Split view</property>
+		  <property name="label" translatable="yes">Split</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_id">gtk-missing-image</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+		  <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolButton" id="button6">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Full view</property>
+		  <property name="label" translatable="yes">Full</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_id">gtk-missing-image</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+		  <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolItem" id="toolitem3">
+		  <property name="visible">True</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+
+		  <child>
+		    <widget class="GtkVSeparator" id="vseparator3">
+		      <property name="visible">True</property>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolButton" id="button7">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
+		  <property name="label" translatable="yes">Collapse</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_id">gtk-remove</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+		  <signal name="clicked" handler="on_collapse_clicked"/>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkToolButton" id="button8">
+		  <property name="visible">True</property>
+		  <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
+		  <property name="label" translatable="yes">Expand</property>
+		  <property name="use_underline">True</property>
+		  <property name="stock_id">gtk-add</property>
+		  <property name="visible_horizontal">True</property>
+		  <property name="visible_vertical">True</property>
+		  <property name="is_important">False</property>
+		  <signal name="clicked" handler="on_expand_clicked"/>
+		</widget>
+		<packing>
+		  <property name="expand">False</property>
+		  <property name="homogeneous">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHPaned" id="hpaned1">
+	  <property name="width_request">1</property>
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="position">0</property>
+
+	  <child>
+	    <widget class="GtkScrolledWindow" id="scrolledwindow1">
+	      <property name="visible">True</property>
+	      <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+	      <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+	      <property name="shadow_type">GTK_SHADOW_IN</property>
+	      <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+	      <child>
+		<widget class="GtkTreeView" id="treeview1">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="headers_visible">True</property>
+		  <property name="rules_hint">False</property>
+		  <property name="reorderable">False</property>
+		  <property name="enable_search">True</property>
+		  <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/>
+		  <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/>
+		  <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/>
+		</widget>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="shrink">True</property>
+	      <property name="resize">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkVPaned" id="vpaned1">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="position">0</property>
+
+	      <child>
+		<widget class="GtkScrolledWindow" id="scrolledwindow2">
+		  <property name="visible">True</property>
+		  <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+		  <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+		  <property name="shadow_type">GTK_SHADOW_IN</property>
+		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+		  <child>
+		    <widget class="GtkTreeView" id="treeview2">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="has_focus">True</property>
+		      <property name="headers_visible">True</property>
+		      <property name="rules_hint">False</property>
+		      <property name="reorderable">False</property>
+		      <property name="enable_search">True</property>
+		      <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/>
+		      <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/>
+		      <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="shrink">True</property>
+		  <property name="resize">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkScrolledWindow" id="scrolledwindow3">
+		  <property name="visible">True</property>
+		  <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+		  <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+		  <property name="shadow_type">GTK_SHADOW_IN</property>
+		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+		  <child>
+		    <widget class="GtkTextView" id="textview3">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="editable">False</property>
+		      <property name="overwrite">False</property>
+		      <property name="accepts_tab">True</property>
+		      <property name="justification">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap_mode">GTK_WRAP_WORD</property>
+		      <property name="cursor_visible">True</property>
+		      <property name="pixels_above_lines">0</property>
+		      <property name="pixels_below_lines">0</property>
+		      <property name="pixels_inside_wrap">0</property>
+		      <property name="left_margin">0</property>
+		      <property name="right_margin">0</property>
+		      <property name="indent">0</property>
+		      <property name="text" translatable="yes">Sorry, no help available for this option yet.</property>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="shrink">True</property>
+		  <property name="resize">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="shrink">True</property>
+	      <property name="resize">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>

+ 326 - 0
package/config/images.c

@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+static const char *xpm_load[] = {
+"22 22 5 1",
+". c None",
+"# c #000000",
+"c c #838100",
+"a c #ffff00",
+"b c #ffffff",
+"......................",
+"......................",
+"......................",
+"............####....#.",
+"...........#....##.##.",
+"..................###.",
+".................####.",
+".####...........#####.",
+"#abab##########.......",
+"#babababababab#.......",
+"#ababababababa#.......",
+"#babababababab#.......",
+"#ababab###############",
+"#babab##cccccccccccc##",
+"#abab##cccccccccccc##.",
+"#bab##cccccccccccc##..",
+"#ab##cccccccccccc##...",
+"#b##cccccccccccc##....",
+"###cccccccccccc##.....",
+"##cccccccccccc##......",
+"###############.......",
+"......................"};
+
+static const char *xpm_save[] = {
+"22 22 5 1",
+". c None",
+"# c #000000",
+"a c #838100",
+"b c #c5c2c5",
+"c c #cdb6d5",
+"......................",
+".####################.",
+".#aa#bbbbbbbbbbbb#bb#.",
+".#aa#bbbbbbbbbbbb#bb#.",
+".#aa#bbbbbbbbbcbb####.",
+".#aa#bbbccbbbbbbb#aa#.",
+".#aa#bbbccbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aaa############aaa#.",
+".#aaaaaaaaaaaaaaaaaa#.",
+".#aaaaaaaaaaaaaaaaaa#.",
+".#aaa#############aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+"..##################..",
+"......................"};
+
+static const char *xpm_back[] = {
+"22 22 3 1",
+". c None",
+"# c #000083",
+"a c #838183",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................",
+"...........######a....",
+"..#......##########...",
+"..##...####......##a..",
+"..###.###.........##..",
+"..######..........##..",
+"..#####...........##..",
+"..######..........##..",
+"..#######.........##..",
+"..########.......##a..",
+"...............a###...",
+"...............###....",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................"};
+
+static const char *xpm_tree_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......................",
+"......................"};
+
+static const char *xpm_single_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"......................",
+"......................"};
+
+static const char *xpm_split_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......................",
+"......................"};
+
+static const char *xpm_symbol_no[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+" .......... ",
+" .        . ",
+" .        . ",
+" .        . ",
+" .        . ",
+" .        . ",
+" .        . ",
+" .        . ",
+" .        . ",
+" .......... ",
+"            "};
+
+static const char *xpm_symbol_mod[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+" .......... ",
+" .        . ",
+" .        . ",
+" .   ..   . ",
+" .  ....  . ",
+" .  ....  . ",
+" .   ..   . ",
+" .        . ",
+" .        . ",
+" .......... ",
+"            "};
+
+static const char *xpm_symbol_yes[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+" .......... ",
+" .        . ",
+" .        . ",
+" .      . . ",
+" .     .. . ",
+" . .  ..  . ",
+" . ....   . ",
+" .  ..    . ",
+" .        . ",
+" .......... ",
+"            "};
+
+static const char *xpm_choice_no[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+"    ....    ",
+"  ..    ..  ",
+"  .      .  ",
+" .        . ",
+" .        . ",
+" .        . ",
+" .        . ",
+"  .      .  ",
+"  ..    ..  ",
+"    ....    ",
+"            "};
+
+static const char *xpm_choice_yes[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+"    ....    ",
+"  ..    ..  ",
+"  .      .  ",
+" .   ..   . ",
+" .  ....  . ",
+" .  ....  . ",
+" .   ..   . ",
+"  .      .  ",
+"  ..    ..  ",
+"    ....    ",
+"            "};
+
+static const char *xpm_menu[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+" .......... ",
+" .        . ",
+" . ..     . ",
+" . ....   . ",
+" . ...... . ",
+" . ...... . ",
+" . ....   . ",
+" . ..     . ",
+" .        . ",
+" .......... ",
+"            "};
+
+static const char *xpm_menu_inv[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+" .......... ",
+" .......... ",
+" ..  ...... ",
+" ..    .... ",
+" ..      .. ",
+" ..      .. ",
+" ..    .... ",
+" ..  ...... ",
+" .......... ",
+" .......... ",
+"            "};
+
+static const char *xpm_menuback[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+" .......... ",
+" .        . ",
+" .     .. . ",
+" .   .... . ",
+" . ...... . ",
+" . ...... . ",
+" .   .... . ",
+" .     .. . ",
+" .        . ",
+" .......... ",
+"            "};
+
+static const char *xpm_void[] = {
+"12 12 2 1",
+"  c white",
+". c black",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            "};

+ 453 - 0
package/config/kconfig-to-buildroot2.patch

@@ -0,0 +1,453 @@
+--- kconfig/conf.c
++++ Buildroot/conf.c
+@@ -557,10 +557,10 @@
+ 	case ask_silent:
+ 		if (stat(".config", &tmpstat)) {
+ 			printf(_("***\n"
+-				"*** You have not yet configured your kernel!\n"
++				"*** You have not yet configured Buildroot!\n"
+ 				"***\n"
+ 				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
+-				"*** \"make menuconfig\" or \"make xconfig\").\n"
++				"*** \"make menuconfig\" or \"make config\").\n"
+ 				"***\n"));
+ 			exit(1);
+ 		}
+@@ -603,7 +603,7 @@
+ 	} else if (conf_get_changed()) {
+ 		name = getenv("KCONFIG_NOSILENTUPDATE");
+ 		if (name && *name) {
+-			fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
++			fprintf(stderr, _("\n*** Buildroot configuration requires explicit update.\n\n"));
+ 			return 1;
+ 		}
+ 	} else
+@@ -614,12 +614,12 @@
+ 		check_conf(&rootmenu);
+ 	} while (conf_cnt);
+ 	if (conf_write(NULL)) {
+-		fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
++		fprintf(stderr, _("\n*** Error during writing of the Buildroot configuration.\n\n"));
+ 		return 1;
+ 	}
+ skip_check:
+-	if (input_mode == ask_silent && conf_write_autoconf()) {
+-		fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
++	if (/*input_mode == ask_silent &&*/ conf_write_autoconf()) {
++		fprintf(stderr, _("\n*** Error during writing of the Buildroot configuration.\n\n"));
+ 		return 1;
+ 	}
+ 
+--- kconfig/confdata.c
++++ Buildroot/confdata.c
+@@ -21,7 +21,7 @@
+ static const char *conf_filename;
+ static int conf_lineno, conf_warnings, conf_unsaved;
+ 
+-const char conf_defname[] = "arch/$ARCH/defconfig";
++const char conf_defname[] = "extra/Configs/defconfigs/$ARCH";
+ 
+ static void conf_warning(const char *fmt, ...)
+ {
+@@ -150,22 +150,22 @@
+ 		sym = NULL;
+ 		switch (line[0]) {
+ 		case '#':
+-			if (memcmp(line + 2, "CONFIG_", 7))
++			if (line[1]!=' ')
+ 				continue;
+-			p = strchr(line + 9, ' ');
++			p = strchr(line + 2, ' ');
+ 			if (!p)
+ 				continue;
+ 			*p++ = 0;
+ 			if (strncmp(p, "is not set", 10))
+ 				continue;
+ 			if (def == S_DEF_USER) {
+-				sym = sym_find(line + 9);
++				sym = sym_find(line + 2);
+ 				if (!sym) {
+-					conf_warning("trying to assign nonexistent symbol %s", line + 9);
++					conf_warning("trying to assign nonexistent symbol %s", line + 2);
+ 					break;
+ 				}
+ 			} else {
+-				sym = sym_lookup(line + 9, 0);
++				sym = sym_lookup(line + 2, 0);
+ 				if (sym->type == S_UNKNOWN)
+ 					sym->type = S_BOOLEAN;
+ 			}
+@@ -183,12 +183,8 @@
+ 				;
+ 			}
+ 			break;
+-		case 'C':
+-			if (memcmp(line, "CONFIG_", 7)) {
+-				conf_warning("unexpected data");
+-				continue;
+-			}
+-			p = strchr(line + 7, '=');
++		case 'A' ... 'Z':
++			p = strchr(line, '=');
+ 			if (!p)
+ 				continue;
+ 			*p++ = 0;
+@@ -199,13 +195,13 @@
+ 					*p2 = 0;
+ 			}
+ 			if (def == S_DEF_USER) {
+-				sym = sym_find(line + 7);
++				sym = sym_find(line);
+ 				if (!sym) {
+-					conf_warning("trying to assign nonexistent symbol %s", line + 7);
++					conf_warning("trying to assign nonexistent symbol %s", line);
+ 					break;
+ 				}
+ 			} else {
+-				sym = sym_lookup(line + 7, 0);
++				sym = sym_lookup(line, 0);
+ 				if (sym->type == S_UNKNOWN)
+ 					sym->type = S_OTHER;
+ 			}
+@@ -416,7 +412,7 @@
+ 	if (!out)
+ 		return 1;
+ 
+-	sym = sym_lookup("KERNELVERSION", 0);
++	sym = sym_lookup("VERSION", 0);
+ 	sym_calc_value(sym);
+ 	time(&now);
+ 	env = getenv("KCONFIG_NOTIMESTAMP");
+@@ -425,10 +421,8 @@
+ 
+ 	fprintf(out, _("#\n"
+ 		       "# Automatically generated make config: don't edit\n"
+-		       "# Linux kernel version: %s\n"
+ 		       "%s%s"
+ 		       "#\n"),
+-		     sym_get_string_value(sym),
+ 		     use_timestamp ? "# " : "",
+ 		     use_timestamp ? ctime(&now) : "");
+ 
+@@ -462,19 +456,19 @@
+ 			case S_TRISTATE:
+ 				switch (sym_get_tristate_value(sym)) {
+ 				case no:
+-					fprintf(out, "# CONFIG_%s is not set\n", sym->name);
++					fprintf(out, "# %s is not set\n", sym->name);
+ 					break;
+ 				case mod:
+-					fprintf(out, "CONFIG_%s=m\n", sym->name);
++					fprintf(out, "%s=m\n", sym->name);
+ 					break;
+ 				case yes:
+-					fprintf(out, "CONFIG_%s=y\n", sym->name);
++					fprintf(out, "%s=y\n", sym->name);
+ 					break;
+ 				}
+ 				break;
+ 			case S_STRING:
+ 				str = sym_get_string_value(sym);
+-				fprintf(out, "CONFIG_%s=\"", sym->name);
++				fprintf(out, "%s=\"", sym->name);
+ 				while (1) {
+ 					l = strcspn(str, "\"\\");
+ 					if (l) {
+@@ -490,12 +484,12 @@
+ 			case S_HEX:
+ 				str = sym_get_string_value(sym);
+ 				if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
+-					fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
++					fprintf(out, "%s=%s\n", sym->name, str);
+ 					break;
+ 				}
+ 			case S_INT:
+ 				str = sym_get_string_value(sym);
+-				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
++				fprintf(out, "%s=%s\n", sym->name, str);
+ 				break;
+ 			}
+ 		}
+@@ -655,6 +649,8 @@
+ 	time_t now;
+ 	int i, l;
+ 
++	return 0;
++
+ 	sym_clear_all_valid();
+ 
+ 	file_write_dep("include/config/auto.conf.cmd");
+@@ -672,22 +668,19 @@
+ 		return 1;
+ 	}
+ 
+-	sym = sym_lookup("KERNELVERSION", 0);
++	sym = sym_lookup("VERSION", 0);
+ 	sym_calc_value(sym);
+ 	time(&now);
+ 	fprintf(out, "#\n"
+ 		     "# Automatically generated make config: don't edit\n"
+-		     "# Linux kernel version: %s\n"
+ 		     "# %s"
+ 		     "#\n",
+-		     sym_get_string_value(sym), ctime(&now));
++		     ctime(&now));
+ 	fprintf(out_h, "/*\n"
+ 		       " * Automatically generated C config: don't edit\n"
+-		       " * Linux kernel version: %s\n"
+ 		       " * %s"
+-		       " */\n"
+-		       "#define AUTOCONF_INCLUDED\n",
+-		       sym_get_string_value(sym), ctime(&now));
++		       " */\n",
++		       ctime(&now));
+ 
+ 	for_all_symbols(i, sym) {
+ 		sym_calc_value(sym);
+@@ -700,19 +693,19 @@
+ 			case no:
+ 				break;
+ 			case mod:
+-				fprintf(out, "CONFIG_%s=m\n", sym->name);
+-				fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
++				fprintf(out, "%s=m\n", sym->name);
++				fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
+ 				break;
+ 			case yes:
+-				fprintf(out, "CONFIG_%s=y\n", sym->name);
+-				fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
++				fprintf(out, "%s=y\n", sym->name);
++				fprintf(out_h, "#define %s 1\n", sym->name);
+ 				break;
+ 			}
+ 			break;
+ 		case S_STRING:
+ 			str = sym_get_string_value(sym);
+-			fprintf(out, "CONFIG_%s=\"", sym->name);
+-			fprintf(out_h, "#define CONFIG_%s \"", sym->name);
++			fprintf(out, "%s=\"", sym->name);
++			fprintf(out_h, "#define %s \"", sym->name);
+ 			while (1) {
+ 				l = strcspn(str, "\"\\");
+ 				if (l) {
+@@ -732,14 +725,14 @@
+ 		case S_HEX:
+ 			str = sym_get_string_value(sym);
+ 			if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
+-				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+-				fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
++				fprintf(out, "%s=%s\n", sym->name, str);
++				fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
+ 				break;
+ 			}
+ 		case S_INT:
+ 			str = sym_get_string_value(sym);
+-			fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+-			fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
++			fprintf(out, "%s=%s\n", sym->name, str);
++			fprintf(out_h, "#define %s %s\n", sym->name, str);
+ 			break;
+ 		default:
+ 			break;
+--- kconfig/gconf.c
++++ Buildroot/gconf.c
+@@ -271,8 +271,8 @@
+ 					  /*"style", PANGO_STYLE_OBLIQUE, */
+ 					  NULL);
+ 
+-	sprintf(title, _("Linux Kernel v%s Configuration"),
+-		getenv("KERNELVERSION"));
++	sprintf(title, _("Buildroot v%s Configuration"),
++		getenv("VERSION"));
+ 	gtk_window_set_title(GTK_WINDOW(main_wnd), title);
+ 
+ 	gtk_widget_show(main_wnd);
+--- kconfig/mconf.c
++++ Buildroot/mconf.c
+@@ -30,20 +30,18 @@
+ static const char mconf_readme[] = N_(
+ "Overview\n"
+ "--------\n"
+-"Some kernel features may be built directly into the kernel.\n"
+-"Some may be made into loadable runtime modules.  Some features\n"
++"Some features may be built directly into Buildroot.  Some features\n"
+ "may be completely removed altogether.  There are also certain\n"
+-"kernel parameters which are not really features, but must be\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 [*], <M> or [ ] represent features\n"
+-"configured to be built in, modularized or removed respectively.\n"
+-"Pointed brackets <> represent module capable features.\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, <M> to make it a module or\n"
+-"<N> to removed it.  You may also press the <Space Bar> to cycle\n"
+-"through the available options (ie. Y->N->M->Y).\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"
+@@ -116,7 +114,7 @@
+ "-----------------------------\n"
+ "Menuconfig supports the use of alternate configuration files for\n"
+ "those who, for various reasons, find it necessary to switch\n"
+-"between different kernel configurations.\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"
+@@ -149,7 +147,7 @@
+ "\n"
+ "Optional personality available\n"
+ "------------------------------\n"
+-"If you prefer to have all of the kernel options listed in a single\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"
+@@ -179,9 +177,9 @@
+ 	"Arrow keys navigate the menu.  "
+ 	"<Enter> selects submenus --->.  "
+ 	"Highlighted letters are hotkeys.  "
+-	"Pressing <Y> includes, <N> excludes, <M> modularizes features.  "
++	"Pressing <Y> selectes a feature, while <N> will exclude a feature.  "
+ 	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  "
+-	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable"),
++	"Legend: [*] feature is selected  [ ] feature is excluded"),
+ radiolist_instructions[] = N_(
+ 	"Use the arrow keys to navigate this window or "
+ 	"press the hotkey of the item you wish to select "
+@@ -201,18 +199,18 @@
+ 	"This feature depends on another which has been configured as a module.\n"
+ 	"As a result, this feature will be built as a module."),
+ nohelp_text[] = N_(
+-	"There is no help available for this kernel option.\n"),
++	"There is no help available for this option.\n"),
+ load_config_text[] = N_(
+ 	"Enter the name of the configuration file you wish to load.  "
+ 	"Accept the name shown to restore the configuration you "
+ 	"last retrieved.  Leave blank to abort."),
+ load_config_help[] = N_(
+ 	"\n"
+-	"For various reasons, one may wish to keep several different kernel\n"
++	"For various reasons, one may wish to keep several different Buildroot\n"
+ 	"configurations available on a single machine.\n"
+ 	"\n"
+ 	"If you have saved a previous configuration in a file other than the\n"
+-	"kernel's default, entering the name of the file here will allow you\n"
++	"Buildroot's default, entering the name of the file here will allow you\n"
+ 	"to modify that configuration.\n"
+ 	"\n"
+ 	"If you are uncertain, then you have probably never used alternate\n"
+@@ -222,7 +220,7 @@
+ 	"as an alternate.  Leave blank to abort."),
+ save_config_help[] = N_(
+ 	"\n"
+-	"For various reasons, one may wish to keep different kernel\n"
++	"For various reasons, one may wish to keep different Buildroot\n"
+ 	"configurations available on a single machine.\n"
+ 	"\n"
+ 	"Entering a file name here will allow you to later retrieve, modify\n"
+@@ -871,9 +869,9 @@
+ 	conf_parse(av[1]);
+ 	conf_read(NULL);
+ 
+-	sym = sym_lookup("KERNELVERSION", 0);
++	sym = sym_lookup("VERSION", 0);
+ 	sym_calc_value(sym);
+-	sprintf(menu_backtitle, _("Linux Kernel v%s Configuration"),
++	sprintf(menu_backtitle, _("Buildroot v%s Configuration"),
+ 		sym_get_string_value(sym));
+ 
+ 	mode = getenv("MENUCONFIG_MODE");
+@@ -893,7 +891,7 @@
+ 		if (conf_get_changed())
+ 			res = dialog_yesno(NULL,
+ 					   _("Do you wish to save your "
+-					     "new kernel configuration?\n"
++					     "new Buildroot configuration?\n"
+ 					     "<ESC><ESC> to continue."),
+ 					   6, 60);
+ 		else
+@@ -905,22 +903,22 @@
+ 	case 0:
+ 		if (conf_write(NULL)) {
+ 			fprintf(stderr, _("\n\n"
+-				"Error during writing of the kernel configuration.\n"
+-				"Your kernel configuration changes were NOT saved."
++				"Error during writing of the Buildroot configuration.\n"
++				"Your Buildroot configuration changes were NOT saved."
+ 				"\n\n"));
+ 			return 1;
+ 		}
+ 	case -1:
+ 		printf(_("\n\n"
+-			"*** End of Linux kernel configuration.\n"
+-			"*** Execute 'make' to build the kernel or try 'make help'."
++			"*** End of Buildroot configuration.\n"
++			"*** Execute 'make' to build Buildroot or try 'make help'."
+ 			"\n\n"));
+ 		break;
+ 	default:
+ 		fprintf(stderr, _("\n\n"
+-			"Your kernel configuration changes were NOT saved."
++			"Your Buildroot configuration changes were NOT saved."
+ 			"\n\n"));
+ 	}
+ 
+-	return 0;
++	return conf_write_autoconf();
+ }
+--- kconfig/symbol.c
++++ Buildroot/symbol.c
+@@ -61,10 +61,10 @@
+ 	if (p)
+ 		sym_add_default(sym, p);
+ 
+-	sym = sym_lookup("KERNELVERSION", 0);
++	sym = sym_lookup("VERSION", 0);
+ 	sym->type = S_STRING;
+ 	sym->flags |= SYMBOL_AUTO;
+-	p = getenv("KERNELVERSION");
++	p = getenv("VERSION");
+ 	if (p)
+ 		sym_add_default(sym, p);
+ 
+--- kconfig/zconf.tab.c_shipped
++++ Buildroot/zconf.tab.c_shipped
+@@ -2115,7 +2115,7 @@
+ 	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);
++	rootmenu.prompt = menu_add_prompt(P_MENU, "Buildroot Configuration", NULL);
+ 
+ #if YYDEBUG
+ 	if (getenv("ZCONF_DEBUG"))
+--- kconfig/zconf.y
++++ Buildroot/zconf.y
+@@ -484,7 +484,7 @@
+ 	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);
++	rootmenu.prompt = menu_add_prompt(P_MENU, "Buildroot Configuration", NULL);
+ 
+ #if YYDEBUG
+ 	if (getenv("ZCONF_DEBUG"))
+--- kconfig/gconf.glade	2007-06-11 20:37:06.000000000 +0200
++++ Buildroot/gconf.glade	2007-06-28 12:17:40.000000000 +0200
+@@ -5,7 +5,7 @@
+ 
+ <widget class="GtkWindow" id="window1">
+   <property name="visible">True</property>
+-  <property name="title" translatable="yes">Gtk Kernel Configurator</property>
++  <property name="title" translatable="yes">Gtk Buildroot Configurator</property>
+   <property name="type">GTK_WINDOW_TOPLEVEL</property>
+   <property name="window_position">GTK_WIN_POS_NONE</property>
+   <property name="modal">False</property>

+ 35 - 0
package/config/kconfig_load.c

@@ -0,0 +1,35 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lkc.h"
+
+#define P(name,type,arg)	type (*name ## _p) arg
+#include "lkc_proto.h"
+#undef P
+
+void kconfig_load(void)
+{
+	void *handle;
+	char *error;
+
+	handle = dlopen("./libkconfig.so", RTLD_LAZY);
+	if (!handle) {
+		handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY);
+		if (!handle) {
+			fprintf(stderr, "%s\n", dlerror());
+			exit(1);
+		}
+	}
+
+#define P(name,type,arg)			\
+{						\
+	name ## _p = dlsym(handle, #name);	\
+        if ((error = dlerror()))  {		\
+                fprintf(stderr, "%s\n", error);	\
+		exit(1);			\
+	}					\
+}
+#include "lkc_proto.h"
+#undef P
+}

+ 227 - 0
package/config/kxgettext.c

@@ -0,0 +1,227 @@
+/*
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
+ *
+ * Released under the terms of the GNU GPL v2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static char *escape(const char* text, char *bf, int len)
+{
+	char *bfp = bf;
+	int multiline = strchr(text, '\n') != NULL;
+	int eol = 0;
+	int textlen = strlen(text);
+
+	if ((textlen > 0) && (text[textlen-1] == '\n'))
+		eol = 1;
+
+	*bfp++ = '"';
+	--len;
+
+	if (multiline) {
+		*bfp++ = '"';
+		*bfp++ = '\n';
+		*bfp++ = '"';
+		len -= 3;
+	}
+
+	while (*text != '\0' && len > 1) {
+		if (*text == '"')
+			*bfp++ = '\\';
+		else if (*text == '\n') {
+			*bfp++ = '\\';
+			*bfp++ = 'n';
+			*bfp++ = '"';
+			*bfp++ = '\n';
+			*bfp++ = '"';
+			len -= 5;
+			++text;
+			goto next;
+		}
+		*bfp++ = *text++;
+next:
+		--len;
+	}
+
+	if (multiline && eol)
+		bfp -= 3;
+
+	*bfp++ = '"';
+	*bfp = '\0';
+
+	return bf;
+}
+
+struct file_line {
+	struct file_line *next;
+	char*		 file;
+	int		 lineno;
+};
+
+static struct file_line *file_line__new(char *file, int lineno)
+{
+	struct file_line *self = malloc(sizeof(*self));
+
+	if (self == NULL)
+		goto out;
+
+	self->file   = file;
+	self->lineno = lineno;
+	self->next   = NULL;
+out:
+	return self;
+}
+
+struct message {
+	const char	 *msg;
+	const char	 *option;
+	struct message	 *next;
+	struct file_line *files;
+};
+
+static struct message *message__list;
+
+static struct message *message__new(const char *msg, char *option, char *file, int lineno)
+{
+	struct message *self = malloc(sizeof(*self));
+
+	if (self == NULL)
+		goto out;
+
+	self->files = file_line__new(file, lineno);
+	if (self->files == NULL)
+		goto out_fail;
+
+	self->msg = strdup(msg);
+	if (self->msg == NULL)
+		goto out_fail_msg;
+
+	self->option = option;
+	self->next = NULL;
+out:
+	return self;
+out_fail_msg:
+	free(self->files);
+out_fail:
+	free(self);
+	self = NULL;
+	goto out;
+}
+
+static struct message *mesage__find(const char *msg)
+{
+	struct message *m = message__list;
+
+	while (m != NULL) {
+		if (strcmp(m->msg, msg) == 0)
+			break;
+		m = m->next;
+	}
+
+	return m;
+}
+
+static int message__add_file_line(struct message *self, char *file, int lineno)
+{
+	int rc = -1;
+	struct file_line *fl = file_line__new(file, lineno);
+
+	if (fl == NULL)
+		goto out;
+
+	fl->next    = self->files;
+	self->files = fl;
+	rc = 0;
+out:
+	return rc;
+}
+
+static int message__add(const char *msg, char *option, char *file, int lineno)
+{
+	int rc = 0;
+	char bf[16384];
+	char *escaped = escape(msg, bf, sizeof(bf));
+	struct message *m = mesage__find(escaped);
+
+	if (m != NULL)
+		rc = message__add_file_line(m, file, lineno);
+	else {
+		m = message__new(escaped, option, file, lineno);
+
+		if (m != NULL) {
+			m->next	      = message__list;
+			message__list = m;
+		} else
+			rc = -1;
+	}
+	return rc;
+}
+
+void menu_build_message_list(struct menu *menu)
+{
+	struct menu *child;
+
+	message__add(menu_get_prompt(menu), NULL,
+		     menu->file == NULL ? "Root Menu" : menu->file->name,
+		     menu->lineno);
+
+	if (menu->sym != NULL && menu->sym->help != NULL)
+		message__add(menu->sym->help, menu->sym->name,
+			     menu->file == NULL ? "Root Menu" : menu->file->name,
+			     menu->lineno);
+
+	for (child = menu->list; child != NULL; child = child->next)
+		if (child->prompt != NULL)
+			menu_build_message_list(child);
+}
+
+static void message__print_file_lineno(struct message *self)
+{
+	struct file_line *fl = self->files;
+
+	putchar('\n');
+	if (self->option != NULL)
+		printf("# %s:00000\n", self->option);
+
+	printf("#: %s:%d", fl->file, fl->lineno);
+	fl = fl->next;
+
+	while (fl != NULL) {
+		printf(", %s:%d", fl->file, fl->lineno);
+		fl = fl->next;
+	}
+
+	putchar('\n');
+}
+
+static void message__print_gettext_msgid_msgstr(struct message *self)
+{
+	message__print_file_lineno(self);
+
+	printf("msgid %s\n"
+	       "msgstr \"\"\n", self->msg);
+}
+
+void menu__xgettext(void)
+{
+	struct message *m = message__list;
+
+	while (m != NULL) {
+		message__print_gettext_msgid_msgstr(m);
+		m = m->next;
+	}
+}
+
+int main(int ac, char **av)
+{
+	conf_parse(av[1]);
+
+	menu_build_message_list(menu_get_root_menu(NULL));
+	menu__xgettext();
+	return 0;
+}

+ 318 - 1656
package/config/lex.zconf.c_shipped

@@ -1,5 +1,5 @@
 
 
-#line 3 "lex.zconf.c"
+#line 3 "scripts/kconfig/lex.zconf.c"
 
 
 #define  YY_INT_ALIGNED short int
 #define  YY_INT_ALIGNED short int
 
 
@@ -8,7 +8,7 @@
 #define FLEX_SCANNER
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 31
+#define YY_FLEX_SUBMINOR_VERSION 33
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #define FLEX_BETA
 #endif
 #endif
@@ -30,7 +30,15 @@
 
 
 /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 
 
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
 #include <inttypes.h>
 #include <inttypes.h>
 typedef int8_t flex_int8_t;
 typedef int8_t flex_int8_t;
 typedef uint8_t flex_uint8_t;
 typedef uint8_t flex_uint8_t;
@@ -134,6 +142,10 @@ typedef unsigned int flex_uint32_t;
 #define YY_BUF_SIZE 16384
 #define YY_BUF_SIZE 16384
 #endif
 #endif
 
 
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
 #ifndef YY_TYPEDEF_YY_BUFFER_STATE
 #ifndef YY_TYPEDEF_YY_BUFFER_STATE
 #define YY_TYPEDEF_YY_BUFFER_STATE
 #define YY_TYPEDEF_YY_BUFFER_STATE
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
@@ -267,7 +279,7 @@ int zconfleng;
 
 
 /* Points to current character in buffer. */
 /* Points to current character in buffer. */
 static char *yy_c_buf_p = (char *) 0;
 static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 1;		/* whether we need to initialize */
+static int yy_init = 0;		/* whether we need to initialize */
 static int yy_start = 0;	/* start state number */
 static int yy_start = 0;	/* start state number */
 
 
 /* Flag which is used to allow zconfwrap()'s to do buffer switches
 /* Flag which is used to allow zconfwrap()'s to do buffer switches
@@ -281,1624 +293,380 @@ YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size  );
 void zconf_delete_buffer (YY_BUFFER_STATE b  );
 void zconf_delete_buffer (YY_BUFFER_STATE b  );
 void zconf_flush_buffer (YY_BUFFER_STATE b  );
 void zconf_flush_buffer (YY_BUFFER_STATE b  );
 void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer  );
 void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void zconfpop_buffer_state (void );
-
-static void zconfensure_buffer_stack (void );
-static void zconf_load_buffer_state (void );
-static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len  );
-
-void *zconfalloc (yy_size_t  );
-void *zconfrealloc (void *,yy_size_t  );
-void zconffree (void *  );
-
-#define yy_new_buffer zconf_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        zconfensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        zconfensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define zconfwrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int zconflineno;
-
-int zconflineno = 1;
-
-extern char *zconftext;
-#define yytext_ptr zconftext
-static yyconst flex_int16_t yy_nxt[][38] =
-    {
-    {
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0
-    },
-
-    {
-       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   12
-    },
-
-    {
-       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-
-       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   12
-    },
-
-    {
-       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   18,   16,   16,   18,   18,   19,   20,
-       21,   22,   18,   18,   23,   24,   18,   25,   18,   26,
-       27,   18,   28,   29,   30,   18,   18,   16
-    },
-
-    {
-       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   18,   16,   16,   18,   18,   19,   20,
-       21,   22,   18,   18,   23,   24,   18,   25,   18,   26,
-       27,   18,   28,   29,   30,   18,   18,   16
-
-    },
-
-    {
-       11,   31,   32,   33,   31,   31,   31,   31,   31,   31,
-       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
-       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
-       31,   31,   31,   31,   31,   31,   31,   31
-    },
-
-    {
-       11,   31,   32,   33,   31,   31,   31,   31,   31,   31,
-       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
-       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
-       31,   31,   31,   31,   31,   31,   31,   31
-    },
-
-    {
-       11,   34,   34,   35,   34,   36,   34,   34,   36,   34,
-       34,   34,   34,   34,   34,   37,   34,   34,   34,   34,
-
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34
-    },
-
-    {
-       11,   34,   34,   35,   34,   36,   34,   34,   36,   34,
-       34,   34,   34,   34,   34,   37,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,   34,   34,   34,   34,   34,   34
-    },
-
-    {
-       11,   38,   38,   39,   40,   41,   42,   43,   41,   44,
-       45,   46,   47,   47,   48,   49,   47,   47,   47,   47,
-       47,   47,   47,   47,   47,   50,   47,   47,   47,   51,
-       47,   47,   47,   47,   47,   47,   47,   52
-
-    },
-
-    {
-       11,   38,   38,   39,   40,   41,   42,   43,   41,   44,
-       45,   46,   47,   47,   48,   49,   47,   47,   47,   47,
-       47,   47,   47,   47,   47,   50,   47,   47,   47,   51,
-       47,   47,   47,   47,   47,   47,   47,   52
-    },
-
-    {
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11
-    },
-
-    {
-       11,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12
-    },
-
-    {
-       11,  -13,   53,   54,  -13,  -13,   55,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13
-    },
-
-    {
-       11,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14
-
-    },
-
-    {
-       11,   56,   56,   57,   56,   56,   56,   56,   56,   56,
-       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
-       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
-       56,   56,   56,   56,   56,   56,   56,   56
-    },
-
-    {
-       11,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16
-    },
-
-    {
-       11,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17
-    },
-
-    {
-       11,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,   58,  -18,  -18,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -18
-    },
-
-    {
-       11,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
-      -19,  -19,  -19,   58,  -19,  -19,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   59,
-       58,   58,   58,   58,   58,   58,   58,  -19
-
-    },
-
-    {
-       11,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,   58,  -20,  -20,   58,   58,   58,   58,
-       58,   58,   58,   58,   60,   58,   58,   58,   58,   61,
-       58,   58,   58,   58,   58,   58,   58,  -20
-    },
-
-    {
-       11,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
-      -21,  -21,  -21,   58,  -21,  -21,   58,   58,   58,   58,
-       58,   62,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -21
-    },
-
-    {
-       11,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
-      -22,  -22,  -22,   58,  -22,  -22,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   63,   58,
-       58,   58,   58,   58,   58,   58,   58,  -22
-    },
-
-    {
-       11,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,   58,  -23,  -23,   58,   58,   58,   58,
-       58,   64,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -23
-    },
-
-    {
-       11,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,   58,  -24,  -24,   58,   58,   58,   58,
-       58,   58,   65,   58,   58,   58,   58,   58,   66,   58,
-       58,   58,   58,   58,   58,   58,   58,  -24
-
-    },
-
-    {
-       11,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,  -25,  -25,   58,  -25,  -25,   58,   67,   58,   58,
-       58,   68,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -25
-    },
-
-    {
-       11,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,   58,  -26,  -26,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       69,   58,   58,   58,   58,   58,   58,  -26
-    },
-
-    {
-       11,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,   58,  -27,  -27,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   70,   58,   58,   58,   58,  -27
-    },
-
-    {
-       11,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,   58,  -28,  -28,   58,   71,   58,   58,
-       58,   72,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -28
-    },
-
-    {
-       11,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,   58,  -29,  -29,   58,   58,   58,   58,
-       58,   73,   58,   58,   58,   58,   58,   58,   58,   74,
-       58,   58,   58,   58,   75,   58,   58,  -29
-
-    },
-
-    {
-       11,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
-      -30,  -30,  -30,   58,  -30,  -30,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   76,   58,   58,   58,   58,  -30
-    },
-
-    {
-       11,   77,   77,  -31,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       11,  -32,   78,   79,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32
-    },
-
-    {
-       11,   80,  -33,  -33,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80
-    },
-
-    {
-       11,   81,   81,   82,   81,  -34,   81,   81,  -34,   81,
-       81,   81,   81,   81,   81,  -34,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81
-
-    },
-
-    {
-       11,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
-    },
-
-    {
-       11,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
-    },
-
-    {
-       11,   83,   83,   84,   83,   83,   83,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-
-       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
-       83,   83,   83,   83,   83,   83,   83,   83
-    },
-
-    {
-       11,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
-    },
-
-    {
-       11,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39
-
-    },
-
-    {
-       11,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,   85,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40
-    },
-
-    {
-       11,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
-      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41
-    },
-
-    {
-       11,   86,   86,  -42,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86
-    },
-
-    {
-       11,  -43,  -43,  -43,  -43,  -43,  -43,   87,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43
-    },
-
-    {
-       11,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44
-
-    },
-
-    {
-       11,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
-      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45
-    },
-
-    {
-       11,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,   88,   89,   89,  -46,  -46,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,  -46
-    },
-
-    {
-       11,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
-      -47,   89,   89,   89,  -47,  -47,   89,   89,   89,   89,
-
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,  -47
-    },
-
-    {
-       11,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48
-    },
-
-    {
-       11,  -49,  -49,   90,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
-      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49
-
-    },
-
-    {
-       11,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,   89,   89,   89,  -50,  -50,   89,   89,   89,   89,
-       89,   89,   91,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,  -50
-    },
-
-    {
-       11,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,   89,   89,   89,  -51,  -51,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   92,   89,
-       89,   89,   89,   89,   89,   89,   89,  -51
-    },
-
-    {
-       11,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52,   93
-    },
-
-    {
-       11,  -53,   53,   54,  -53,  -53,   55,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
-    },
-
-    {
-       11,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
-
-    },
-
-    {
-       11,   56,   56,   57,   56,   56,   56,   56,   56,   56,
-       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
-       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
-       56,   56,   56,   56,   56,   56,   56,   56
-    },
-
-    {
-       11,   56,   56,   57,   56,   56,   56,   56,   56,   56,
-       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
-       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
-       56,   56,   56,   56,   56,   56,   56,   56
-    },
-
-    {
-       11,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57
-    },
-
-    {
-       11,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,   58,  -58,  -58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -58
-    },
-
-    {
-       11,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,   58,  -59,  -59,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   94,
-       58,   58,   58,   58,   58,   58,   58,  -59
-
-    },
-
-    {
-       11,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,  -60,  -60,   58,  -60,  -60,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   95,
-       58,   58,   58,   58,   58,   58,   58,  -60
-    },
-
-    {
-       11,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
-      -61,  -61,  -61,   58,  -61,  -61,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   96,   97,   58,
-       58,   58,   58,   58,   58,   58,   58,  -61
-    },
-
-    {
-       11,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
-      -62,  -62,  -62,   58,  -62,  -62,   58,   58,   58,   58,
-
-       58,   58,   98,   58,   58,   58,   58,   58,   58,   58,
-       99,   58,   58,   58,   58,   58,   58,  -62
-    },
-
-    {
-       11,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
-      -63,  -63,  -63,   58,  -63,  -63,   58,  100,   58,   58,
-      101,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -63
-    },
-
-    {
-       11,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
-      -64,  -64,  -64,   58,  -64,  -64,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,  102,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,  103,  -64
-
-    },
-
-    {
-       11,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
-      -65,  -65,  -65,   58,  -65,  -65,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -65
-    },
-
-    {
-       11,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
-      -66,  -66,  -66,   58,  -66,  -66,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  104,   58,   58,  -66
-    },
-
-    {
-       11,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
-      -67,  -67,  -67,   58,  -67,  -67,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,  105,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -67
-    },
-
-    {
-       11,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
-      -68,  -68,  -68,   58,  -68,  -68,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,  106,   58,
-       58,   58,   58,   58,   58,   58,   58,  -68
-    },
-
-    {
-       11,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
-      -69,  -69,  -69,   58,  -69,  -69,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  107,   58,   58,  -69
-
-    },
-
-    {
-       11,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
-      -70,  -70,  -70,   58,  -70,  -70,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,  108,
-       58,   58,   58,   58,   58,   58,   58,  -70
-    },
-
-    {
-       11,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
-      -71,  -71,  -71,   58,  -71,  -71,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,  109,   58,
-       58,   58,   58,   58,   58,   58,   58,  -71
-    },
-
-    {
-       11,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
-      -72,  -72,  -72,   58,  -72,  -72,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,  110,   58,   58,   58,   58,   58,  -72
-    },
-
-    {
-       11,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
-      -73,  -73,  -73,   58,  -73,  -73,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,  111,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -73
-    },
-
-    {
-       11,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
-      -74,  -74,  -74,   58,  -74,  -74,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  112,   58,  -74
-
-    },
-
-    {
-       11,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
-      -75,  -75,  -75,   58,  -75,  -75,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,  113,   58,   58,   58,   58,  -75
-    },
-
-    {
-       11,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
-      -76,  -76,  -76,   58,  -76,  -76,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  114,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -76
-    },
-
-    {
-       11,   77,   77,  -77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-
-       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
-       77,   77,   77,   77,   77,   77,   77,   77
-    },
-
-    {
-       11,  -78,   78,   79,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
-      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78
-    },
-
-    {
-       11,   80,  -79,  -79,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80
-
-    },
-
-    {
-       11,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
-      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
-    },
-
-    {
-       11,   81,   81,   82,   81,  -81,   81,   81,  -81,   81,
-       81,   81,   81,   81,   81,  -81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
-       81,   81,   81,   81,   81,   81,   81,   81
-    },
-
-    {
-       11,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
-      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82
-    },
-
-    {
-       11,  -83,  -83,   84,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
-      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
-    },
-
-    {
-       11,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
-      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
-
-    },
-
-    {
-       11,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
-      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
-    },
-
-    {
-       11,   86,   86,  -86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86
-    },
-
-    {
-       11,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
-      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
-    },
-
-    {
-       11,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
-      -88,  115,   89,   89,  -88,  -88,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,  -88
-    },
-
-    {
-       11,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
-      -89,   89,   89,   89,  -89,  -89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,  -89
-
-    },
-
-    {
-       11,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
-      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
-    },
-
-    {
-       11,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
-      -91,   89,   89,   89,  -91,  -91,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,  -91
-    },
-
-    {
-       11,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
-      -92,   89,   89,   89,  -92,  -92,   89,   89,   89,   89,
-
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,  -92
-    },
-
-    {
-       11,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
-      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93
-    },
-
-    {
-       11,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
-      -94,  -94,  -94,   58,  -94,  -94,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,  116,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -94
-
-    },
-
-    {
-       11,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
-      -95,  -95,  -95,   58,  -95,  -95,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  117,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -95
-    },
-
-    {
-       11,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
-      -96,  -96,  -96,   58,  -96,  -96,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  118,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -96
-    },
-
-    {
-       11,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
-      -97,  -97,  -97,   58,  -97,  -97,   58,   58,   58,   58,
-
-       58,   58,  119,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -97
-    },
-
-    {
-       11,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
-      -98,  -98,  -98,   58,  -98,  -98,  120,  121,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -98
-    },
-
-    {
-       11,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
-      -99,  -99,  -99,   58,  -99,  -99,   58,   58,   58,   58,
-       58,  122,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  -99
-
-    },
-
-    {
-       11, -100, -100, -100, -100, -100, -100, -100, -100, -100,
-     -100, -100, -100,   58, -100, -100,   58,   58,  123,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -100
-    },
-
-    {
-       11, -101, -101, -101, -101, -101, -101, -101, -101, -101,
-     -101, -101, -101,   58, -101, -101,   58,   58,   58,  124,
-       58,   58,   58,   58,   58,  125,   58,  126,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -101
-    },
-
-    {
-       11, -102, -102, -102, -102, -102, -102, -102, -102, -102,
-     -102, -102, -102,   58, -102, -102,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-      127,   58,   58,   58,   58,   58,   58, -102
-    },
-
-    {
-       11, -103, -103, -103, -103, -103, -103, -103, -103, -103,
-     -103, -103, -103,   58, -103, -103,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -103
-    },
-
-    {
-       11, -104, -104, -104, -104, -104, -104, -104, -104, -104,
-     -104, -104, -104,   58, -104, -104,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -104
-
-    },
-
-    {
-       11, -105, -105, -105, -105, -105, -105, -105, -105, -105,
-     -105, -105, -105,   58, -105, -105,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,  128,   58,
-       58,   58,   58,   58,   58,   58,   58, -105
-    },
-
-    {
-       11, -106, -106, -106, -106, -106, -106, -106, -106, -106,
-     -106, -106, -106,   58, -106, -106,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  129,   58, -106
-    },
-
-    {
-       11, -107, -107, -107, -107, -107, -107, -107, -107, -107,
-     -107, -107, -107,   58, -107, -107,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,  130,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -107
-    },
-
-    {
-       11, -108, -108, -108, -108, -108, -108, -108, -108, -108,
-     -108, -108, -108,   58, -108, -108,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  131,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -108
-    },
-
-    {
-       11, -109, -109, -109, -109, -109, -109, -109, -109, -109,
-     -109, -109, -109,   58, -109, -109,   58,   58,   58,   58,
-       58,   58,   58,  132,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -109
-
-    },
-
-    {
-       11, -110, -110, -110, -110, -110, -110, -110, -110, -110,
-     -110, -110, -110,   58, -110, -110,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  133,   58, -110
-    },
-
-    {
-       11, -111, -111, -111, -111, -111, -111, -111, -111, -111,
-     -111, -111, -111,   58, -111, -111,   58,   58,   58,   58,
-       58,  134,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -111
-    },
-
-    {
-       11, -112, -112, -112, -112, -112, -112, -112, -112, -112,
-     -112, -112, -112,   58, -112, -112,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,  135,   58,   58,   58,   58, -112
-    },
-
-    {
-       11, -113, -113, -113, -113, -113, -113, -113, -113, -113,
-     -113, -113, -113,   58, -113, -113,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  136,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -113
-    },
-
-    {
-       11, -114, -114, -114, -114, -114, -114, -114, -114, -114,
-     -114, -114, -114,   58, -114, -114,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,  137,   58,   58,   58, -114
-
-    },
-
-    {
-       11, -115, -115, -115, -115, -115, -115, -115, -115, -115,
-     -115,   89,   89,   89, -115, -115,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
-       89,   89,   89,   89,   89,   89,   89, -115
-    },
-
-    {
-       11, -116, -116, -116, -116, -116, -116, -116, -116, -116,
-     -116, -116, -116,   58, -116, -116,   58,   58,   58,   58,
-       58,  138,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -116
-    },
-
-    {
-       11, -117, -117, -117, -117, -117, -117, -117, -117, -117,
-     -117, -117, -117,   58, -117, -117,   58,   58,   58,  139,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -117
-    },
-
-    {
-       11, -118, -118, -118, -118, -118, -118, -118, -118, -118,
-     -118, -118, -118,   58, -118, -118,   58,   58,   58,   58,
-       58,  140,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -118
-    },
-
-    {
-       11, -119, -119, -119, -119, -119, -119, -119, -119, -119,
-     -119, -119, -119,   58, -119, -119,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  141,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -119
-
-    },
-
-    {
-       11, -120, -120, -120, -120, -120, -120, -120, -120, -120,
-     -120, -120, -120,   58, -120, -120,   58,   58,  142,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  143,   58,   58, -120
-    },
-
-    {
-       11, -121, -121, -121, -121, -121, -121, -121, -121, -121,
-     -121, -121, -121,   58, -121, -121,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  144,   58, -121
-    },
-
-    {
-       11, -122, -122, -122, -122, -122, -122, -122, -122, -122,
-     -122, -122, -122,   58, -122, -122,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,  145,   58,
-       58,   58,   58,   58,   58,   58,   58, -122
-    },
-
-    {
-       11, -123, -123, -123, -123, -123, -123, -123, -123, -123,
-     -123, -123, -123,   58, -123, -123,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,  146,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -123
-    },
-
-    {
-       11, -124, -124, -124, -124, -124, -124, -124, -124, -124,
-     -124, -124, -124,   58, -124, -124,   58,   58,   58,   58,
-       58,   58,   58,   58,  147,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -124
-
-    },
-
-    {
-       11, -125, -125, -125, -125, -125, -125, -125, -125, -125,
-     -125, -125, -125,   58, -125, -125,   58,   58,   58,   58,
-       58,   58,  148,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -125
-    },
-
-    {
-       11, -126, -126, -126, -126, -126, -126, -126, -126, -126,
-     -126, -126, -126,   58, -126, -126,   58,   58,   58,   58,
-       58,  149,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -126
-    },
-
-    {
-       11, -127, -127, -127, -127, -127, -127, -127, -127, -127,
-     -127, -127, -127,   58, -127, -127,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -127
-    },
-
-    {
-       11, -128, -128, -128, -128, -128, -128, -128, -128, -128,
-     -128, -128, -128,   58, -128, -128,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,  150,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -128
-    },
-
-    {
-       11, -129, -129, -129, -129, -129, -129, -129, -129, -129,
-     -129, -129, -129,   58, -129, -129,   58,   58,   58,  151,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -129
-
-    },
-
-    {
-       11, -130, -130, -130, -130, -130, -130, -130, -130, -130,
-     -130, -130, -130,   58, -130, -130,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,  152,
-       58,   58,   58,   58,   58,   58,   58, -130
-    },
-
-    {
-       11, -131, -131, -131, -131, -131, -131, -131, -131, -131,
-     -131, -131, -131,   58, -131, -131,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-      153,   58,   58,   58,   58,   58,   58, -131
-    },
-
-    {
-       11, -132, -132, -132, -132, -132, -132, -132, -132, -132,
-     -132, -132, -132,   58, -132, -132,   58,   58,   58,   58,
-
-       58,  154,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -132
-    },
-
-    {
-       11, -133, -133, -133, -133, -133, -133, -133, -133, -133,
-     -133, -133, -133,   58, -133, -133,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  155,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -133
-    },
-
-    {
-       11, -134, -134, -134, -134, -134, -134, -134, -134, -134,
-     -134, -134, -134,   58, -134, -134,   58,   58,   58,  156,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -134
-
-    },
-
-    {
-       11, -135, -135, -135, -135, -135, -135, -135, -135, -135,
-     -135, -135, -135,   58, -135, -135,   58,   58,   58,  157,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -135
-    },
-
-    {
-       11, -136, -136, -136, -136, -136, -136, -136, -136, -136,
-     -136, -136, -136,   58, -136, -136,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,  158,   58,
-       58,   58,   58,   58,   58,   58,   58, -136
-    },
-
-    {
-       11, -137, -137, -137, -137, -137, -137, -137, -137, -137,
-     -137, -137, -137,   58, -137, -137,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  159,   58,   58, -137
-    },
-
-    {
-       11, -138, -138, -138, -138, -138, -138, -138, -138, -138,
-     -138, -138, -138,   58, -138, -138,   58,  160,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -138
-    },
-
-    {
-       11, -139, -139, -139, -139, -139, -139, -139, -139, -139,
-     -139, -139, -139,   58, -139, -139,   58,   58,   58,   58,
-       58,  161,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -139
+void zconfpop_buffer_state (void );
 
 
-    },
+static void zconfensure_buffer_stack (void );
+static void zconf_load_buffer_state (void );
+static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file  );
 
 
-    {
-       11, -140, -140, -140, -140, -140, -140, -140, -140, -140,
-     -140, -140, -140,   58, -140, -140,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,  162,   58,
-       58,   58,   58,   58,   58,   58,   58, -140
-    },
+#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER )
 
 
-    {
-       11, -141, -141, -141, -141, -141, -141, -141, -141, -141,
-     -141, -141, -141,   58, -141, -141,   58,   58,   58,   58,
-       58,   58,   58,  163,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -141
-    },
+YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len  );
 
 
-    {
-       11, -142, -142, -142, -142, -142, -142, -142, -142, -142,
-     -142, -142, -142,   58, -142, -142,   58,   58,   58,   58,
+void *zconfalloc (yy_size_t  );
+void *zconfrealloc (void *,yy_size_t  );
+void zconffree (void *  );
 
 
-       58,   58,   58,   58,   58,   58,   58,   58,   58,  164,
-       58,   58,   58,   58,   58,   58,   58, -142
-    },
+#define yy_new_buffer zconf_create_buffer
 
 
-    {
-       11, -143, -143, -143, -143, -143, -143, -143, -143, -143,
-     -143, -143, -143,   58, -143, -143,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,  165,   58,   58,   58,   58, -143
-    },
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        zconfensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
 
 
-    {
-       11, -144, -144, -144, -144, -144, -144, -144, -144, -144,
-     -144, -144, -144,   58, -144, -144,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,  166,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -144
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        zconfensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
 
 
-    },
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
 
 
-    {
-       11, -145, -145, -145, -145, -145, -145, -145, -145, -145,
-     -145, -145, -145,   58, -145, -145,   58,   58,   58,   58,
-      167,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -145
-    },
+/* Begin user sect3 */
 
 
-    {
-       11, -146, -146, -146, -146, -146, -146, -146, -146, -146,
-     -146, -146, -146,   58, -146, -146,   58,   58,   58,   58,
-       58,  168,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -146
-    },
+#define zconfwrap() 1
+#define YY_SKIP_YYWRAP
 
 
-    {
-       11, -147, -147, -147, -147, -147, -147, -147, -147, -147,
-     -147, -147, -147,   58, -147, -147,   58,   58,   58,   58,
+typedef unsigned char YY_CHAR;
 
 
-       58,   58,   58,   58,   58,   58,   58,   58,   58,  169,
-       58,   58,   58,   58,   58,   58,   58, -147
-    },
+FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0;
 
 
-    {
-       11, -148, -148, -148, -148, -148, -148, -148, -148, -148,
-     -148, -148, -148,   58, -148, -148,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -148
-    },
+typedef int yy_state_type;
 
 
-    {
-       11, -149, -149, -149, -149, -149, -149, -149, -149, -149,
-     -149, -149, -149,   58, -149, -149,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,  170,   58,
-       58,   58,   58,   58,   58,   58,   58, -149
+extern int zconflineno;
 
 
-    },
+int zconflineno = 1;
 
 
+extern char *zconftext;
+#define yytext_ptr zconftext
+static yyconst flex_int16_t yy_nxt[][17] =
+    {
     {
     {
-       11, -150, -150, -150, -150, -150, -150, -150, -150, -150,
-     -150, -150, -150,   58, -150, -150,   58,   58,   58,   58,
-       58,  171,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -150
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0
     },
     },
 
 
     {
     {
-       11, -151, -151, -151, -151, -151, -151, -151, -151, -151,
-     -151, -151, -151,   58, -151, -151,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,  172,
-       58,   58,   58,   58,   58,   58,   58, -151
+       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12
     },
     },
 
 
     {
     {
-       11, -152, -152, -152, -152, -152, -152, -152, -152, -152,
-     -152, -152, -152,   58, -152, -152,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,  173,   58,
-       58,   58,   58,   58,   58,   58,   58, -152
+       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12
     },
     },
 
 
     {
     {
-       11, -153, -153, -153, -153, -153, -153, -153, -153, -153,
-     -153, -153, -153,   58, -153, -153,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  174,   58,   58, -153
+       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   18,   16,   16,   16
     },
     },
 
 
     {
     {
-       11, -154, -154, -154, -154, -154, -154, -154, -154, -154,
-     -154, -154, -154,   58, -154, -154,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -154
+       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   18,   16,   16,   16
 
 
     },
     },
 
 
     {
     {
-       11, -155, -155, -155, -155, -155, -155, -155, -155, -155,
-     -155, -155, -155,   58, -155, -155,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,  175,   58,   58,   58,   58, -155
+       11,   19,   20,   21,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   19
     },
     },
 
 
     {
     {
-       11, -156, -156, -156, -156, -156, -156, -156, -156, -156,
-     -156, -156, -156,   58, -156, -156,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  176,   58,   58, -156
+       11,   19,   20,   21,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   19
     },
     },
 
 
     {
     {
-       11, -157, -157, -157, -157, -157, -157, -157, -157, -157,
-     -157, -157, -157,   58, -157, -157,   58,   58,   58,   58,
-
-       58,  177,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -157
+       11,   22,   22,   23,   22,   24,   22,   22,   24,   22,
+       22,   22,   22,   22,   22,   25,   22
     },
     },
 
 
     {
     {
-       11, -158, -158, -158, -158, -158, -158, -158, -158, -158,
-     -158, -158, -158,   58, -158, -158,   58,   58,   58,   58,
-       58,   58,   58,  178,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -158
+       11,   22,   22,   23,   22,   24,   22,   22,   24,   22,
+       22,   22,   22,   22,   22,   25,   22
     },
     },
 
 
     {
     {
-       11, -159, -159, -159, -159, -159, -159, -159, -159, -159,
-     -159, -159, -159,   58, -159, -159,   58,  179,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -159
+       11,   26,   26,   27,   28,   29,   30,   31,   29,   32,
+       33,   34,   35,   35,   36,   37,   38
 
 
     },
     },
 
 
     {
     {
-       11, -160, -160, -160, -160, -160, -160, -160, -160, -160,
-     -160, -160, -160,   58, -160, -160,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,  180,   58,
-       58,   58,   58,   58,   58,   58,   58, -160
+       11,   26,   26,   27,   28,   29,   30,   31,   29,   32,
+       33,   34,   35,   35,   36,   37,   38
     },
     },
 
 
     {
     {
-       11, -161, -161, -161, -161, -161, -161, -161, -161, -161,
-     -161, -161, -161,   58, -161, -161,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -161
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11
     },
     },
 
 
     {
     {
-       11, -162, -162, -162, -162, -162, -162, -162, -162, -162,
-     -162, -162, -162,   58, -162, -162,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  181,   58,   58, -162
+       11,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12
     },
     },
 
 
     {
     {
-       11, -163, -163, -163, -163, -163, -163, -163, -163, -163,
-     -163, -163, -163,   58, -163, -163,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -163
+       11,  -13,   39,   40,  -13,  -13,   41,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13
     },
     },
 
 
     {
     {
-       11, -164, -164, -164, -164, -164, -164, -164, -164, -164,
-     -164, -164, -164,   58, -164, -164,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,  182,
-       58,   58,   58,   58,   58,   58,   58, -164
+       11,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14
 
 
     },
     },
 
 
     {
     {
-       11, -165, -165, -165, -165, -165, -165, -165, -165, -165,
-     -165, -165, -165,   58, -165, -165,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  183,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -165
+       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42
     },
     },
 
 
     {
     {
-       11, -166, -166, -166, -166, -166, -166, -166, -166, -166,
-     -166, -166, -166,   58, -166, -166,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  184,   58,   58, -166
+       11,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16
     },
     },
 
 
     {
     {
-       11, -167, -167, -167, -167, -167, -167, -167, -167, -167,
-     -167, -167, -167,   58, -167, -167,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,  185,   58,   58,   58, -167
+       11,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17
     },
     },
 
 
     {
     {
-       11, -168, -168, -168, -168, -168, -168, -168, -168, -168,
-     -168, -168, -168,   58, -168, -168,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -168
+       11,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,   44,  -18,  -18,  -18
     },
     },
 
 
     {
     {
-       11, -169, -169, -169, -169, -169, -169, -169, -169, -169,
-     -169, -169, -169,   58, -169, -169,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  186,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -169
+       11,   45,   45,  -19,   45,   45,   45,   45,   45,   45,
+       45,   45,   45,   45,   45,   45,   45
 
 
     },
     },
 
 
     {
     {
-       11, -170, -170, -170, -170, -170, -170, -170, -170, -170,
-     -170, -170, -170,   58, -170, -170,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  187,   58, -170
+       11,  -20,   46,   47,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20
     },
     },
 
 
     {
     {
-       11, -171, -171, -171, -171, -171, -171, -171, -171, -171,
-     -171, -171, -171,   58, -171, -171,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,  188,   58,
-       58,   58,   58,   58,   58,   58,   58, -171
+       11,   48,  -21,  -21,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48
     },
     },
 
 
     {
     {
-       11, -172, -172, -172, -172, -172, -172, -172, -172, -172,
-     -172, -172, -172,   58, -172, -172,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,  189,   58,
-       58,   58,   58,   58,   58,   58,   58, -172
+       11,   49,   49,   50,   49,  -22,   49,   49,  -22,   49,
+       49,   49,   49,   49,   49,  -22,   49
     },
     },
 
 
     {
     {
-       11, -173, -173, -173, -173, -173, -173, -173, -173, -173,
-     -173, -173, -173,   58, -173, -173,   58,  190,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -173
+       11,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23
     },
     },
 
 
     {
     {
-       11, -174, -174, -174, -174, -174, -174, -174, -174, -174,
-     -174, -174, -174,   58, -174, -174,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -174
+       11,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24
 
 
     },
     },
 
 
     {
     {
-       11, -175, -175, -175, -175, -175, -175, -175, -175, -175,
-     -175, -175, -175,   58, -175, -175,   58,   58,   58,   58,
-       58,  191,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -175
+       11,   51,   51,   52,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51
     },
     },
 
 
     {
     {
-       11, -176, -176, -176, -176, -176, -176, -176, -176, -176,
-     -176, -176, -176,   58, -176, -176,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -176
+       11,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,  -26,  -26,  -26,  -26
     },
     },
 
 
     {
     {
-       11, -177, -177, -177, -177, -177, -177, -177, -177, -177,
-     -177, -177, -177,   58, -177, -177,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -177
+       11,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27
     },
     },
 
 
     {
     {
-       11, -178, -178, -178, -178, -178, -178, -178, -178, -178,
-     -178, -178, -178,   58, -178, -178,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -178
+       11,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,   53,  -28,  -28
     },
     },
 
 
     {
     {
-       11, -179, -179, -179, -179, -179, -179, -179, -179, -179,
-     -179, -179, -179,   58, -179, -179,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  192,   58,   58, -179
+       11,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29
 
 
     },
     },
 
 
     {
     {
-       11, -180, -180, -180, -180, -180, -180, -180, -180, -180,
-     -180, -180, -180,   58, -180, -180,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -180
+       11,   54,   54,  -30,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54
     },
     },
 
 
     {
     {
-       11, -181, -181, -181, -181, -181, -181, -181, -181, -181,
-     -181, -181, -181,   58, -181, -181,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -181
+       11,  -31,  -31,  -31,  -31,  -31,  -31,   55,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31
     },
     },
 
 
     {
     {
-       11, -182, -182, -182, -182, -182, -182, -182, -182, -182,
-     -182, -182, -182,   58, -182, -182,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,  193,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -182
+       11,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32
     },
     },
 
 
     {
     {
-       11, -183, -183, -183, -183, -183, -183, -183, -183, -183,
-     -183, -183, -183,   58, -183, -183,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,  194,   58,   58,   58, -183
+       11,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33
     },
     },
 
 
     {
     {
-       11, -184, -184, -184, -184, -184, -184, -184, -184, -184,
-     -184, -184, -184,   58, -184, -184,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -184
+       11,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,   56,   57,   57,  -34,  -34,  -34
 
 
     },
     },
 
 
     {
     {
-       11, -185, -185, -185, -185, -185, -185, -185, -185, -185,
-     -185, -185, -185,   58, -185, -185,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -185
+       11,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,   57,   57,   57,  -35,  -35,  -35
     },
     },
 
 
     {
     {
-       11, -186, -186, -186, -186, -186, -186, -186, -186, -186,
-     -186, -186, -186,   58, -186, -186,   58,   58,   58,  195,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -186
+       11,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36
     },
     },
 
 
     {
     {
-       11, -187, -187, -187, -187, -187, -187, -187, -187, -187,
-     -187, -187, -187,   58, -187, -187,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -187
+       11,  -37,  -37,   58,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37
     },
     },
 
 
     {
     {
-       11, -188, -188, -188, -188, -188, -188, -188, -188, -188,
-     -188, -188, -188,   58, -188, -188,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,  196,   58, -188
+       11,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,   59
     },
     },
 
 
     {
     {
-       11, -189, -189, -189, -189, -189, -189, -189, -189, -189,
-     -189, -189, -189,   58, -189, -189,   58,   58,   58,   58,
-       58,   58,  197,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -189
+       11,  -39,   39,   40,  -39,  -39,   41,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39
 
 
     },
     },
 
 
     {
     {
-       11, -190, -190, -190, -190, -190, -190, -190, -190, -190,
-     -190, -190, -190,   58, -190, -190,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,  198,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -190
+       11,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40
     },
     },
 
 
     {
     {
-       11, -191, -191, -191, -191, -191, -191, -191, -191, -191,
-     -191, -191, -191,   58, -191, -191,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,  199,   58,   58,   58, -191
+       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42
     },
     },
 
 
     {
     {
-       11, -192, -192, -192, -192, -192, -192, -192, -192, -192,
-     -192, -192, -192,   58, -192, -192,   58,   58,   58,   58,
-
-       58,  200,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -192
+       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42
     },
     },
 
 
     {
     {
-       11, -193, -193, -193, -193, -193, -193, -193, -193, -193,
-     -193, -193, -193,   58, -193, -193,   58,   58,   58,   58,
-       58,  201,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -193
+       11,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43
     },
     },
 
 
     {
     {
-       11, -194, -194, -194, -194, -194, -194, -194, -194, -194,
-     -194, -194, -194,   58, -194, -194,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  202,   58,   58, -194
+       11,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,   44,  -44,  -44,  -44
 
 
     },
     },
 
 
     {
     {
-       11, -195, -195, -195, -195, -195, -195, -195, -195, -195,
-     -195, -195, -195,   58, -195, -195,   58,   58,   58,   58,
-       58,  203,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -195
+       11,   45,   45,  -45,   45,   45,   45,   45,   45,   45,
+       45,   45,   45,   45,   45,   45,   45
     },
     },
 
 
     {
     {
-       11, -196, -196, -196, -196, -196, -196, -196, -196, -196,
-     -196, -196, -196,   58, -196, -196,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -196
+       11,  -46,   46,   47,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46
     },
     },
 
 
     {
     {
-       11, -197, -197, -197, -197, -197, -197, -197, -197, -197,
-     -197, -197, -197,   58, -197, -197,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,  204,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -197
+       11,   48,  -47,  -47,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48
     },
     },
 
 
     {
     {
-       11, -198, -198, -198, -198, -198, -198, -198, -198, -198,
-     -198, -198, -198,   58, -198, -198,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -198
+       11,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48
     },
     },
 
 
     {
     {
-       11, -199, -199, -199, -199, -199, -199, -199, -199, -199,
-     -199, -199, -199,   58, -199, -199,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -199
+       11,   49,   49,   50,   49,  -49,   49,   49,  -49,   49,
+       49,   49,   49,   49,   49,  -49,   49
 
 
     },
     },
 
 
     {
     {
-       11, -200, -200, -200, -200, -200, -200, -200, -200, -200,
-     -200, -200, -200,   58, -200, -200,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -200
+       11,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50
     },
     },
 
 
     {
     {
-       11, -201, -201, -201, -201, -201, -201, -201, -201, -201,
-     -201, -201, -201,   58, -201, -201,   58,  205,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -201
+       11,  -51,  -51,   52,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51
     },
     },
 
 
     {
     {
-       11, -202, -202, -202, -202, -202, -202, -202, -202, -202,
-     -202, -202, -202,   58, -202, -202,   58,  206,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -202
+       11,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52
     },
     },
 
 
     {
     {
-       11, -203, -203, -203, -203, -203, -203, -203, -203, -203,
-     -203, -203, -203,   58, -203, -203,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -203
+       11,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53
     },
     },
 
 
     {
     {
-       11, -204, -204, -204, -204, -204, -204, -204, -204, -204,
-     -204, -204, -204,   58, -204, -204,   58,   58,   58,   58,
-       58,   58,   58,  207,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -204
+       11,   54,   54,  -54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54
 
 
     },
     },
 
 
     {
     {
-       11, -205, -205, -205, -205, -205, -205, -205, -205, -205,
-     -205, -205, -205,   58, -205, -205,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,  208,   58,
-       58,   58,   58,   58,   58,   58,   58, -205
+       11,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55
     },
     },
 
 
     {
     {
-       11, -206, -206, -206, -206, -206, -206, -206, -206, -206,
-     -206, -206, -206,   58, -206, -206,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,  209,   58,   58, -206
+       11,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,   60,   57,   57,  -56,  -56,  -56
     },
     },
 
 
     {
     {
-       11, -207, -207, -207, -207, -207, -207, -207, -207, -207,
-     -207, -207, -207,   58, -207, -207,   58,   58,   58,   58,
-
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -207
+       11,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,   57,   57,   57,  -57,  -57,  -57
     },
     },
 
 
     {
     {
-       11, -208, -208, -208, -208, -208, -208, -208, -208, -208,
-     -208, -208, -208,   58, -208, -208,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -208
+       11,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58
     },
     },
 
 
     {
     {
-       11, -209, -209, -209, -209, -209, -209, -209, -209, -209,
-     -209, -209, -209,   58, -209, -209,   58,   58,   58,   58,
-       58,  210,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -209
+       11,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59
 
 
     },
     },
 
 
     {
     {
-       11, -210, -210, -210, -210, -210, -210, -210, -210, -210,
-     -210, -210, -210,   58, -210, -210,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58, -210
+       11,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,   57,   57,   57,  -60,  -60,  -60
     },
     },
 
 
     } ;
     } ;
@@ -1918,8 +686,8 @@ static void yy_fatal_error (yyconst char msg[]  );
 	*yy_cp = '\0'; \
 	*yy_cp = '\0'; \
 	(yy_c_buf_p) = yy_cp;
 	(yy_c_buf_p) = yy_cp;
 
 
-#define YY_NUM_RULES 64
-#define YY_END_OF_BUFFER 65
+#define YY_NUM_RULES 33
+#define YY_END_OF_BUFFER 34
 /* This struct is not used in this scanner,
 /* This struct is not used in this scanner,
    but its presence is necessary. */
    but its presence is necessary. */
 struct yy_trans_info
 struct yy_trans_info
@@ -1927,31 +695,14 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	flex_int32_t yy_nxt;
 	};
 	};
-static yyconst flex_int16_t yy_accept[211] =
+static yyconst flex_int16_t yy_accept[61] =
     {   0,
     {   0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       65,    5,    4,    3,    2,   36,   37,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       63,   60,   62,   55,   59,   58,   57,   53,   48,   42,
-       47,   51,   53,   40,   41,   50,   50,   43,   53,   50,
-       50,   53,    4,    3,    2,    2,    1,   35,   35,   35,
-       35,   35,   35,   35,   16,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   63,   60,   62,   61,
-       55,   54,   57,   56,   44,   51,   38,   50,   50,   52,
-       45,   46,   39,   35,   35,   35,   35,   35,   35,   35,
-
-       35,   35,   30,   29,   35,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   49,   25,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   15,   35,    7,   35,
-       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   17,   35,   35,
-       35,   35,   35,   34,   35,   35,   35,   35,   35,   35,
-       10,   35,   13,   35,   35,   35,   35,   33,   35,   35,
-       35,   35,   35,   22,   35,   32,    9,   31,   35,   26,
-       12,   35,   35,   21,   18,   35,    8,   35,   35,   35,
-       35,   35,   27,   35,   35,    6,   35,   20,   19,   23,
-
-       35,   35,   11,   35,   35,   35,   14,   28,   35,   24
+       34,    5,    4,    2,    3,    7,    8,    6,   32,   29,
+       31,   24,   28,   27,   26,   22,   17,   13,   16,   20,
+       22,   11,   12,   19,   19,   14,   22,   22,    4,    2,
+        3,    3,    1,    6,   32,   29,   31,   30,   24,   23,
+       26,   25,   15,   20,    9,   19,   19,   21,   10,   18
     } ;
     } ;
 
 
 static yyconst flex_int32_t yy_ec[256] =
 static yyconst flex_int32_t yy_ec[256] =
@@ -1965,11 +716,11 @@ static yyconst flex_int32_t yy_ec[256] =
        14,    1,    1,    1,   13,   13,   13,   13,   13,   13,
        14,    1,    1,    1,   13,   13,   13,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-        1,   15,    1,    1,   16,    1,   17,   18,   19,   20,
+        1,   15,    1,    1,   13,    1,   13,   13,   13,   13,
 
 
-       21,   22,   23,   24,   25,   13,   13,   26,   27,   28,
-       29,   30,   31,   32,   33,   34,   35,   13,   13,   36,
-       13,   13,    1,   37,    1,    1,    1,    1,    1,    1,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+       13,   13,    1,   16,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -2014,8 +765,12 @@ char *zconftext;
 
 
 #define START_STRSIZE	16
 #define START_STRSIZE	16
 
 
-char *text;
-static char *text_ptr;
+static struct {
+	struct file *file;
+	int lineno;
+} current_pos;
+
+static char *text;
 static int text_size, text_asize;
 static int text_size, text_asize;
 
 
 struct buffer {
 struct buffer {
@@ -2028,29 +783,28 @@ struct buffer *current_buf;
 static int last_ts, first_ts;
 static int last_ts, first_ts;
 
 
 static void zconf_endhelp(void);
 static void zconf_endhelp(void);
-static struct buffer *zconf_endfile(void);
+static void zconf_endfile(void);
 
 
 void new_string(void)
 void new_string(void)
 {
 {
 	text = malloc(START_STRSIZE);
 	text = malloc(START_STRSIZE);
 	text_asize = START_STRSIZE;
 	text_asize = START_STRSIZE;
-	text_ptr = text;
 	text_size = 0;
 	text_size = 0;
-	*text_ptr = 0;
+	*text = 0;
 }
 }
 
 
 void append_string(const char *str, int size)
 void append_string(const char *str, int size)
 {
 {
 	int new_size = text_size + size + 1;
 	int new_size = text_size + size + 1;
 	if (new_size > text_asize) {
 	if (new_size > text_asize) {
+		new_size += START_STRSIZE - 1;
+		new_size &= -START_STRSIZE;
 		text = realloc(text, new_size);
 		text = realloc(text, new_size);
 		text_asize = new_size;
 		text_asize = new_size;
-		text_ptr = text + text_size;
 	}
 	}
-	memcpy(text_ptr, str, size);
-	text_ptr += size;
+	memcpy(text + text_size, str, size);
 	text_size += size;
 	text_size += size;
-	*text_ptr = 0;
+	text[text_size] = 0;
 }
 }
 
 
 void alloc_string(const char *str, int size)
 void alloc_string(const char *str, int size)
@@ -2066,16 +820,20 @@ void alloc_string(const char *str, int size)
 #define STRING 3
 #define STRING 3
 #define PARAM 4
 #define PARAM 4
 
 
+#ifndef YY_NO_UNISTD_H
 /* Special case for "unistd.h", since it is non-ANSI. We include it way
 /* Special case for "unistd.h", since it is non-ANSI. We include it way
  * down here because we want the user's section 1 to have been scanned first.
  * down here because we want the user's section 1 to have been scanned first.
  * The user has a chance to override it with an option.
  * The user has a chance to override it with an option.
  */
  */
 #include <unistd.h>
 #include <unistd.h>
+#endif
 
 
 #ifndef YY_EXTRA_TYPE
 #ifndef YY_EXTRA_TYPE
 #define YY_EXTRA_TYPE void *
 #define YY_EXTRA_TYPE void *
 #endif
 #endif
 
 
+static int yy_init_globals (void );
+
 /* Macros after this point can all be overridden by user definitions in
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
  * section 1.
  */
  */
@@ -2198,9 +956,9 @@ YY_DECL
 	int str = 0;
 	int str = 0;
 	int ts, i;
 	int ts, i;
 
 
-	if ( (yy_init) )
+	if ( !(yy_init) )
 		{
 		{
-		(yy_init) = 0;
+		(yy_init) = 1;
 
 
 #ifdef YY_USER_INIT
 #ifdef YY_USER_INIT
 		YY_USER_INIT;
 		YY_USER_INIT;
@@ -2254,17 +1012,17 @@ do_action:	/* This label is used only to access EOF actions. */
 	{ /* beginning of action switch */
 	{ /* beginning of action switch */
 case 1:
 case 1:
 /* rule 1 can match eol */
 /* rule 1 can match eol */
-YY_RULE_SETUP
-current_file->lineno++;
-	YY_BREAK
 case 2:
 case 2:
+/* rule 2 can match eol */
 YY_RULE_SETUP
 YY_RULE_SETUP
-
+{
+	current_file->lineno++;
+	return T_EOL;
+}
 	YY_BREAK
 	YY_BREAK
 case 3:
 case 3:
-/* rule 3 can match eol */
 YY_RULE_SETUP
 YY_RULE_SETUP
-current_file->lineno++; return T_EOL;
+
 	YY_BREAK
 	YY_BREAK
 case 4:
 case 4:
 YY_RULE_SETUP
 YY_RULE_SETUP
@@ -2282,175 +1040,63 @@ YY_RULE_SETUP
 
 
 case 6:
 case 6:
 YY_RULE_SETUP
 YY_RULE_SETUP
-BEGIN(PARAM); return T_MAINMENU;
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_MENU;
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_ENDMENU;
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_SOURCE;
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_CHOICE;
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_ENDCHOICE;
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_COMMENT;
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_CONFIG;
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_MENUCONFIG;
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_HELP;
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_IF;
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_ENDIF;
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_DEPENDS;
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_REQUIRES;
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_OPTIONAL;
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_DEFAULT;
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_PROMPT;
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_TRISTATE;
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_DEF_TRISTATE;
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_BOOLEAN;
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_BOOLEAN;
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_DEF_BOOLEAN;
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_DEF_BOOLEAN;
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_INT;
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_HEX;
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_STRING;
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_SELECT;
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_SELECT;
-	YY_BREAK
-case 34:
-YY_RULE_SETUP
-BEGIN(PARAM); return T_RANGE;
-	YY_BREAK
-case 35:
-YY_RULE_SETUP
 {
 {
+		struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
+		BEGIN(PARAM);
+		current_pos.file = current_file;
+		current_pos.lineno = current_file->lineno;
+		if (id && id->flags & TF_COMMAND) {
+			zconflval.id = id;
+			return id->token;
+		}
 		alloc_string(zconftext, zconfleng);
 		alloc_string(zconftext, zconfleng);
 		zconflval.string = text;
 		zconflval.string = text;
 		return T_WORD;
 		return T_WORD;
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 36:
+case 7:
 YY_RULE_SETUP
 YY_RULE_SETUP
 
 
 	YY_BREAK
 	YY_BREAK
-case 37:
-/* rule 37 can match eol */
+case 8:
+/* rule 8 can match eol */
 YY_RULE_SETUP
 YY_RULE_SETUP
-current_file->lineno++; BEGIN(INITIAL);
+{
+		BEGIN(INITIAL);
+		current_file->lineno++;
+		return T_EOL;
+	}
 	YY_BREAK
 	YY_BREAK
 
 
-case 38:
+case 9:
 YY_RULE_SETUP
 YY_RULE_SETUP
 return T_AND;
 return T_AND;
 	YY_BREAK
 	YY_BREAK
-case 39:
+case 10:
 YY_RULE_SETUP
 YY_RULE_SETUP
 return T_OR;
 return T_OR;
 	YY_BREAK
 	YY_BREAK
-case 40:
+case 11:
 YY_RULE_SETUP
 YY_RULE_SETUP
 return T_OPEN_PAREN;
 return T_OPEN_PAREN;
 	YY_BREAK
 	YY_BREAK
-case 41:
+case 12:
 YY_RULE_SETUP
 YY_RULE_SETUP
 return T_CLOSE_PAREN;
 return T_CLOSE_PAREN;
 	YY_BREAK
 	YY_BREAK
-case 42:
+case 13:
 YY_RULE_SETUP
 YY_RULE_SETUP
 return T_NOT;
 return T_NOT;
 	YY_BREAK
 	YY_BREAK
-case 43:
+case 14:
 YY_RULE_SETUP
 YY_RULE_SETUP
 return T_EQUAL;
 return T_EQUAL;
 	YY_BREAK
 	YY_BREAK
-case 44:
+case 15:
 YY_RULE_SETUP
 YY_RULE_SETUP
 return T_UNEQUAL;
 return T_UNEQUAL;
 	YY_BREAK
 	YY_BREAK
-case 45:
-YY_RULE_SETUP
-return T_IF;
-	YY_BREAK
-case 46:
-YY_RULE_SETUP
-return T_ON;
-	YY_BREAK
-case 47:
+case 16:
 YY_RULE_SETUP
 YY_RULE_SETUP
 {
 {
 		str = zconftext[0];
 		str = zconftext[0];
@@ -2458,33 +1104,38 @@ YY_RULE_SETUP
 		BEGIN(STRING);
 		BEGIN(STRING);
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 48:
-/* rule 48 can match eol */
+case 17:
+/* rule 17 can match eol */
 YY_RULE_SETUP
 YY_RULE_SETUP
 BEGIN(INITIAL); current_file->lineno++; return T_EOL;
 BEGIN(INITIAL); current_file->lineno++; return T_EOL;
 	YY_BREAK
 	YY_BREAK
-case 49:
+case 18:
 YY_RULE_SETUP
 YY_RULE_SETUP
 /* ignore */
 /* ignore */
 	YY_BREAK
 	YY_BREAK
-case 50:
+case 19:
 YY_RULE_SETUP
 YY_RULE_SETUP
 {
 {
+		struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
+		if (id && id->flags & TF_PARAM) {
+			zconflval.id = id;
+			return id->token;
+		}
 		alloc_string(zconftext, zconfleng);
 		alloc_string(zconftext, zconfleng);
 		zconflval.string = text;
 		zconflval.string = text;
 		return T_WORD;
 		return T_WORD;
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 51:
+case 20:
 YY_RULE_SETUP
 YY_RULE_SETUP
 /* comment */
 /* comment */
 	YY_BREAK
 	YY_BREAK
-case 52:
-/* rule 52 can match eol */
+case 21:
+/* rule 21 can match eol */
 YY_RULE_SETUP
 YY_RULE_SETUP
 current_file->lineno++;
 current_file->lineno++;
 	YY_BREAK
 	YY_BREAK
-case 53:
+case 22:
 YY_RULE_SETUP
 YY_RULE_SETUP
 
 
 	YY_BREAK
 	YY_BREAK
@@ -2494,8 +1145,8 @@ case YY_STATE_EOF(PARAM):
 	}
 	}
 	YY_BREAK
 	YY_BREAK
 
 
-case 54:
-/* rule 54 can match eol */
+case 23:
+/* rule 23 can match eol */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
 (yy_c_buf_p) = yy_cp -= 1;
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
@@ -2506,14 +1157,14 @@ YY_RULE_SETUP
 		return T_WORD_QUOTE;
 		return T_WORD_QUOTE;
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 55:
+case 24:
 YY_RULE_SETUP
 YY_RULE_SETUP
 {
 {
 		append_string(zconftext, zconfleng);
 		append_string(zconftext, zconfleng);
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 56:
-/* rule 56 can match eol */
+case 25:
+/* rule 25 can match eol */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
 (yy_c_buf_p) = yy_cp -= 1;
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
@@ -2524,13 +1175,13 @@ YY_RULE_SETUP
 		return T_WORD_QUOTE;
 		return T_WORD_QUOTE;
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 57:
+case 26:
 YY_RULE_SETUP
 YY_RULE_SETUP
 {
 {
 		append_string(zconftext + 1, zconfleng - 1);
 		append_string(zconftext + 1, zconfleng - 1);
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 58:
+case 27:
 YY_RULE_SETUP
 YY_RULE_SETUP
 {
 {
 		if (str == zconftext[0]) {
 		if (str == zconftext[0]) {
@@ -2541,8 +1192,8 @@ YY_RULE_SETUP
 			append_string(zconftext, 1);
 			append_string(zconftext, 1);
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 59:
-/* rule 59 can match eol */
+case 28:
+/* rule 28 can match eol */
 YY_RULE_SETUP
 YY_RULE_SETUP
 {
 {
 		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
 		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
@@ -2557,7 +1208,7 @@ case YY_STATE_EOF(STRING):
 	}
 	}
 	YY_BREAK
 	YY_BREAK
 
 
-case 60:
+case 29:
 YY_RULE_SETUP
 YY_RULE_SETUP
 {
 {
 		ts = 0;
 		ts = 0;
@@ -2582,8 +1233,8 @@ YY_RULE_SETUP
 		}
 		}
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 61:
-/* rule 61 can match eol */
+case 30:
+/* rule 30 can match eol */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
 (yy_c_buf_p) = yy_cp -= 1;
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
@@ -2594,15 +1245,15 @@ YY_RULE_SETUP
 		return T_HELPTEXT;
 		return T_HELPTEXT;
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 62:
-/* rule 62 can match eol */
+case 31:
+/* rule 31 can match eol */
 YY_RULE_SETUP
 YY_RULE_SETUP
 {
 {
 		current_file->lineno++;
 		current_file->lineno++;
 		append_string("\n", 1);
 		append_string("\n", 1);
 	}
 	}
 	YY_BREAK
 	YY_BREAK
-case 63:
+case 32:
 YY_RULE_SETUP
 YY_RULE_SETUP
 {
 {
 		append_string(zconftext, zconfleng);
 		append_string(zconftext, zconfleng);
@@ -2620,15 +1271,15 @@ case YY_STATE_EOF(HELP):
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(COMMAND):
 case YY_STATE_EOF(COMMAND):
 {
 {
-	if (current_buf) {
+	if (current_file) {
 		zconf_endfile();
 		zconf_endfile();
-		return T_EOF;
+		return T_EOL;
 	}
 	}
 	fclose(zconfin);
 	fclose(zconfin);
 	yyterminate();
 	yyterminate();
 }
 }
 	YY_BREAK
 	YY_BREAK
-case 64:
+case 33:
 YY_RULE_SETUP
 YY_RULE_SETUP
 YY_FATAL_ERROR( "flex scanner jammed" );
 YY_FATAL_ERROR( "flex scanner jammed" );
 	YY_BREAK
 	YY_BREAK
@@ -2815,7 +1466,7 @@ static int yy_get_next_buffer (void)
 
 
 	else
 	else
 		{
 		{
-			size_t num_to_read =
+			int num_to_read =
 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
 
 		while ( num_to_read <= 0 )
 		while ( num_to_read <= 0 )
@@ -3332,16 +1983,16 @@ YY_BUFFER_STATE zconf_scan_buffer  (char * base, yy_size_t  size )
 
 
 /** Setup the input buffer state to scan a string. The next call to zconflex() will
 /** Setup the input buffer state to scan a string. The next call to zconflex() will
  * scan from a @e copy of @a str.
  * scan from a @e copy of @a str.
- * @param str a NUL-terminated string to scan
+ * @param yystr a NUL-terminated string to scan
  * 
  * 
  * @return the newly allocated buffer state object.
  * @return the newly allocated buffer state object.
  * @note If you want to scan bytes that may contain NUL values, then use
  * @note If you want to scan bytes that may contain NUL values, then use
  *       zconf_scan_bytes() instead.
  *       zconf_scan_bytes() instead.
  */
  */
-YY_BUFFER_STATE zconf_scan_string (yyconst char * str )
+YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr )
 {
 {
     
     
-	return zconf_scan_bytes(str,strlen(str) );
+	return zconf_scan_bytes(yystr,strlen(yystr) );
 }
 }
 
 
 /** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
 /** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
@@ -3351,7 +2002,7 @@ YY_BUFFER_STATE zconf_scan_string (yyconst char * str )
  * 
  * 
  * @return the newly allocated buffer state object.
  * @return the newly allocated buffer state object.
  */
  */
-YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * bytes, int  len )
+YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
 {
 {
 	YY_BUFFER_STATE b;
 	YY_BUFFER_STATE b;
 	char *buf;
 	char *buf;
@@ -3359,15 +2010,15 @@ YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * bytes, int  len )
 	int i;
 	int i;
     
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
 	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = len + 2;
+	n = _yybytes_len + 2;
 	buf = (char *) zconfalloc(n  );
 	buf = (char *) zconfalloc(n  );
 	if ( ! buf )
 	if ( ! buf )
 		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" );
 		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" );
 
 
-	for ( i = 0; i < len; ++i )
-		buf[i] = bytes[i];
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
 
 
-	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
 
 
 	b = zconf_scan_buffer(buf,n );
 	b = zconf_scan_buffer(buf,n );
 	if ( ! b )
 	if ( ! b )
@@ -3488,6 +2139,34 @@ void zconfset_debug (int  bdebug )
         zconf_flex_debug = bdebug ;
         zconf_flex_debug = bdebug ;
 }
 }
 
 
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from zconflex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    zconfin = stdin;
+    zconfout = stdout;
+#else
+    zconfin = (FILE *) 0;
+    zconfout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * zconflex_init()
+     */
+    return 0;
+}
+
 /* zconflex_destroy is for both reentrant and non-reentrant scanners. */
 /* zconflex_destroy is for both reentrant and non-reentrant scanners. */
 int zconflex_destroy  (void)
 int zconflex_destroy  (void)
 {
 {
@@ -3503,6 +2182,10 @@ int zconflex_destroy  (void)
 	zconffree((yy_buffer_stack) );
 	zconffree((yy_buffer_stack) );
 	(yy_buffer_stack) = NULL;
 	(yy_buffer_stack) = NULL;
 
 
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * zconflex() is called, initialization will occur. */
+    yy_init_globals( );
+
     return 0;
     return 0;
 }
 }
 
 
@@ -3514,7 +2197,7 @@ int zconflex_destroy  (void)
 static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 {
 {
 	register int i;
 	register int i;
-    	for ( i = 0; i < n; ++i )
+	for ( i = 0; i < n; ++i )
 		s1[i] = s2[i];
 		s1[i] = s2[i];
 }
 }
 #endif
 #endif
@@ -3523,7 +2206,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 static int yy_flex_strlen (yyconst char * s )
 static int yy_flex_strlen (yyconst char * s )
 {
 {
 	register int n;
 	register int n;
-    	for ( n = 0; s[n]; ++n )
+	for ( n = 0; s[n]; ++n )
 		;
 		;
 
 
 	return n;
 	return n;
@@ -3554,19 +2237,6 @@ void zconffree (void * ptr )
 
 
 #define YYTABLES_NAME "yytables"
 #define YYTABLES_NAME "yytables"
 
 
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef yytext_ptr
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-
 void zconf_starthelp(void)
 void zconf_starthelp(void)
 {
 {
 	new_string();
 	new_string();
@@ -3650,7 +2320,7 @@ void zconf_nextfile(const char *name)
 	current_file = file;
 	current_file = file;
 }
 }
 
 
-static struct buffer *zconf_endfile(void)
+static void zconf_endfile(void)
 {
 {
 	struct buffer *parent;
 	struct buffer *parent;
 
 
@@ -3666,23 +2336,15 @@ static struct buffer *zconf_endfile(void)
 	}
 	}
 	free(current_buf);
 	free(current_buf);
 	current_buf = parent;
 	current_buf = parent;
-
-	return parent;
 }
 }
 
 
 int zconf_lineno(void)
 int zconf_lineno(void)
 {
 {
-	if (current_buf)
-		return current_file->lineno - 1;
-	else
-		return 0;
+	return current_pos.lineno;
 }
 }
 
 
 char *zconf_curname(void)
 char *zconf_curname(void)
 {
 {
-	if (current_buf)
-		return current_file->name;
-	else
-		return "<none>";
+	return current_pos.file ? current_pos.file->name : "<none>";
 }
 }
 
 

+ 36 - 6
package/config/lkc.h

@@ -8,6 +8,14 @@
 
 
 #include "expr.h"
 #include "expr.h"
 
 
+#ifndef KBUILD_NO_NLS
+# include <libintl.h>
+#else
+# define gettext(Msgid) ((const char *) (Msgid))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
@@ -23,6 +31,27 @@ extern "C" {
 
 
 #define SRCTREE "srctree"
 #define SRCTREE "srctree"
 
 
+#define PACKAGE "linux"
+#define LOCALEDIR "/usr/share/locale"
+
+#define _(text) gettext(text)
+#define N_(text) (text)
+
+
+#define TF_COMMAND	0x0001
+#define TF_PARAM	0x0002
+#define TF_OPTION	0x0004
+
+#define T_OPT_MODULES		1
+#define T_OPT_DEFCONFIG_LIST	2
+
+struct kconf_id {
+	int name;
+	int token;
+	unsigned int flags;
+	enum symbol_type stype;
+};
+
 int zconfparse(void);
 int zconfparse(void);
 void zconfdump(FILE *out);
 void zconfdump(FILE *out);
 
 
@@ -35,25 +64,25 @@ int zconf_lineno(void);
 char *zconf_curname(void);
 char *zconf_curname(void);
 
 
 /* confdata.c */
 /* confdata.c */
-extern const char conf_def_filename[];
-extern char conf_filename[];
-
 char *conf_get_default_confname(void);
 char *conf_get_default_confname(void);
+void sym_set_change_count(int count);
+void sym_add_change_count(int count);
 
 
 /* kconfig_load.c */
 /* kconfig_load.c */
 void kconfig_load(void);
 void kconfig_load(void);
 
 
 /* menu.c */
 /* menu.c */
 void menu_init(void);
 void menu_init(void);
-void menu_add_menu(void);
+struct menu *menu_add_menu(void);
 void menu_end_menu(void);
 void menu_end_menu(void);
 void menu_add_entry(struct symbol *sym);
 void menu_add_entry(struct symbol *sym);
 void menu_end_entry(void);
 void menu_end_entry(void);
 void menu_add_dep(struct expr *dep);
 void menu_add_dep(struct expr *dep);
 struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
 struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
-void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
+void menu_add_option(int token, char *arg);
 void menu_finalize(struct menu *parent);
 void menu_finalize(struct menu *parent);
 void menu_set_type(int type);
 void menu_set_type(int type);
 
 
@@ -75,6 +104,7 @@ const char *str_get(struct gstr *gs);
 /* symbol.c */
 /* symbol.c */
 void sym_init(void);
 void sym_init(void);
 void sym_clear_all_valid(void);
 void sym_clear_all_valid(void);
+void sym_set_all_changed(void);
 void sym_set_changed(struct symbol *sym);
 void sym_set_changed(struct symbol *sym);
 struct symbol *sym_check_deps(struct symbol *sym);
 struct symbol *sym_check_deps(struct symbol *sym);
 struct property *prop_alloc(enum prop_type type, struct symbol *sym);
 struct property *prop_alloc(enum prop_type type, struct symbol *sym);
@@ -113,7 +143,7 @@ static inline bool sym_is_optional(struct symbol *sym)
 
 
 static inline bool sym_has_value(struct symbol *sym)
 static inline bool sym_has_value(struct symbol *sym)
 {
 {
-	return sym->flags & SYMBOL_NEW ? false : true;
+	return sym->flags & SYMBOL_DEF_USER ? true : false;
 }
 }
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 5 - 2
package/config/lkc_proto.h

@@ -2,7 +2,11 @@
 /* confdata.c */
 /* confdata.c */
 P(conf_parse,void,(const char *name));
 P(conf_parse,void,(const char *name));
 P(conf_read,int,(const char *name));
 P(conf_read,int,(const char *name));
+P(conf_read_simple,int,(const char *name, int));
 P(conf_write,int,(const char *name));
 P(conf_write,int,(const char *name));
+P(conf_write_autoconf,int,(void));
+P(conf_get_changed,bool,(void));
+P(conf_set_changed_callback, void,(void (*fn)(void)));
 
 
 /* menu.c */
 /* menu.c */
 P(rootmenu,struct menu,);
 P(rootmenu,struct menu,);
@@ -14,7 +18,6 @@ P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 
 
 /* symbol.c */
 /* symbol.c */
 P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
 P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
-P(sym_change_count,int,);
 
 
 P(sym_lookup,struct symbol *,(const char *name, int isconst));
 P(sym_lookup,struct symbol *,(const char *name, int isconst));
 P(sym_find,struct symbol *,(const char *name));
 P(sym_find,struct symbol *,(const char *name));
@@ -37,4 +40,4 @@ P(prop_get_type_name,const char *,(enum prop_type type));
 
 
 /* expr.c */
 /* expr.c */
 P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
 P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
-P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken));
+P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken));

+ 84 - 0
package/config/lxdialog/check-lxdialog.sh

@@ -0,0 +1,84 @@
+#!/bin/sh
+# Check ncurses compatibility
+
+# What library to link
+ldflags()
+{
+	$cc -print-file-name=libncursesw.so | grep -q /
+	if [ $? -eq 0 ]; then
+		echo '-lncursesw'
+		exit
+	fi
+	$cc -print-file-name=libncurses.so | grep -q /
+	if [ $? -eq 0 ]; then
+		echo '-lncurses'
+		exit
+	fi
+	$cc -print-file-name=libcurses.so | grep -q /
+	if [ $? -eq 0 ]; then
+		echo '-lcurses'
+		exit
+	fi
+	exit 1
+}
+
+# Where is ncurses.h?
+ccflags()
+{
+	if [ -f /usr/include/ncurses/ncurses.h ]; then
+		echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
+	elif [ -f /usr/include/ncurses/curses.h ]; then
+		echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
+	elif [ -f /usr/include/ncurses.h ]; then
+		echo '-DCURSES_LOC="<ncurses.h>"'
+	else
+		echo '-DCURSES_LOC="<curses.h>"'
+	fi
+}
+
+# Temp file, try to clean up after us
+tmp=.lxdialog.tmp
+trap "rm -f $tmp" 0 1 2 3 15
+
+# Check if we can link to ncurses
+check() {
+	echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null
+	if [ $? != 0 ]; then
+		echo " *** Unable to find the ncurses libraries."          1>&2
+		echo " *** make menuconfig require the ncurses libraries"  1>&2
+		echo " *** "                                               1>&2
+		echo " *** Install ncurses (ncurses-devel) and try again"  1>&2
+		echo " *** "                                               1>&2
+		exit 1
+	fi
+}
+
+usage() {
+	printf "Usage: $0 [-check compiler options|-header|-library]\n"
+}
+
+if [ $# == 0 ]; then
+	usage
+	exit 1
+fi
+
+cc=""
+case "$1" in
+	"-check")
+		shift
+		cc="$@"
+		check
+		;;
+	"-ccflags")
+		ccflags
+		;;
+	"-ldflags")
+		shift
+		cc="$@"
+		ldflags
+		;;
+	"*")
+		usage
+		exit 1
+		;;
+esac

+ 270 - 317
package/config/lxdialog/checklist.c

@@ -23,350 +23,303 @@
 
 
 #include "dialog.h"
 #include "dialog.h"
 
 
-static int list_width, check_x, item_x, checkflag;
+static int list_width, check_x, item_x;
 
 
 /*
 /*
  * Print list item
  * Print list item
  */
  */
-static void
-print_item (WINDOW * win, const char *item, int status,
-	    int choice, int selected)
+static void print_item(WINDOW * win, int choice, int selected)
 {
 {
-    int i;
-
-    /* Clear 'residue' of last item */
-    wattrset (win, menubox_attr);
-    wmove (win, choice, 0);
-    for (i = 0; i < list_width; i++)
-	waddch (win, ' ');
-
-    wmove (win, choice, check_x);
-    wattrset (win, selected ? check_selected_attr : check_attr);
-    if (checkflag == FLAG_CHECK)
-	wprintw (win, "[%c]", status ? 'X' : ' ');
-    else
-	wprintw (win, "(%c)", status ? 'X' : ' ');
-
-    wattrset (win, selected ? tag_selected_attr : tag_attr);
-    mvwaddch(win, choice, item_x, item[0]);
-    wattrset (win, selected ? item_selected_attr : item_attr);
-    waddstr (win, (char *)item+1);
-    if (selected) {
-    	wmove (win, choice, check_x+1);
-    	wrefresh (win);
-    }
+	int i;
+
+	/* Clear 'residue' of last item */
+	wattrset(win, dlg.menubox.atr);
+	wmove(win, choice, 0);
+	for (i = 0; i < list_width; i++)
+		waddch(win, ' ');
+
+	wmove(win, choice, check_x);
+	wattrset(win, selected ? dlg.check_selected.atr
+		 : dlg.check.atr);
+	wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
+
+	wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
+	mvwaddch(win, choice, item_x, item_str()[0]);
+	wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
+	waddstr(win, (char *)item_str() + 1);
+	if (selected) {
+		wmove(win, choice, check_x + 1);
+		wrefresh(win);
+	}
 }
 }
 
 
 /*
 /*
  * Print the scroll indicators.
  * Print the scroll indicators.
  */
  */
-static void
-print_arrows (WINDOW * win, int choice, int item_no, int scroll,
-		int y, int x, int height)
+static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
+	     int y, int x, int height)
 {
 {
-    wmove(win, y, x);
-
-    if (scroll > 0) {
-	wattrset (win, uarrow_attr);
-	waddch (win, ACS_UARROW);
-	waddstr (win, "(-)");
-    }
-    else {
-	wattrset (win, menubox_attr);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-    }
-
-   y = y + height + 1;
-   wmove(win, y, x);
-
-   if ((height < item_no) && (scroll + choice < item_no - 1)) {
-	wattrset (win, darrow_attr);
-	waddch (win, ACS_DARROW);
-	waddstr (win, "(+)");
-    }
-    else {
-	wattrset (win, menubox_border_attr);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-   }
+	wmove(win, y, x);
+
+	if (scroll > 0) {
+		wattrset(win, dlg.uarrow.atr);
+		waddch(win, ACS_UARROW);
+		waddstr(win, "(-)");
+	} else {
+		wattrset(win, dlg.menubox.atr);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+	}
+
+	y = y + height + 1;
+	wmove(win, y, x);
+
+	if ((height < item_no) && (scroll + choice < item_no - 1)) {
+		wattrset(win, dlg.darrow.atr);
+		waddch(win, ACS_DARROW);
+		waddstr(win, "(+)");
+	} else {
+		wattrset(win, dlg.menubox_border.atr);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+	}
 }
 }
 
 
 /*
 /*
  *  Display the termination buttons
  *  Display the termination buttons
  */
  */
-static void
-print_buttons( WINDOW *dialog, int height, int width, int selected)
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
 {
 {
-    int x = width / 2 - 11;
-    int y = height - 2;
+	int x = width / 2 - 11;
+	int y = height - 2;
 
 
-    print_button (dialog, "Select", y, x, selected == 0);
-    print_button (dialog, " Help ", y, x + 14, selected == 1);
+	print_button(dialog, "Select", y, x, selected == 0);
+	print_button(dialog, " Help ", y, x + 14, selected == 1);
 
 
-    wmove(dialog, y, x+1 + 14*selected);
-    wrefresh (dialog);
+	wmove(dialog, y, x + 1 + 14 * selected);
+	wrefresh(dialog);
 }
 }
 
 
 /*
 /*
  * Display a dialog box with a list of options that can be turned on or off
  * Display a dialog box with a list of options that can be turned on or off
- * The `flag' parameter is used to select between radiolist and checklist.
+ * in the style of radiolist (only one option turned on at a time).
  */
  */
-int
-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 dialog_checklist(const char *title, const char *prompt, int height,
+		     int width, int list_height)
 {
 {
-    int i, x, y, box_x, box_y;
-    int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
-    WINDOW *dialog, *list;
-
-    checkflag = flag;
-
-    /* Allocate space for storing item on/off status */
-    if ((status = malloc (sizeof (int) * item_no)) == NULL) {
-	endwin ();
-	fprintf (stderr,
-		 "\nCan't allocate memory in dialog_checklist().\n");
-	exit (-1);
-    }
-
-    /* Initializes status */
-    for (i = 0; i < item_no; 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);
-
-    /* center dialog box on screen */
-    x = (COLS - width) / 2;
-    y = (LINES - height) / 2;
-
-    draw_shadow (stdscr, y, x, height, width);
-
-    dialog = newwin (height, width, y, x);
-    keypad (dialog, TRUE);
-
-    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
-    wattrset (dialog, border_attr);
-    mvwaddch (dialog, height-3, 0, ACS_LTEE);
-    for (i = 0; i < width - 2; i++)
-	waddch (dialog, ACS_HLINE);
-    wattrset (dialog, dialog_attr);
-    waddch (dialog, ACS_RTEE);
-
-    if (title != NULL && strlen(title) >= width-2 ) {
-	/* truncate long title -- mec */
-	char * title2 = malloc(width-2+1);
-	memcpy( title2, title, width-2 );
-	title2[width-2] = '\0';
-	title = title2;
-    }
-
-    if (title != NULL) {
-	wattrset (dialog, title_attr);
-	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
-	waddstr (dialog, (char *)title);
-	waddch (dialog, ' ');
-    }
-
-    wattrset (dialog, dialog_attr);
-    print_autowrap (dialog, prompt, width - 2, 1, 3);
-
-    list_width = width - 6;
-    box_y = height - list_height - 5;
-    box_x = (width - list_width) / 2 - 1;
-
-    /* create new window for the list */
-    list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1);
-
-    keypad (list, TRUE);
-
-    /* draw a box around the list items */
-    draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2,
-	      menubox_border_attr, menubox_attr);
-
-    /* Find length of longest item in order to center checklist */
-    check_x = 0;
-    for (i = 0; i < item_no; i++) 
-	check_x = MAX (check_x, + strlen (items[i]->name) + 4);
-
-    check_x = (list_width - check_x) / 2;
-    item_x = check_x + 4;
-
-    if (choice >= list_height) {
-	scroll = choice - list_height + 1;
-	choice -= scroll;
-    }
-
-    /* Print the list */
-    for (i = 0; i < max_choice; i++) {
-	print_item (list, items[scroll + i]->name,
-		    status[i+scroll], i, i == choice);
-    }
-
-    print_arrows(dialog, choice, item_no, scroll,
-			box_y, box_x + check_x + 5, list_height);
-
-    print_buttons(dialog, height, width, 0);
-
-    wnoutrefresh (list);
-    wnoutrefresh (dialog);
-    doupdate ();
-
-    while (key != ESC) {
-	key = wgetch (dialog);
-
-    	for (i = 0; i < max_choice; i++)
-            if (toupper(key) == toupper(items[scroll + i]->name[0]))
-                break;
-
-
-	if ( i < max_choice || key == KEY_UP || key == KEY_DOWN || 
-	    key == '+' || key == '-' ) {
-	    if (key == KEY_UP || key == '-') {
-		if (!choice) {
-		    if (!scroll)
-			continue;
-		    /* Scroll list down */
-		    if (list_height > 1) {
-			/* De-highlight current first item */
-			print_item (list, items[scroll]->name,
-					status[scroll], 0, FALSE);
-			scrollok (list, TRUE);
-			wscrl (list, -1);
-			scrollok (list, FALSE);
-		    }
-		    scroll--;
-		    print_item (list, items[scroll]->name,
-				status[scroll], 0, TRUE);
-		    wnoutrefresh (list);
-
-    		    print_arrows(dialog, choice, item_no, scroll,
-				box_y, box_x + check_x + 5, list_height);
-
-		    wrefresh (dialog);
-
-		    continue;	/* wait for another key press */
-		} else
-		    i = choice - 1;
-	    } else if (key == KEY_DOWN || key == '+') {
-		if (choice == max_choice - 1) {
-		    if (scroll + choice >= item_no - 1)
-			continue;
-		    /* Scroll list up */
-		    if (list_height > 1) {
-			/* De-highlight current last item before scrolling up */
-			print_item (list, items[scroll + max_choice - 1]->name,
-				    status[scroll + max_choice - 1],
-				    max_choice - 1, FALSE);
-			scrollok (list, TRUE);
-			scroll (list);
-			scrollok (list, FALSE);
-		    }
-		    scroll++;
-		    print_item (list, items[scroll + max_choice - 1]->name,
-				status[scroll + max_choice - 1],
-				max_choice - 1, TRUE);
-		    wnoutrefresh (list);
-
-    		    print_arrows(dialog, choice, item_no, scroll,
-				box_y, box_x + check_x + 5, list_height);
-
-		    wrefresh (dialog);
-
-		    continue;	/* wait for another key press */
-		} else
-		    i = choice + 1;
-	    }
-	    if (i != choice) {
-		/* De-highlight current item */
-		print_item (list, items[scroll + choice]->name,
-			    status[scroll + choice], choice, FALSE);
-		/* Highlight new item */
-		choice = i;
-		print_item (list, items[scroll + choice]->name,
-			    status[scroll + choice], choice, TRUE);
-		wnoutrefresh (list);
-		wrefresh (dialog);
-	    }
-	    continue;		/* wait for another key press */
-	}
-	switch (key) {
-	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;
-	case TAB:
-	case KEY_LEFT:
-	case KEY_RIGHT:
-	    button = ((key == KEY_LEFT ? --button : ++button) < 0)
-			? 1 : (button > 1 ? 0 : button);
-
-	    print_buttons(dialog, height, width, button);
-	    wrefresh (dialog);
-	    break;
-	case 'S':
-	case 's':
-	case ' ':
-	case '\n':
-	    if (!button) {
-		if (flag == FLAG_CHECK) {
-		    status[scroll + choice] = !status[scroll + choice];
-		    wmove (list, choice, check_x);
-		    wattrset (list, check_selected_attr);
-		    wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' ');
-		} else {
-		    if (!status[scroll + choice]) {
-			for (i = 0; i < item_no; i++)
-			    status[i] = 0;
-			status[scroll + choice] = 1;
-			for (i = 0; i < max_choice; i++)
-			    print_item (list, items[scroll + i]->name,
-					status[scroll + i], i, i == choice);
-		    }
+	int i, x, y, box_x, box_y;
+	int key = 0, button = 0, choice = 0, scroll = 0, max_choice;
+	WINDOW *dialog, *list;
+
+	/* which item to highlight */
+	item_foreach() {
+		if (item_is_tag('X'))
+			choice = item_n();
+		if (item_is_selected()) {
+			choice = item_n();
+			break;
 		}
 		}
-		wnoutrefresh (list);
-		wrefresh (dialog);
-            
-		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;
-	case 'X':
-	case 'x':
-	    key = ESC;
-	case ESC:
-	    break;
 	}
 	}
 
 
-	/* Now, update everything... */
-	doupdate ();
-    }
-    
+do_resize:
+	if (getmaxy(stdscr) < (height + 6))
+		return -ERRDISPLAYTOOSMALL;
+	if (getmaxx(stdscr) < (width + 6))
+		return -ERRDISPLAYTOOSMALL;
+
+	max_choice = MIN(list_height, item_count());
+
+	/* center dialog box on screen */
+	x = (COLS - width) / 2;
+	y = (LINES - height) / 2;
+
+	draw_shadow(stdscr, y, x, height, width);
+
+	dialog = newwin(height, width, y, x);
+	keypad(dialog, TRUE);
+
+	draw_box(dialog, 0, 0, height, width,
+		 dlg.dialog.atr, dlg.border.atr);
+	wattrset(dialog, dlg.border.atr);
+	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+	for (i = 0; i < width - 2; i++)
+		waddch(dialog, ACS_HLINE);
+	wattrset(dialog, dlg.dialog.atr);
+	waddch(dialog, ACS_RTEE);
+
+	print_title(dialog, title, width);
+
+	wattrset(dialog, dlg.dialog.atr);
+	print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+	list_width = width - 6;
+	box_y = height - list_height - 5;
+	box_x = (width - list_width) / 2 - 1;
+
+	/* create new window for the list */
+	list = subwin(dialog, list_height, list_width, y + box_y + 1,
+	              x + box_x + 1);
+
+	keypad(list, TRUE);
+
+	/* draw a box around the list items */
+	draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
+	         dlg.menubox_border.atr, dlg.menubox.atr);
 
 
-    delwin (dialog);
-    free (status);
-    return -1;			/* ESC pressed */
+	/* Find length of longest item in order to center checklist */
+	check_x = 0;
+	item_foreach()
+		check_x = MAX(check_x, strlen(item_str()) + 4);
+
+	check_x = (list_width - check_x) / 2;
+	item_x = check_x + 4;
+
+	if (choice >= list_height) {
+		scroll = choice - list_height + 1;
+		choice -= scroll;
+	}
+
+	/* Print the list */
+	for (i = 0; i < max_choice; i++) {
+		item_set(scroll + i);
+		print_item(list, i, i == choice);
+	}
+
+	print_arrows(dialog, choice, item_count(), scroll,
+		     box_y, box_x + check_x + 5, list_height);
+
+	print_buttons(dialog, height, width, 0);
+
+	wnoutrefresh(dialog);
+	wnoutrefresh(list);
+	doupdate();
+
+	while (key != KEY_ESC) {
+		key = wgetch(dialog);
+
+		for (i = 0; i < max_choice; i++) {
+			item_set(i + scroll);
+			if (toupper(key) == toupper(item_str()[0]))
+				break;
+		}
+
+		if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
+		    key == '+' || key == '-') {
+			if (key == KEY_UP || key == '-') {
+				if (!choice) {
+					if (!scroll)
+						continue;
+					/* Scroll list down */
+					if (list_height > 1) {
+						/* De-highlight current first item */
+						item_set(scroll);
+						print_item(list, 0, FALSE);
+						scrollok(list, TRUE);
+						wscrl(list, -1);
+						scrollok(list, FALSE);
+					}
+					scroll--;
+					item_set(scroll);
+					print_item(list, 0, TRUE);
+					print_arrows(dialog, choice, item_count(),
+						     scroll, box_y, box_x + check_x + 5, list_height);
+
+					wnoutrefresh(dialog);
+					wrefresh(list);
+
+					continue;	/* wait for another key press */
+				} else
+					i = choice - 1;
+			} else if (key == KEY_DOWN || key == '+') {
+				if (choice == max_choice - 1) {
+					if (scroll + choice >= item_count() - 1)
+						continue;
+					/* Scroll list up */
+					if (list_height > 1) {
+						/* De-highlight current last item before scrolling up */
+						item_set(scroll + max_choice - 1);
+						print_item(list,
+							    max_choice - 1,
+							    FALSE);
+						scrollok(list, TRUE);
+						wscrl(list, 1);
+						scrollok(list, FALSE);
+					}
+					scroll++;
+					item_set(scroll + max_choice - 1);
+					print_item(list, max_choice - 1, TRUE);
+
+					print_arrows(dialog, choice, item_count(),
+						     scroll, box_y, box_x + check_x + 5, list_height);
+
+					wnoutrefresh(dialog);
+					wrefresh(list);
+
+					continue;	/* wait for another key press */
+				} else
+					i = choice + 1;
+			}
+			if (i != choice) {
+				/* De-highlight current item */
+				item_set(scroll + choice);
+				print_item(list, choice, FALSE);
+				/* Highlight new item */
+				choice = i;
+				item_set(scroll + choice);
+				print_item(list, choice, TRUE);
+				wnoutrefresh(dialog);
+				wrefresh(list);
+			}
+			continue;	/* wait for another key press */
+		}
+		switch (key) {
+		case 'H':
+		case 'h':
+		case '?':
+			button = 1;
+			/* fall-through */
+		case 'S':
+		case 's':
+		case ' ':
+		case '\n':
+			item_foreach()
+				item_set_selected(0);
+			item_set(scroll + choice);
+			item_set_selected(1);
+			delwin(list);
+			delwin(dialog);
+			return button;
+		case TAB:
+		case KEY_LEFT:
+		case KEY_RIGHT:
+			button = ((key == KEY_LEFT ? --button : ++button) < 0)
+			    ? 1 : (button > 1 ? 0 : button);
+
+			print_buttons(dialog, height, width, button);
+			wrefresh(dialog);
+			break;
+		case 'X':
+		case 'x':
+			key = KEY_ESC;
+			break;
+		case KEY_ESC:
+			key = on_key_esc(dialog);
+			break;
+		case KEY_RESIZE:
+			delwin(list);
+			delwin(dialog);
+			on_key_resize();
+			goto do_resize;
+		}
+
+		/* Now, update everything... */
+		doupdate();
+	}
+	delwin(list);
+	delwin(dialog);
+	return key;		/* ESC pressed */
 }
 }

+ 116 - 91
package/config/lxdialog/dialog.h

@@ -1,4 +1,3 @@
-
 /*
 /*
  *  dialog.h -- common declarations for all dialog modules
  *  dialog.h -- common declarations for all dialog modules
  *
  *
@@ -25,8 +24,8 @@
 #include <ctype.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
+#include <stdbool.h>
 
 
-#ifdef CURSES_LOC
 #ifdef __sun__
 #ifdef __sun__
 #define CURS_MACROS
 #define CURS_MACROS
 #endif
 #endif
@@ -43,21 +42,20 @@
 #if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
 #if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
 #define OLD_NCURSES 1
 #define OLD_NCURSES 1
 #undef  wbkgdset
 #undef  wbkgdset
-#define wbkgdset(w,p) /*nothing*/
+#define wbkgdset(w,p)		/*nothing */
 #else
 #else
 #define OLD_NCURSES 0
 #define OLD_NCURSES 0
 #endif
 #endif
 
 
 #define TR(params) _tracef params
 #define TR(params) _tracef params
 
 
-#define ESC 27
+#define KEY_ESC 27
 #define TAB 9
 #define TAB 9
 #define MAX_LEN 2048
 #define MAX_LEN 2048
 #define BUF_SIZE (10*1024)
 #define BUF_SIZE (10*1024)
 #define MIN(x,y) (x < y ? x : y)
 #define MIN(x,y) (x < y ? x : y)
 #define MAX(x,y) (x > y ? x : y)
 #define MAX(x,y) (x > y ? x : y)
 
 
-
 #ifndef ACS_ULCORNER
 #ifndef ACS_ULCORNER
 #define ACS_ULCORNER '+'
 #define ACS_ULCORNER '+'
 #endif
 #endif
@@ -89,93 +87,130 @@
 #define ACS_DARROW 'v'
 #define ACS_DARROW 'v'
 #endif
 #endif
 
 
-/* 
- * Attribute names
- */
-#define screen_attr                   attributes[0]
-#define shadow_attr                   attributes[1]
-#define dialog_attr                   attributes[2]
-#define title_attr                    attributes[3]
-#define border_attr                   attributes[4]
-#define button_active_attr            attributes[5]
-#define button_inactive_attr          attributes[6]
-#define button_key_active_attr        attributes[7]
-#define button_key_inactive_attr      attributes[8]
-#define button_label_active_attr      attributes[9]
-#define button_label_inactive_attr    attributes[10]
-#define inputbox_attr                 attributes[11]
-#define inputbox_border_attr          attributes[12]
-#define searchbox_attr                attributes[13]
-#define searchbox_title_attr          attributes[14]
-#define searchbox_border_attr         attributes[15]
-#define position_indicator_attr       attributes[16]
-#define menubox_attr                  attributes[17]
-#define menubox_border_attr           attributes[18]
-#define item_attr                     attributes[19]
-#define item_selected_attr            attributes[20]
-#define tag_attr                      attributes[21]
-#define tag_selected_attr             attributes[22]
-#define tag_key_attr                  attributes[23]
-#define tag_key_selected_attr         attributes[24]
-#define check_attr                    attributes[25]
-#define check_selected_attr           attributes[26]
-#define uarrow_attr                   attributes[27]
-#define darrow_attr                   attributes[28]
-
-/* number of attributes */
-#define ATTRIBUTE_COUNT               29
+/* error return codes */
+#define ERRDISPLAYTOOSMALL (KEY_MAX + 1)
 
 
 /*
 /*
- * Global variables
+ *   Color definitions
  */
  */
-extern bool use_colors;
-
-extern chtype attributes[];
-#endif
-
-extern const char *backtitle;
+struct dialog_color {
+	chtype atr;	/* Color attribute */
+	int fg;		/* foreground */
+	int bg;		/* background */
+	int hl;		/* highlight this item */
+};
 
 
-struct dialog_list_item {
-	char *name;
-	int namelen;
-	char *tag;
-	int selected; /* Set to 1 by dialog_*() function. */
+struct dialog_info {
+	const char *backtitle;
+	struct dialog_color screen;
+	struct dialog_color shadow;
+	struct dialog_color dialog;
+	struct dialog_color title;
+	struct dialog_color border;
+	struct dialog_color button_active;
+	struct dialog_color button_inactive;
+	struct dialog_color button_key_active;
+	struct dialog_color button_key_inactive;
+	struct dialog_color button_label_active;
+	struct dialog_color button_label_inactive;
+	struct dialog_color inputbox;
+	struct dialog_color inputbox_border;
+	struct dialog_color searchbox;
+	struct dialog_color searchbox_title;
+	struct dialog_color searchbox_border;
+	struct dialog_color position_indicator;
+	struct dialog_color menubox;
+	struct dialog_color menubox_border;
+	struct dialog_color item;
+	struct dialog_color item_selected;
+	struct dialog_color tag;
+	struct dialog_color tag_selected;
+	struct dialog_color tag_key;
+	struct dialog_color tag_key_selected;
+	struct dialog_color check;
+	struct dialog_color check_selected;
+	struct dialog_color uarrow;
+	struct dialog_color darrow;
 };
 };
 
 
+/*
+ * Global variables
+ */
+extern struct dialog_info dlg;
+extern char dialog_input_result[];
+
 /*
 /*
  * Function prototypes
  * Function prototypes
  */
  */
 
 
-void init_dialog (void);
-void end_dialog (void);
-void dialog_clear (void);
-#ifdef CURSES_LOC
-void attr_clear (WINDOW * win, int height, int width, chtype attr);
-void color_setup (void);
-void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x);
-void print_button (WINDOW * win, const char *label, int y, int x, int selected);
-void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
-		chtype border);
-void draw_shadow (WINDOW * win, int y, int x, int height, int width);
-#endif
+/* item list as used by checklist and menubox */
+void item_reset(void);
+void item_make(const char *fmt, ...);
+void item_add_str(const char *fmt, ...);
+void item_set_tag(char tag);
+void item_set_data(void *p);
+void item_set_selected(int val);
+int item_activate_selected(void);
+void *item_data(void);
+char item_tag(void);
+
+/* item list manipulation for lxdialog use */
+#define MAXITEMSTR 200
+struct dialog_item {
+	char str[MAXITEMSTR];	/* promtp displayed */
+	char tag;
+	void *data;	/* pointer to menu item - used by menubox+checklist */
+	int selected;	/* Set to 1 by dialog_*() function if selected. */
+};
+
+/* list of lialog_items */
+struct dialog_list {
+	struct dialog_item node;
+	struct dialog_list *next;
+};
 
 
-int first_alpha (const char *string, const char *exempt);
-int dialog_yesno (const char *title, const char *prompt, int height, int width);
-int dialog_msgbox (const char *title, const char *prompt, int height,
-		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, 
-		struct dialog_list_item ** items);
-int 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);
-extern unsigned char dialog_input_result[];
-int dialog_inputbox (const char *title, const char *prompt, int height,
-		int width, const char *init);
-
-struct dialog_list_item *first_sel_item(int item_no,
-		struct dialog_list_item ** items);
+extern struct dialog_list *item_cur;
+extern struct dialog_list item_nil;
+extern struct dialog_list *item_head;
+
+int item_count(void);
+void item_set(int n);
+int item_n(void);
+const char *item_str(void);
+int item_is_selected(void);
+int item_is_tag(char tag);
+#define item_foreach() \
+	for (item_cur = item_head ? item_head: item_cur; \
+	     item_cur && (item_cur != &item_nil); item_cur = item_cur->next)
+
+/* generic key handlers */
+int on_key_esc(WINDOW *win);
+int on_key_resize(void);
+
+void init_dialog(const char *backtitle);
+void reset_dialog(void);
+void end_dialog(void);
+void attr_clear(WINDOW * win, int height, int width, chtype attr);
+void dialog_clear(void);
+void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x);
+void print_button(WINDOW * win, const char *label, int y, int x, int selected);
+void print_title(WINDOW *dialog, const char *title, int width);
+void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box,
+	      chtype border);
+void draw_shadow(WINDOW * win, int y, int x, int height, int width);
+
+int first_alpha(const char *string, const char *exempt);
+int dialog_yesno(const char *title, const char *prompt, int height, int width);
+int dialog_msgbox(const char *title, const char *prompt, int height,
+		  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,
+		const void *selected, int *s_scroll);
+int dialog_checklist(const char *title, const char *prompt, int height,
+		     int width, int list_height);
+extern char dialog_input_result[];
+int dialog_inputbox(const char *title, const char *prompt, int height,
+		    int width, const char *init);
 
 
 /*
 /*
  * This is the base for fictitious keys, which activate
  * This is the base for fictitious keys, which activate
@@ -186,14 +221,4 @@ struct dialog_list_item *first_sel_item(int item_no,
  *   -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
  *   -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
  *   -- uppercase chars are used to invoke the button (M_EVENT + 'O')
  *   -- uppercase chars are used to invoke the button (M_EVENT + 'O')
  */
  */
-#ifdef CURSES_LOC
 #define M_EVENT (KEY_MAX+1)
 #define M_EVENT (KEY_MAX+1)
-#endif
-
-
-/*
- * The `flag' parameter in checklist is used to select between
- * radiolist and checklist
- */
-#define FLAG_CHECK 1
-#define FLAG_RADIO 0

+ 196 - 198
package/config/lxdialog/inputbox.c

@@ -21,220 +21,218 @@
 
 
 #include "dialog.h"
 #include "dialog.h"
 
 
-unsigned char dialog_input_result[MAX_LEN + 1];
+char dialog_input_result[MAX_LEN + 1];
 
 
 /*
 /*
  *  Print the termination buttons
  *  Print the termination buttons
  */
  */
-static void
-print_buttons(WINDOW *dialog, int height, int width, int selected)
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
 {
 {
-    int x = width / 2 - 11;
-    int y = height - 2;
+	int x = width / 2 - 11;
+	int y = height - 2;
 
 
-    print_button (dialog, "  Ok  ", y, x, selected==0);
-    print_button (dialog, " Help ", y, x + 14, selected==1);
+	print_button(dialog, "  Ok  ", y, x, selected == 0);
+	print_button(dialog, " Help ", y, x + 14, selected == 1);
 
 
-    wmove(dialog, y, x+1+14*selected);
-    wrefresh(dialog);
+	wmove(dialog, y, x + 1 + 14 * selected);
+	wrefresh(dialog);
 }
 }
 
 
 /*
 /*
  * Display a dialog box for inputing a string
  * Display a dialog box for inputing a string
  */
  */
-int
-dialog_inputbox (const char *title, const char *prompt, int height, int width,
-		 const char *init)
+int dialog_inputbox(const char *title, const char *prompt, int height, int width,
+                    const char *init)
 {
 {
-    int i, x, y, box_y, box_x, box_width;
-    int input_x = 0, scroll = 0, key = 0, button = -1;
-    unsigned char *instr = dialog_input_result;
-    WINDOW *dialog;
-
-    /* center dialog box on screen */
-    x = (COLS - width) / 2;
-    y = (LINES - height) / 2;
-
-
-    draw_shadow (stdscr, y, x, height, width);
-
-    dialog = newwin (height, width, y, x);
-    keypad (dialog, TRUE);
-
-    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
-    wattrset (dialog, border_attr);
-    mvwaddch (dialog, height-3, 0, ACS_LTEE);
-    for (i = 0; i < width - 2; i++)
-	waddch (dialog, ACS_HLINE);
-    wattrset (dialog, dialog_attr);
-    waddch (dialog, ACS_RTEE);
-
-    if (title != NULL && strlen(title) >= width-2 ) {
-	/* truncate long title -- mec */
-	char * title2 = malloc(width-2+1);
-	memcpy( title2, title, width-2 );
-	title2[width-2] = '\0';
-	title = title2;
-    }
-
-    if (title != NULL) {
-	wattrset (dialog, title_attr);
-	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
-	waddstr (dialog, (char *)title);
-	waddch (dialog, ' ');
-    }
-
-    wattrset (dialog, dialog_attr);
-    print_autowrap (dialog, prompt, width - 2, 1, 3);
-
-    /* Draw the input field box */
-    box_width = width - 6;
-    getyx (dialog, y, x);
-    box_y = y + 2;
-    box_x = (width - box_width) / 2;
-    draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
-	      border_attr, dialog_attr);
-
-    print_buttons(dialog, height, width, 0);
-
-    /* Set up the initial value */
-    wmove (dialog, box_y, box_x);
-    wattrset (dialog, inputbox_attr);
-
-    if (!init)
-	instr[0] = '\0';
-    else
-	strcpy (instr, init);
-
-    input_x = strlen (instr);
-
-    if (input_x >= box_width) {
-	scroll = input_x - box_width + 1;
-	input_x = box_width - 1;
-	for (i = 0; i < box_width - 1; i++)
-	    waddch (dialog, instr[scroll + i]);
-    } else
-	waddstr (dialog, instr);
-
-    wmove (dialog, box_y, box_x + input_x);
-
-    wrefresh (dialog);
-
-    while (key != ESC) {
-	key = wgetch (dialog);
-
-	if (button == -1) {	/* Input box selected */
-	    switch (key) {
-	    case TAB:
-	    case KEY_UP:
-	    case KEY_DOWN:
-		break;
-	    case KEY_LEFT:
-		continue;
-	    case KEY_RIGHT:
-		continue;
-	    case KEY_BACKSPACE:
-	    case 127:
-		if (input_x || scroll) {
-		    wattrset (dialog, inputbox_attr);
-		    if (!input_x) {
-			scroll = scroll < box_width - 1 ?
-			    0 : scroll - (box_width - 1);
-			wmove (dialog, box_y, box_x);
-			for (i = 0; i < box_width; i++)
-			    waddch (dialog, instr[scroll + input_x + i] ?
-				    instr[scroll + input_x + i] : ' ');
-			input_x = strlen (instr) - scroll;
-		    } else
-			input_x--;
-		    instr[scroll + input_x] = '\0';
-		    mvwaddch (dialog, box_y, input_x + box_x, ' ');
-		    wmove (dialog, box_y, input_x + box_x);
-		    wrefresh (dialog);
+	int i, x, y, box_y, box_x, box_width;
+	int input_x = 0, scroll = 0, key = 0, button = -1;
+	char *instr = dialog_input_result;
+	WINDOW *dialog;
+
+	if (!init)
+		instr[0] = '\0';
+	else
+		strcpy(instr, init);
+
+do_resize:
+	if (getmaxy(stdscr) <= (height - 2))
+		return -ERRDISPLAYTOOSMALL;
+	if (getmaxx(stdscr) <= (width - 2))
+		return -ERRDISPLAYTOOSMALL;
+
+	/* center dialog box on screen */
+	x = (COLS - width) / 2;
+	y = (LINES - height) / 2;
+
+	draw_shadow(stdscr, y, x, height, width);
+
+	dialog = newwin(height, width, y, x);
+	keypad(dialog, TRUE);
+
+	draw_box(dialog, 0, 0, height, width,
+		 dlg.dialog.atr, dlg.border.atr);
+	wattrset(dialog, dlg.border.atr);
+	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+	for (i = 0; i < width - 2; i++)
+		waddch(dialog, ACS_HLINE);
+	wattrset(dialog, dlg.dialog.atr);
+	waddch(dialog, ACS_RTEE);
+
+	print_title(dialog, title, width);
+
+	wattrset(dialog, dlg.dialog.atr);
+	print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+	/* Draw the input field box */
+	box_width = width - 6;
+	getyx(dialog, y, x);
+	box_y = y + 2;
+	box_x = (width - box_width) / 2;
+	draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
+		 dlg.border.atr, dlg.dialog.atr);
+
+	print_buttons(dialog, height, width, 0);
+
+	/* Set up the initial value */
+	wmove(dialog, box_y, box_x);
+	wattrset(dialog, dlg.inputbox.atr);
+
+	input_x = strlen(instr);
+
+	if (input_x >= box_width) {
+		scroll = input_x - box_width + 1;
+		input_x = box_width - 1;
+		for (i = 0; i < box_width - 1; i++)
+			waddch(dialog, instr[scroll + i]);
+	} else {
+		waddstr(dialog, instr);
+	}
+
+	wmove(dialog, box_y, box_x + input_x);
+
+	wrefresh(dialog);
+
+	while (key != KEY_ESC) {
+		key = wgetch(dialog);
+
+		if (button == -1) {	/* Input box selected */
+			switch (key) {
+			case TAB:
+			case KEY_UP:
+			case KEY_DOWN:
+				break;
+			case KEY_LEFT:
+				continue;
+			case KEY_RIGHT:
+				continue;
+			case KEY_BACKSPACE:
+			case 127:
+				if (input_x || scroll) {
+					wattrset(dialog, dlg.inputbox.atr);
+					if (!input_x) {
+						scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1);
+						wmove(dialog, box_y, box_x);
+						for (i = 0; i < box_width; i++)
+							waddch(dialog,
+							       instr[scroll + input_x + i] ?
+							       instr[scroll + input_x + i] : ' ');
+						input_x = strlen(instr) - scroll;
+					} else
+						input_x--;
+					instr[scroll + input_x] = '\0';
+					mvwaddch(dialog, box_y, input_x + box_x, ' ');
+					wmove(dialog, box_y, input_x + box_x);
+					wrefresh(dialog);
+				}
+				continue;
+			default:
+				if (key < 0x100 && isprint(key)) {
+					if (scroll + input_x < MAX_LEN) {
+						wattrset(dialog, dlg.inputbox.atr);
+						instr[scroll + input_x] = key;
+						instr[scroll + input_x + 1] = '\0';
+						if (input_x == box_width - 1) {
+							scroll++;
+							wmove(dialog, box_y, box_x);
+							for (i = 0; i < box_width - 1; i++)
+								waddch(dialog, instr [scroll + i]);
+						} else {
+							wmove(dialog, box_y, input_x++ + box_x);
+							waddch(dialog, key);
+						}
+						wrefresh(dialog);
+					} else
+						flash();	/* Alarm user about overflow */
+					continue;
+				}
+			}
 		}
 		}
-		continue;
-	    default:
-		if (key < 0x100 && isprint (key)) {
-		    if (scroll + input_x < MAX_LEN) {
-			wattrset (dialog, inputbox_attr);
-			instr[scroll + input_x] = key;
-			instr[scroll + input_x + 1] = '\0';
-			if (input_x == box_width - 1) {
-			    scroll++;
-			    wmove (dialog, box_y, box_x);
-			    for (i = 0; i < box_width - 1; i++)
-				waddch (dialog, instr[scroll + i]);
-			} else {
-			    wmove (dialog, box_y, input_x++ + box_x);
-			    waddch (dialog, key);
+		switch (key) {
+		case 'O':
+		case 'o':
+			delwin(dialog);
+			return 0;
+		case 'H':
+		case 'h':
+			delwin(dialog);
+			return 1;
+		case KEY_UP:
+		case KEY_LEFT:
+			switch (button) {
+			case -1:
+				button = 1;	/* Indicates "Cancel" button is selected */
+				print_buttons(dialog, height, width, 1);
+				break;
+			case 0:
+				button = -1;	/* Indicates input box is selected */
+				print_buttons(dialog, height, width, 0);
+				wmove(dialog, box_y, box_x + input_x);
+				wrefresh(dialog);
+				break;
+			case 1:
+				button = 0;	/* Indicates "OK" button is selected */
+				print_buttons(dialog, height, width, 0);
+				break;
 			}
 			}
-			wrefresh (dialog);
-		    } else
-			flash ();	/* Alarm user about overflow */
-		    continue;
+			break;
+		case TAB:
+		case KEY_DOWN:
+		case KEY_RIGHT:
+			switch (button) {
+			case -1:
+				button = 0;	/* Indicates "OK" button is selected */
+				print_buttons(dialog, height, width, 0);
+				break;
+			case 0:
+				button = 1;	/* Indicates "Cancel" button is selected */
+				print_buttons(dialog, height, width, 1);
+				break;
+			case 1:
+				button = -1;	/* Indicates input box is selected */
+				print_buttons(dialog, height, width, 0);
+				wmove(dialog, box_y, box_x + input_x);
+				wrefresh(dialog);
+				break;
+			}
+			break;
+		case ' ':
+		case '\n':
+			delwin(dialog);
+			return (button == -1 ? 0 : button);
+		case 'X':
+		case 'x':
+			key = KEY_ESC;
+			break;
+		case KEY_ESC:
+			key = on_key_esc(dialog);
+			break;
+		case KEY_RESIZE:
+			delwin(dialog);
+			on_key_resize();
+			goto do_resize;
 		}
 		}
-	    }
-	}
-	switch (key) {
-	case 'O':
-	case 'o':
-	    delwin (dialog);
-	    return 0;
-	case 'H':
-	case 'h':
-	    delwin (dialog);
-	    return 1;
-	case KEY_UP:
-	case KEY_LEFT:
-	    switch (button) {
-	    case -1:
-		button = 1;	/* Indicates "Cancel" button is selected */
-		print_buttons(dialog, height, width, 1);
-		break;
-	    case 0:
-		button = -1;	/* Indicates input box is selected */
-		print_buttons(dialog, height, width, 0);
-		wmove (dialog, box_y, box_x + input_x);
-		wrefresh (dialog);
-		break;
-	    case 1:
-		button = 0;	/* Indicates "OK" button is selected */
-		print_buttons(dialog, height, width, 0);
-		break;
-	    }
-	    break;
-	case TAB:
-	case KEY_DOWN:
-	case KEY_RIGHT:
-	    switch (button) {
-	    case -1:
-		button = 0;	/* Indicates "OK" button is selected */
-		print_buttons(dialog, height, width, 0);
-		break;
-	    case 0:
-		button = 1;	/* Indicates "Cancel" button is selected */
-		print_buttons(dialog, height, width, 1);
-		break;
-	    case 1:
-		button = -1;	/* Indicates input box is selected */
-		print_buttons(dialog, height, width, 0);
-		wmove (dialog, box_y, box_x + input_x);
-		wrefresh (dialog);
-		break;
-	    }
-	    break;
-	case ' ':
-	case '\n':
-	    delwin (dialog);
-	    return (button == -1 ? 0 : button);
-	case 'X':
-	case 'x':
-	    key = ESC;
-	case ESC:
-	    break;
 	}
 	}
-    }
 
 
-    delwin (dialog);
-    return -1;			/* ESC pressed */
+	delwin(dialog);
+	return KEY_ESC;		/* ESC pressed */
 }
 }

+ 334 - 338
package/config/lxdialog/menubox.c

@@ -63,376 +63,372 @@ static int menu_width, item_x;
 /*
 /*
  * Print menu item
  * Print menu item
  */
  */
-static void
-print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
+static void do_print_item(WINDOW * win, const char *item, int line_y,
+                          int selected, int hotkey)
 {
 {
-    int j;
-    char menu_item[menu_width+1];
+	int j;
+	char *menu_item = malloc(menu_width + 1);
 
 
-    strncpy(menu_item, item, menu_width);
-    menu_item[menu_width] = 0;
-    j = first_alpha(menu_item, "YyNnMmHh");
+	strncpy(menu_item, item, menu_width - item_x);
+	menu_item[menu_width - item_x] = '\0';
+	j = first_alpha(menu_item, "YyNnMmHh");
 
 
-    /* Clear 'residue' of last item */
-    wattrset (win, menubox_attr);
-    wmove (win, choice, 0);
+	/* Clear 'residue' of last item */
+	wattrset(win, dlg.menubox.atr);
+	wmove(win, line_y, 0);
 #if OLD_NCURSES
 #if OLD_NCURSES
-    {
-        int i;
-        for (i = 0; i < menu_width; i++)
-	    waddch (win, ' ');
-    }
+	{
+		int i;
+		for (i = 0; i < menu_width; i++)
+			waddch(win, ' ');
+	}
 #else
 #else
-    wclrtoeol(win);
+	wclrtoeol(win);
 #endif
 #endif
-    wattrset (win, selected ? item_selected_attr : item_attr);
-    mvwaddstr (win, choice, item_x, menu_item);
-    if (hotkey) {
-    	wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
-    	mvwaddch(win, choice, item_x+j, menu_item[j]);
-    }
-    if (selected) {
-	wmove (win, choice, item_x+1);
-	wrefresh (win);
-    }
+	wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
+	mvwaddstr(win, line_y, item_x, menu_item);
+	if (hotkey) {
+		wattrset(win, selected ? dlg.tag_key_selected.atr
+			 : dlg.tag_key.atr);
+		mvwaddch(win, line_y, item_x + j, menu_item[j]);
+	}
+	if (selected) {
+		wmove(win, line_y, item_x + 1);
+	}
+	free(menu_item);
+	wrefresh(win);
 }
 }
 
 
+#define print_item(index, choice, selected)				\
+do {									\
+	item_set(index);						\
+	do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
+} while (0)
+
 /*
 /*
  * Print the scroll indicators.
  * Print the scroll indicators.
  */
  */
-static void
-print_arrows (WINDOW * win, int item_no, int scroll,
-		int y, int x, int height)
+static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
+			 int height)
 {
 {
-    int cur_y, cur_x;
-
-    getyx(win, cur_y, cur_x);
-
-    wmove(win, y, x);
-
-    if (scroll > 0) {
-	wattrset (win, uarrow_attr);
-	waddch (win, ACS_UARROW);
-	waddstr (win, "(-)");
-    }
-    else {
-	wattrset (win, menubox_attr);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-    }
-
-   y = y + height + 1;
-   wmove(win, y, x);
-
-   if ((height < item_no) && (scroll + height < item_no)) {
-	wattrset (win, darrow_attr);
-	waddch (win, ACS_DARROW);
-	waddstr (win, "(+)");
-    }
-    else {
-	wattrset (win, menubox_border_attr);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-	waddch (win, ACS_HLINE);
-   }
-
-   wmove(win, cur_y, cur_x);
+	int cur_y, cur_x;
+
+	getyx(win, cur_y, cur_x);
+
+	wmove(win, y, x);
+
+	if (scroll > 0) {
+		wattrset(win, dlg.uarrow.atr);
+		waddch(win, ACS_UARROW);
+		waddstr(win, "(-)");
+	} else {
+		wattrset(win, dlg.menubox.atr);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+	}
+
+	y = y + height + 1;
+	wmove(win, y, x);
+	wrefresh(win);
+
+	if ((height < item_no) && (scroll + height < item_no)) {
+		wattrset(win, dlg.darrow.atr);
+		waddch(win, ACS_DARROW);
+		waddstr(win, "(+)");
+	} else {
+		wattrset(win, dlg.menubox_border.atr);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+		waddch(win, ACS_HLINE);
+	}
+
+	wmove(win, cur_y, cur_x);
+	wrefresh(win);
 }
 }
 
 
 /*
 /*
  * Display the termination buttons.
  * Display the termination buttons.
  */
  */
-static void
-print_buttons (WINDOW *win, int height, int width, int selected)
+static void print_buttons(WINDOW * win, int height, int width, int selected)
 {
 {
-    int x = width / 2 - 16;
-    int y = height - 2;
+	int x = width / 2 - 16;
+	int y = height - 2;
+
+	print_button(win, "Select", y, x, selected == 0);
+	print_button(win, " Exit ", y, x + 12, selected == 1);
+	print_button(win, " Help ", y, x + 24, selected == 2);
 
 
-    print_button (win, "Select", y, x, selected == 0);
-    print_button (win, " Exit ", y, x + 12, selected == 1);
-    print_button (win, " Help ", y, x + 24, selected == 2);
+	wmove(win, y, x + 1 + 12 * selected);
+	wrefresh(win);
+}
 
 
-    wmove(win, y, x+1+12*selected);
-    wrefresh (win);
+/* scroll up n lines (n may be negative) */
+static void do_scroll(WINDOW *win, int *scroll, int n)
+{
+	/* Scroll menu up */
+	scrollok(win, TRUE);
+	wscrl(win, n);
+	scrollok(win, FALSE);
+	*scroll = *scroll + n;
+	wrefresh(win);
 }
 }
 
 
 /*
 /*
  * Display a menu for choosing among a number of options
  * Display a menu for choosing among a number of options
  */
  */
-int
-dialog_menu (const char *title, const char *prompt, int height, int width,
-		int menu_height, const char *current, int item_no,
-		struct dialog_list_item ** items)
+int dialog_menu(const char *title, const char *prompt,
+                const void *selected, int *s_scroll)
 {
 {
-    int i, j, x, y, box_x, box_y;
-    int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
-    WINDOW *dialog, *menu;
-    FILE *f;
-
-    max_choice = MIN (menu_height, item_no);
-
-    /* center dialog box on screen */
-    x = (COLS - width) / 2;
-    y = (LINES - height) / 2;
-
-    draw_shadow (stdscr, y, x, height, width);
-
-    dialog = newwin (height, width, y, x);
-    keypad (dialog, TRUE);
-
-    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
-    wattrset (dialog, border_attr);
-    mvwaddch (dialog, height - 3, 0, ACS_LTEE);
-    for (i = 0; i < width - 2; i++)
-	waddch (dialog, ACS_HLINE);
-    wattrset (dialog, dialog_attr);
-    wbkgdset (dialog, dialog_attr & A_COLOR);
-    waddch (dialog, ACS_RTEE);
-
-    if (title != NULL && strlen(title) >= width-2 ) {
-	/* truncate long title -- mec */
-	char * title2 = malloc(width-2+1);
-	memcpy( title2, title, width-2 );
-	title2[width-2] = '\0';
-	title = title2;
-    }
-
-    if (title != NULL) {
-	wattrset (dialog, title_attr);
-	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
-	waddstr (dialog, (char *)title);
-	waddch (dialog, ' ');
-    }
-
-    wattrset (dialog, dialog_attr);
-    print_autowrap (dialog, prompt, width - 2, 1, 3);
-
-    menu_width = width - 6;
-    box_y = height - menu_height - 5;
-    box_x = (width - menu_width) / 2 - 1;
-
-    /* create new window for the menu */
-    menu = subwin (dialog, menu_height, menu_width,
-		y + box_y + 1, x + box_x + 1);
-    keypad (menu, TRUE);
-
-    /* draw a box around the menu items */
-    draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
-	      menubox_border_attr, menubox_attr);
-
-    /*
-     * Find length of longest item in order to center menu.
-     * Set 'choice' to default item. 
-     */
-    item_x = 0;
-    for (i = 0; i < item_no; i++) {
-	item_x = MAX (item_x, MIN(menu_width, strlen (items[i]->name) + 2));
-	if (strcmp(current, items[i]->tag) == 0) choice = i;
-    }
-
-    item_x = (menu_width - item_x) / 2;
-
-    /* get the scroll info from the temp file */
-    if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) {
-	if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) &&
-	     (scroll+max_choice > choice) && (scroll >= 0) &&
-	     (scroll+max_choice <= item_no) ) {
-	    first_item = scroll;
-	    choice = choice - scroll;
-	    fclose(f);
+	int i, j, x, y, box_x, box_y;
+	int height, width, menu_height;
+	int key = 0, button = 0, scroll = 0, choice = 0;
+	int first_item =  0, max_choice;
+	WINDOW *dialog, *menu;
+
+do_resize:
+	height = getmaxy(stdscr);
+	width = getmaxx(stdscr);
+	if (height < 15 || width < 65)
+		return -ERRDISPLAYTOOSMALL;
+
+	height -= 4;
+	width  -= 5;
+	menu_height = height - 10;
+
+	max_choice = MIN(menu_height, item_count());
+
+	/* center dialog box on screen */
+	x = (COLS - width) / 2;
+	y = (LINES - height) / 2;
+
+	draw_shadow(stdscr, y, x, height, width);
+
+	dialog = newwin(height, width, y, x);
+	keypad(dialog, TRUE);
+
+	draw_box(dialog, 0, 0, height, width,
+		 dlg.dialog.atr, dlg.border.atr);
+	wattrset(dialog, dlg.border.atr);
+	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+	for (i = 0; i < width - 2; i++)
+		waddch(dialog, ACS_HLINE);
+	wattrset(dialog, dlg.dialog.atr);
+	wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
+	waddch(dialog, ACS_RTEE);
+
+	print_title(dialog, title, width);
+
+	wattrset(dialog, dlg.dialog.atr);
+	print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+	menu_width = width - 6;
+	box_y = height - menu_height - 5;
+	box_x = (width - menu_width) / 2 - 1;
+
+	/* create new window for the menu */
+	menu = subwin(dialog, menu_height, menu_width,
+		      y + box_y + 1, x + box_x + 1);
+	keypad(menu, TRUE);
+
+	/* draw a box around the menu items */
+	draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
+		 dlg.menubox_border.atr, dlg.menubox.atr);
+
+	if (menu_width >= 80)
+		item_x = (menu_width - 70) / 2;
+	else
+		item_x = 4;
+
+	/* Set choice to default item */
+	item_foreach()
+		if (selected && (selected == item_data()))
+			choice = item_n();
+	/* get the saved scroll info */
+	scroll = *s_scroll;
+	if ((scroll <= choice) && (scroll + max_choice > choice) &&
+	   (scroll >= 0) && (scroll + max_choice <= item_count())) {
+		first_item = scroll;
+		choice = choice - scroll;
 	} else {
 	} else {
-	    scroll=0;
-	    remove("lxdialog.scrltmp");
-	    fclose(f);
-	    f=NULL;
+		scroll = 0;
+	}
+	if ((choice >= max_choice)) {
+		if (choice >= item_count() - max_choice / 2)
+			scroll = first_item = item_count() - max_choice;
+		else
+			scroll = first_item = choice - max_choice / 2;
+		choice = choice - scroll;
 	}
 	}
-    }
-    if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
-	if (choice >= item_no-max_choice/2)
-	    scroll = first_item = item_no-max_choice;
-	else
-	    scroll = first_item = choice - max_choice/2;
-	choice = choice - scroll;
-    }
-
-    /* Print the menu */
-    for (i=0; i < max_choice; i++) {
-	print_item (menu, items[first_item + i]->name, i, i == choice,
-                    (items[first_item + i]->tag[0] != ':'));
-    }
-
-    wnoutrefresh (menu);
-
-    print_arrows(dialog, item_no, scroll,
-		 box_y, box_x+item_x+1, menu_height);
-
-    print_buttons (dialog, height, width, 0);
-    wmove (menu, choice, item_x+1);
-    wrefresh (menu);
 
 
-    while (key != ESC) {
-	key = wgetch(menu);
+	/* Print the menu */
+	for (i = 0; i < max_choice; i++) {
+		print_item(first_item + i, i, i == choice);
+	}
 
 
-	if (key < 256 && isalpha(key)) key = tolower(key);
+	wnoutrefresh(menu);
+
+	print_arrows(dialog, item_count(), scroll,
+		     box_y, box_x + item_x + 1, menu_height);
+
+	print_buttons(dialog, height, width, 0);
+	wmove(menu, choice, item_x + 1);
+	wrefresh(menu);
+
+	while (key != KEY_ESC) {
+		key = wgetch(menu);
+
+		if (key < 256 && isalpha(key))
+			key = tolower(key);
+
+		if (strchr("ynmh", key))
+			i = max_choice;
+		else {
+			for (i = choice + 1; i < max_choice; i++) {
+				item_set(scroll + i);
+				j = first_alpha(item_str(), "YyNnMmHh");
+				if (key == tolower(item_str()[j]))
+					break;
+			}
+			if (i == max_choice)
+				for (i = 0; i < max_choice; i++) {
+					item_set(scroll + i);
+					j = first_alpha(item_str(), "YyNnMmHh");
+					if (key == tolower(item_str()[j]))
+						break;
+				}
+		}
 
 
-	if (strchr("ynmh", key))
-		i = max_choice;
-	else {
-        for (i = choice+1; i < max_choice; i++) {
-		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, "YyNnMmHh");
-			if (key == tolower(items[scroll + i]->name[j]))
-                		break;
+		if (i < max_choice ||
+		    key == KEY_UP || key == KEY_DOWN ||
+		    key == '-' || key == '+' ||
+		    key == KEY_PPAGE || key == KEY_NPAGE) {
+			/* Remove highligt of current item */
+			print_item(scroll + choice, choice, FALSE);
+
+			if (key == KEY_UP || key == '-') {
+				if (choice < 2 && scroll) {
+					/* Scroll menu down */
+					do_scroll(menu, &scroll, -1);
+
+					print_item(scroll, 0, FALSE);
+				} else
+					choice = MAX(choice - 1, 0);
+
+			} else if (key == KEY_DOWN || key == '+') {
+				print_item(scroll+choice, choice, FALSE);
+
+				if ((choice > max_choice - 3) &&
+				    (scroll + max_choice < item_count())) {
+					/* Scroll menu up */
+					do_scroll(menu, &scroll, 1);
+
+					print_item(scroll+max_choice - 1,
+						   max_choice - 1, FALSE);
+				} else
+					choice = MIN(choice + 1, max_choice - 1);
+
+			} else if (key == KEY_PPAGE) {
+				scrollok(menu, TRUE);
+				for (i = 0; (i < max_choice); i++) {
+					if (scroll > 0) {
+						do_scroll(menu, &scroll, -1);
+						print_item(scroll, 0, FALSE);
+					} else {
+						if (choice > 0)
+							choice--;
+					}
+				}
+
+			} else if (key == KEY_NPAGE) {
+				for (i = 0; (i < max_choice); i++) {
+					if (scroll + max_choice < item_count()) {
+						do_scroll(menu, &scroll, 1);
+						print_item(scroll+max_choice-1,
+							   max_choice - 1, FALSE);
+					} else {
+						if (choice + 1 < max_choice)
+							choice++;
+					}
+				}
+			} else
+				choice = i;
+
+			print_item(scroll + choice, choice, TRUE);
+
+			print_arrows(dialog, item_count(), scroll,
+				     box_y, box_x + item_x + 1, menu_height);
+
+			wnoutrefresh(dialog);
+			wrefresh(menu);
+
+			continue;	/* wait for another key press */
 		}
 		}
-	}
 
 
-	if (i < max_choice || 
-            key == KEY_UP || key == KEY_DOWN ||
-            key == '-' || key == '+' ||
-            key == KEY_PPAGE || key == KEY_NPAGE) {
-
-            print_item (menu, items[scroll + choice]->name, choice, FALSE,
-                       (items[scroll + choice]->tag[0] != ':'));
-
-	    if (key == KEY_UP || key == '-') {
-                if (choice < 2 && scroll) {
-	            /* Scroll menu down */
-                    scrollok (menu, TRUE);
-                    wscrl (menu, -1);
-                    scrollok (menu, FALSE);
-
-                    scroll--;
-
-                    print_item (menu, items[scroll]->name, 0, FALSE,
-                               (items[scroll]->tag[0] != ':'));
-		} else
-		    choice = MAX(choice - 1, 0);
-
-	    } else if (key == KEY_DOWN || key == '+')  {
-
-		print_item (menu, items[scroll + choice]->name, choice, FALSE,
-                                (items[scroll + choice]->tag[0] != ':'));
-
-                if ((choice > max_choice-3) &&
-                    (scroll + max_choice < item_no)
-                   ) {
-		    /* Scroll menu up */
-		    scrollok (menu, TRUE);
-                    scroll (menu);
-                    scrollok (menu, FALSE);
-
-                    scroll++;
-
-                    print_item (menu, items[scroll + max_choice - 1]->name,
-                               max_choice-1, FALSE,
-                               (items[scroll + max_choice - 1]->tag[0] != ':'));
-                } else
-                    choice = MIN(choice+1, max_choice-1);
-
-	    } else if (key == KEY_PPAGE) {
-	        scrollok (menu, TRUE);
-                for (i=0; (i < max_choice); i++) {
-                    if (scroll > 0) {
-                	wscrl (menu, -1);
-                	scroll--;
-                	print_item (menu, items[scroll]->name, 0, FALSE,
-                	(items[scroll]->tag[0] != ':'));
-                    } else {
-                        if (choice > 0)
-                            choice--;
-                    }
-                }
-                scrollok (menu, FALSE);
-
-            } else if (key == KEY_NPAGE) {
-                for (i=0; (i < max_choice); i++) {
-                    if (scroll+max_choice < item_no) {
-			scrollok (menu, TRUE);
-			scroll(menu);
-			scrollok (menu, FALSE);
-                	scroll++;
-                	print_item (menu, items[scroll + max_choice - 1]->name,
-			            max_choice-1, FALSE,
-			            (items[scroll + max_choice - 1]->tag[0] != ':'));
-		    } else {
-			if (choice+1 < max_choice)
-			    choice++;
-		    }
-                }
-
-            } else
-                choice = i;
-
-            print_item (menu, items[scroll + choice]->name, choice, TRUE,
-                       (items[scroll + choice]->tag[0] != ':'));
-
-            print_arrows(dialog, item_no, scroll,
-                         box_y, box_x+item_x+1, menu_height);
-
-            wnoutrefresh (dialog);
-            wrefresh (menu);
-
-	    continue;		/* wait for another key press */
-        }
-
-	switch (key) {
-	case KEY_LEFT:
-	case TAB:
-	case KEY_RIGHT:
-	    button = ((key == KEY_LEFT ? --button : ++button) < 0)
-			? 2 : (button > 2 ? 0 : button);
-
-	    print_buttons(dialog, height, width, button);
-	    wrefresh (menu);
-	    break;
-	case ' ':
-	case 's':
-	case 'y':
-	case 'n':
-	case 'm':
-	case '/':
-	    /* save scroll info */
-	    if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
-		fprintf(f,"%d\n",scroll);
-		fclose(f);
-	    }
-	    delwin (dialog);
-            items[scroll + choice]->selected = 1;
-            switch (key) {
-            case 's': return 3;
-            case 'y': return 3;
-            case 'n': return 4;
-            case 'm': return 5;
-            case ' ': return 6;
-            case '/': return 7;
-            }
-	    return 0;
-	case 'h':
-	case '?':
-	    button = 2;
-	case '\n':
-	    delwin (dialog);
-	    items[scroll + choice]->selected = 1;
-
-	    remove("lxdialog.scrltmp");
-	    return button;
-	case 'e':
-	case 'x':
-	    key = ESC;
-	case ESC:
-	    break;
+		switch (key) {
+		case KEY_LEFT:
+		case TAB:
+		case KEY_RIGHT:
+			button = ((key == KEY_LEFT ? --button : ++button) < 0)
+			    ? 2 : (button > 2 ? 0 : button);
+
+			print_buttons(dialog, height, width, button);
+			wrefresh(menu);
+			break;
+		case ' ':
+		case 's':
+		case 'y':
+		case 'n':
+		case 'm':
+		case '/':
+			/* save scroll info */
+			*s_scroll = scroll;
+			delwin(menu);
+			delwin(dialog);
+			item_set(scroll + choice);
+			item_set_selected(1);
+			switch (key) {
+			case 's':
+				return 3;
+			case 'y':
+				return 3;
+			case 'n':
+				return 4;
+			case 'm':
+				return 5;
+			case ' ':
+				return 6;
+			case '/':
+				return 7;
+			}
+			return 0;
+		case 'h':
+		case '?':
+			button = 2;
+		case '\n':
+			*s_scroll = scroll;
+			delwin(menu);
+			delwin(dialog);
+			item_set(scroll + choice);
+			item_set_selected(1);
+			return button;
+		case 'e':
+		case 'x':
+			key = KEY_ESC;
+			break;
+		case KEY_ESC:
+			key = on_key_esc(menu);
+			break;
+		case KEY_RESIZE:
+			on_key_resize();
+			delwin(menu);
+			delwin(dialog);
+			goto do_resize;
+		}
 	}
 	}
-    }
-
-    delwin (dialog);
-    remove("lxdialog.scrltmp");
-    return -1;			/* ESC pressed */
+	delwin(menu);
+	delwin(dialog);
+	return key;		/* ESC pressed */
 }
 }

+ 316 - 481
package/config/lxdialog/textbox.c

@@ -21,463 +21,324 @@
 
 
 #include "dialog.h"
 #include "dialog.h"
 
 
-static void back_lines (int n);
-static void print_page (WINDOW * win, int height, int width);
-static void print_line (WINDOW * win, int row, int width);
-static char *get_line (void);
-static void print_position (WINDOW * win, int height, int width);
+static void back_lines(int n);
+static void print_page(WINDOW * win, int height, int width);
+static void print_line(WINDOW * win, int row, int width);
+static char *get_line(void);
+static void print_position(WINDOW * win);
+
+static int hscroll;
+static int begin_reached, end_reached, page_length;
+static const char *buf;
+static const char *page;
+
+/*
+ * refresh window content
+ */
+static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
+							  int cur_y, int cur_x)
+{
+	print_page(box, boxh, boxw);
+	print_position(dialog);
+	wmove(dialog, cur_y, cur_x);	/* Restore cursor position */
+	wrefresh(dialog);
+}
 
 
-static int hscroll, fd, file_size, bytes_read;
-static int begin_reached = 1, end_reached, page_length;
-static char *buf, *page;
 
 
 /*
 /*
  * Display text from a file in a dialog box.
  * Display text from a file in a dialog box.
  */
  */
-int
-dialog_textbox (const char *title, const char *file, int height, int width)
+int dialog_textbox(const char *title, const char *tbuf,
+		   int initial_height, int initial_width)
 {
 {
-    int i, x, y, cur_x, cur_y, fpos, key = 0;
-    int passed_end;
-    char search_term[MAX_LEN + 1];
-    WINDOW *dialog, *text;
-
-    search_term[0] = '\0';	/* no search term entered yet */
-
-    /* Open input file for reading */
-    if ((fd = open (file, O_RDONLY)) == -1) {
-	endwin ();
-	fprintf (stderr,
-		 "\nCan't open input file in dialog_textbox().\n");
-	exit (-1);
-    }
-    /* Get file size. Actually, 'file_size' is the real file size - 1,
-       since it's only the last byte offset from the beginning */
-    if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
-	endwin ();
-	fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
-	exit (-1);
-    }
-    /* Restore file pointer to beginning of file after getting file size */
-    if (lseek (fd, 0, SEEK_SET) == -1) {
-	endwin ();
-	fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
-	exit (-1);
-    }
-    /* Allocate space for read buffer */
-    if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
-	endwin ();
-	fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
-	exit (-1);
-    }
-    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
-	endwin ();
-	fprintf (stderr, "\nError reading file in dialog_textbox().\n");
-	exit (-1);
-    }
-    buf[bytes_read] = '\0';	/* mark end of valid data */
-    page = buf;			/* page is pointer to start of page to be displayed */
-
-    /* center dialog box on screen */
-    x = (COLS - width) / 2;
-    y = (LINES - height) / 2;
-
-
-    draw_shadow (stdscr, y, x, height, width);
-
-    dialog = newwin (height, width, y, x);
-    keypad (dialog, TRUE);
-
-    /* Create window for text region, used for scrolling text */
-    text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
-    wattrset (text, dialog_attr);
-    wbkgdset (text, dialog_attr & A_COLOR);
-
-    keypad (text, TRUE);
-
-    /* register the new window, along with its borders */
-    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
-
-    wattrset (dialog, border_attr);
-    mvwaddch (dialog, height-3, 0, ACS_LTEE);
-    for (i = 0; i < width - 2; i++)
-	waddch (dialog, ACS_HLINE);
-    wattrset (dialog, dialog_attr);
-    wbkgdset (dialog, dialog_attr & A_COLOR);
-    waddch (dialog, ACS_RTEE);
-
-    if (title != NULL && strlen(title) >= width-2 ) {
-	/* truncate long title -- mec */
-	char * title2 = malloc(width-2+1);
-	memcpy( title2, title, width-2 );
-	title2[width-2] = '\0';
-	title = title2;
-    }
-
-    if (title != NULL) {
-	wattrset (dialog, title_attr);
-	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
-	waddstr (dialog, (char *)title);
-	waddch (dialog, ' ');
-    }
-    print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
-    wnoutrefresh (dialog);
-    getyx (dialog, cur_y, cur_x);	/* Save cursor position */
-
-    /* Print first page of text */
-    attr_clear (text, height - 4, width - 2, dialog_attr);
-    print_page (text, height - 4, width - 2);
-    print_position (dialog, height, width);
-    wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
-    wrefresh (dialog);
-
-    while ((key != ESC) && (key != '\n')) {
-	key = wgetch (dialog);
-	switch (key) {
-	case 'E':		/* Exit */
-	case 'e':
-	case 'X':
-	case 'x':
-	    delwin (dialog);
-	    free (buf);
-	    close (fd);
-	    return 0;
-	case 'g':		/* First page */
-	case KEY_HOME:
-	    if (!begin_reached) {
-		begin_reached = 1;
-		/* First page not in buffer? */
-		if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
-		    endwin ();
-		    fprintf (stderr,
-		      "\nError moving file pointer in dialog_textbox().\n");
-		    exit (-1);
-		}
-		if (fpos > bytes_read) {	/* Yes, we have to read it in */
-		    if (lseek (fd, 0, SEEK_SET) == -1) {
-			endwin ();
-			fprintf (stderr, "\nError moving file pointer in "
-				 "dialog_textbox().\n");
-			exit (-1);
-		    }
-		    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
-			endwin ();
-			fprintf (stderr,
-			     "\nError reading file in dialog_textbox().\n");
-			exit (-1);
-		    }
-		    buf[bytes_read] = '\0';
-		}
-		page = buf;
-		print_page (text, height - 4, width - 2);
-		print_position (dialog, height, width);
-		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
-		wrefresh (dialog);
-	    }
-	    break;
-	case 'G':		/* Last page */
-	case KEY_END:
-
-	    end_reached = 1;
-	    /* Last page not in buffer? */
-	    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
-		endwin ();
-		fprintf (stderr,
-		      "\nError moving file pointer in dialog_textbox().\n");
-		exit (-1);
-	    }
-	    if (fpos < file_size) {	/* Yes, we have to read it in */
-		if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
-		    endwin ();
-		    fprintf (stderr,
-		      "\nError moving file pointer in dialog_textbox().\n");
-		    exit (-1);
-		}
-		if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
-		    endwin ();
-		    fprintf (stderr,
-			     "\nError reading file in dialog_textbox().\n");
-		    exit (-1);
-		}
-		buf[bytes_read] = '\0';
-	    }
-	    page = buf + bytes_read;
-	    back_lines (height - 4);
-	    print_page (text, height - 4, width - 2);
-	    print_position (dialog, height, width);
-	    wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
-	    wrefresh (dialog);
-	    break;
-	case 'K':		/* Previous line */
-	case 'k':
-	case KEY_UP:
-	    if (!begin_reached) {
-		back_lines (page_length + 1);
-
-		/* We don't call print_page() here but use scrolling to ensure
-		   faster screen update. However, 'end_reached' and
-		   'page_length' should still be updated, and 'page' should
-		   point to start of next page. This is done by calling
-		   get_line() in the following 'for' loop. */
-		scrollok (text, TRUE);
-		wscrl (text, -1);	/* Scroll text region down one line */
-		scrollok (text, FALSE);
-		page_length = 0;
-		passed_end = 0;
-		for (i = 0; i < height - 4; i++) {
-		    if (!i) {
-			/* print first line of page */
-			print_line (text, 0, width - 2);
-			wnoutrefresh (text);
-		    } else
-			/* Called to update 'end_reached' and 'page' */
-			get_line ();
-		    if (!passed_end)
-			page_length++;
-		    if (end_reached && !passed_end)
-			passed_end = 1;
+	int i, x, y, cur_x, cur_y, key = 0;
+	int height, width, boxh, boxw;
+	int passed_end;
+	WINDOW *dialog, *box;
+
+	begin_reached = 1;
+	end_reached = 0;
+	page_length = 0;
+	hscroll = 0;
+	buf = tbuf;
+	page = buf;	/* page is pointer to start of page to be displayed */
+
+do_resize:
+	getmaxyx(stdscr, height, width);
+	if (height < 8 || width < 8)
+		return -ERRDISPLAYTOOSMALL;
+	if (initial_height != 0)
+		height = initial_height;
+	else
+		if (height > 4)
+			height -= 4;
+		else
+			height = 0;
+	if (initial_width != 0)
+		width = initial_width;
+	else
+		if (width > 5)
+			width -= 5;
+		else
+			width = 0;
+
+	/* center dialog box on screen */
+	x = (COLS - width) / 2;
+	y = (LINES - height) / 2;
+
+	draw_shadow(stdscr, y, x, height, width);
+
+	dialog = newwin(height, width, y, x);
+	keypad(dialog, TRUE);
+
+	/* Create window for box region, used for scrolling text */
+	boxh = height - 4;
+	boxw = width - 2;
+	box = subwin(dialog, boxh, boxw, y + 1, x + 1);
+	wattrset(box, dlg.dialog.atr);
+	wbkgdset(box, dlg.dialog.atr & A_COLOR);
+
+	keypad(box, TRUE);
+
+	/* register the new window, along with its borders */
+	draw_box(dialog, 0, 0, height, width,
+		 dlg.dialog.atr, dlg.border.atr);
+
+	wattrset(dialog, dlg.border.atr);
+	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+	for (i = 0; i < width - 2; i++)
+		waddch(dialog, ACS_HLINE);
+	wattrset(dialog, dlg.dialog.atr);
+	wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
+	waddch(dialog, ACS_RTEE);
+
+	print_title(dialog, title, width);
+
+	print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
+	wnoutrefresh(dialog);
+	getyx(dialog, cur_y, cur_x);	/* Save cursor position */
+
+	/* Print first page of text */
+	attr_clear(box, boxh, boxw, dlg.dialog.atr);
+	refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
+
+	while ((key != KEY_ESC) && (key != '\n')) {
+		key = wgetch(dialog);
+		switch (key) {
+		case 'E':	/* Exit */
+		case 'e':
+		case 'X':
+		case 'x':
+			delwin(box);
+			delwin(dialog);
+			return 0;
+		case 'g':	/* First page */
+		case KEY_HOME:
+			if (!begin_reached) {
+				begin_reached = 1;
+				page = buf;
+				refresh_text_box(dialog, box, boxh, boxw,
+						 cur_y, cur_x);
+			}
+			break;
+		case 'G':	/* Last page */
+		case KEY_END:
+
+			end_reached = 1;
+			/* point to last char in buf */
+			page = buf + strlen(buf);
+			back_lines(boxh);
+			refresh_text_box(dialog, box, boxh, boxw,
+					 cur_y, cur_x);
+			break;
+		case 'K':	/* Previous line */
+		case 'k':
+		case KEY_UP:
+			if (!begin_reached) {
+				back_lines(page_length + 1);
+
+				/* We don't call print_page() here but use
+				 * scrolling to ensure faster screen update.
+				 * However, 'end_reached' and 'page_length'
+				 * should still be updated, and 'page' should
+				 * point to start of next page. This is done
+				 * by calling get_line() in the following
+				 * 'for' loop. */
+				scrollok(box, TRUE);
+				wscrl(box, -1);	/* Scroll box region down one line */
+				scrollok(box, FALSE);
+				page_length = 0;
+				passed_end = 0;
+				for (i = 0; i < boxh; i++) {
+					if (!i) {
+						/* print first line of page */
+						print_line(box, 0, boxw);
+						wnoutrefresh(box);
+					} else
+						/* Called to update 'end_reached' and 'page' */
+						get_line();
+					if (!passed_end)
+						page_length++;
+					if (end_reached && !passed_end)
+						passed_end = 1;
+				}
+
+				print_position(dialog);
+				wmove(dialog, cur_y, cur_x);	/* Restore cursor position */
+				wrefresh(dialog);
+			}
+			break;
+		case 'B':	/* Previous page */
+		case 'b':
+		case KEY_PPAGE:
+			if (begin_reached)
+				break;
+			back_lines(page_length + boxh);
+			refresh_text_box(dialog, box, boxh, boxw,
+					 cur_y, cur_x);
+			break;
+		case 'J':	/* Next line */
+		case 'j':
+		case KEY_DOWN:
+			if (!end_reached) {
+				begin_reached = 0;
+				scrollok(box, TRUE);
+				scroll(box);	/* Scroll box region up one line */
+				scrollok(box, FALSE);
+				print_line(box, boxh - 1, boxw);
+				wnoutrefresh(box);
+				print_position(dialog);
+				wmove(dialog, cur_y, cur_x);	/* Restore cursor position */
+				wrefresh(dialog);
+			}
+			break;
+		case KEY_NPAGE:	/* Next page */
+		case ' ':
+			if (end_reached)
+				break;
+
+			begin_reached = 0;
+			refresh_text_box(dialog, box, boxh, boxw,
+					 cur_y, cur_x);
+			break;
+		case '0':	/* Beginning of line */
+		case 'H':	/* Scroll left */
+		case 'h':
+		case KEY_LEFT:
+			if (hscroll <= 0)
+				break;
+
+			if (key == '0')
+				hscroll = 0;
+			else
+				hscroll--;
+			/* Reprint current page to scroll horizontally */
+			back_lines(page_length);
+			refresh_text_box(dialog, box, boxh, boxw,
+					 cur_y, cur_x);
+			break;
+		case 'L':	/* Scroll right */
+		case 'l':
+		case KEY_RIGHT:
+			if (hscroll >= MAX_LEN)
+				break;
+			hscroll++;
+			/* Reprint current page to scroll horizontally */
+			back_lines(page_length);
+			refresh_text_box(dialog, box, boxh, boxw,
+					 cur_y, cur_x);
+			break;
+		case KEY_ESC:
+			key = on_key_esc(dialog);
+			break;
+		case KEY_RESIZE:
+			back_lines(height);
+			delwin(box);
+			delwin(dialog);
+			on_key_resize();
+			goto do_resize;
 		}
 		}
-
-		print_position (dialog, height, width);
-		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
-		wrefresh (dialog);
-	    }
-	    break;
-	case 'B':		/* Previous page */
-	case 'b':
-	case KEY_PPAGE:
-	    if (begin_reached)
-		break;
-	    back_lines (page_length + height - 4);
-	    print_page (text, height - 4, width - 2);
-	    print_position (dialog, height, width);
-	    wmove (dialog, cur_y, cur_x);
-	    wrefresh (dialog);
-	    break;
-	case 'J':		/* Next line */
-	case 'j':
-	case KEY_DOWN:
-	    if (!end_reached) {
-		begin_reached = 0;
-		scrollok (text, TRUE);
-		scroll (text);	/* Scroll text region up one line */
-		scrollok (text, FALSE);
-		print_line (text, height - 5, width - 2);
-		wnoutrefresh (text);
-		print_position (dialog, height, width);
-		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
-		wrefresh (dialog);
-	    }
-	    break;
-	case KEY_NPAGE:		/* Next page */
-	case ' ':
-	    if (end_reached)
-		break;
-
-	    begin_reached = 0;
-	    print_page (text, height - 4, width - 2);
-	    print_position (dialog, height, width);
-	    wmove (dialog, cur_y, cur_x);
-	    wrefresh (dialog);
-	    break;
-	case '0':		/* Beginning of line */
-	case 'H':		/* Scroll left */
-	case 'h':
-	case KEY_LEFT:
-	    if (hscroll <= 0)
-		break;
-
-	    if (key == '0')
-		hscroll = 0;
-	    else
-		hscroll--;
-	    /* Reprint current page to scroll horizontally */
-	    back_lines (page_length);
-	    print_page (text, height - 4, width - 2);
-	    wmove (dialog, cur_y, cur_x);
-	    wrefresh (dialog);
-	    break;
-	case 'L':		/* Scroll right */
-	case 'l':
-	case KEY_RIGHT:
-	    if (hscroll >= MAX_LEN)
-		break;
-	    hscroll++;
-	    /* Reprint current page to scroll horizontally */
-	    back_lines (page_length);
-	    print_page (text, height - 4, width - 2);
-	    wmove (dialog, cur_y, cur_x);
-	    wrefresh (dialog);
-	    break;
-	case ESC:
-	    break;
 	}
 	}
-    }
-
-    delwin (dialog);
-    free (buf);
-    close (fd);
-    return 1;			/* ESC pressed */
+	delwin(box);
+	delwin(dialog);
+	return key;		/* ESC pressed */
 }
 }
 
 
 /*
 /*
- * Go back 'n' lines in text file. Called by dialog_textbox().
+ * Go back 'n' lines in text. Called by dialog_textbox().
  * 'page' will be updated to point to the desired line in 'buf'.
  * 'page' will be updated to point to the desired line in 'buf'.
  */
  */
-static void
-back_lines (int n)
+static void back_lines(int n)
 {
 {
-    int i, fpos;
-
-    begin_reached = 0;
-    /* We have to distinguish between end_reached and !end_reached
-       since at end of file, the line is not ended by a '\n'.
-       The code inside 'if' basically does a '--page' to move one
-       character backward so as to skip '\n' of the previous line */
-    if (!end_reached) {
-	/* Either beginning of buffer or beginning of file reached? */
-	if (page == buf) {
-	    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
-		endwin ();
-		fprintf (stderr, "\nError moving file pointer in "
-			 "back_lines().\n");
-		exit (-1);
-	    }
-	    if (fpos > bytes_read) {	/* Not beginning of file yet */
-		/* We've reached beginning of buffer, but not beginning of
-		   file yet, so read previous part of file into buffer.
-		   Note that we only move backward for BUF_SIZE/2 bytes,
-		   but not BUF_SIZE bytes to avoid re-reading again in
-		   print_page() later */
-		/* Really possible to move backward BUF_SIZE/2 bytes? */
-		if (fpos < BUF_SIZE / 2 + bytes_read) {
-		    /* No, move less then */
-		    if (lseek (fd, 0, SEEK_SET) == -1) {
-			endwin ();
-			fprintf (stderr, "\nError moving file pointer in "
-				 "back_lines().\n");
-			exit (-1);
-		    }
-		    page = buf + fpos - bytes_read;
-		} else {	/* Move backward BUF_SIZE/2 bytes */
-		    if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
-			== -1) {
-			endwin ();
-			fprintf (stderr, "\nError moving file pointer "
-				 "in back_lines().\n");
-			exit (-1);
-		    }
-		    page = buf + BUF_SIZE / 2;
-		}
-		if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
-		    endwin ();
-		    fprintf (stderr, "\nError reading file in back_lines().\n");
-		    exit (-1);
+	int i;
+
+	begin_reached = 0;
+	/* Go back 'n' lines */
+	for (i = 0; i < n; i++) {
+		if (*page == '\0') {
+			if (end_reached) {
+				end_reached = 0;
+				continue;
+			}
 		}
 		}
-		buf[bytes_read] = '\0';
-	    } else {		/* Beginning of file reached */
-		begin_reached = 1;
-		return;
-	    }
-	}
-	if (*(--page) != '\n') {	/* '--page' here */
-	    /* Something's wrong... */
-	    endwin ();
-	    fprintf (stderr, "\nInternal error in back_lines().\n");
-	    exit (-1);
-	}
-    }
-    /* Go back 'n' lines */
-    for (i = 0; i < n; i++)
-	do {
-	    if (page == buf) {
-		if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
-		    endwin ();
-		    fprintf (stderr,
-			  "\nError moving file pointer in back_lines().\n");
-		    exit (-1);
+		if (page == buf) {
+			begin_reached = 1;
+			return;
 		}
 		}
-		if (fpos > bytes_read) {
-		    /* Really possible to move backward BUF_SIZE/2 bytes? */
-		    if (fpos < BUF_SIZE / 2 + bytes_read) {
-			/* No, move less then */
-			if (lseek (fd, 0, SEEK_SET) == -1) {
-			    endwin ();
-			    fprintf (stderr, "\nError moving file pointer "
-				     "in back_lines().\n");
-			    exit (-1);
-			}
-			page = buf + fpos - bytes_read;
-		    } else {	/* Move backward BUF_SIZE/2 bytes */
-			if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
-				   SEEK_CUR) == -1) {
-			    endwin ();
-			    fprintf (stderr, "\nError moving file pointer"
-				     " in back_lines().\n");
-			    exit (-1);
+		page--;
+		do {
+			if (page == buf) {
+				begin_reached = 1;
+				return;
 			}
 			}
-			page = buf + BUF_SIZE / 2;
-		    }
-		    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
-			endwin ();
-			fprintf (stderr, "\nError reading file in "
-				 "back_lines().\n");
-			exit (-1);
-		    }
-		    buf[bytes_read] = '\0';
-		} else {	/* Beginning of file reached */
-		    begin_reached = 1;
-		    return;
-		}
-	    }
-	} while (*(--page) != '\n');
-    page++;
+			page--;
+		} while (*page != '\n');
+		page++;
+	}
 }
 }
 
 
 /*
 /*
  * Print a new page of text. Called by dialog_textbox().
  * Print a new page of text. Called by dialog_textbox().
  */
  */
-static void
-print_page (WINDOW * win, int height, int width)
+static void print_page(WINDOW * win, int height, int width)
 {
 {
-    int i, passed_end = 0;
-
-    page_length = 0;
-    for (i = 0; i < height; i++) {
-	print_line (win, i, width);
-	if (!passed_end)
-	    page_length++;
-	if (end_reached && !passed_end)
-	    passed_end = 1;
-    }
-    wnoutrefresh (win);
+	int i, passed_end = 0;
+
+	page_length = 0;
+	for (i = 0; i < height; i++) {
+		print_line(win, i, width);
+		if (!passed_end)
+			page_length++;
+		if (end_reached && !passed_end)
+			passed_end = 1;
+	}
+	wnoutrefresh(win);
 }
 }
 
 
 /*
 /*
  * Print a new line of text. Called by dialog_textbox() and print_page().
  * Print a new line of text. Called by dialog_textbox() and print_page().
  */
  */
-static void
-print_line (WINDOW * win, int row, int width)
+static void print_line(WINDOW * win, int row, int width)
 {
 {
-    int y, x;
-    char *line;
+	int y, x;
+	char *line;
 
 
-    line = get_line ();
-    line += MIN (strlen (line), hscroll);	/* Scroll horizontally */
-    wmove (win, row, 0);	/* move cursor to correct line */
-    waddch (win, ' ');
-    waddnstr (win, line, MIN (strlen (line), width - 2));
+	line = get_line();
+	line += MIN(strlen(line), hscroll);	/* Scroll horizontally */
+	wmove(win, row, 0);	/* move cursor to correct line */
+	waddch(win, ' ');
+	waddnstr(win, line, MIN(strlen(line), width - 2));
 
 
-    getyx (win, y, x);
-    /* Clear 'residue' of previous line */
+	getyx(win, y, x);
+	/* Clear 'residue' of previous line */
 #if OLD_NCURSES
 #if OLD_NCURSES
-    {
-        int i;
-        for (i = 0; i < width - x; i++)
-	    waddch (win, ' ');
-    }
+	{
+		int i;
+		for (i = 0; i < width - x; i++)
+			waddch(win, ' ');
+	}
 #else
 #else
-    wclrtoeol(win);
+	wclrtoeol(win);
 #endif
 #endif
 }
 }
 
 
@@ -486,71 +347,45 @@ print_line (WINDOW * win, int row, int width)
  * 'page' should point to start of current line before calling, and will be
  * 'page' should point to start of current line before calling, and will be
  * updated to point to start of next line.
  * updated to point to start of next line.
  */
  */
-static char *
-get_line (void)
+static char *get_line(void)
 {
 {
-    int i = 0, fpos;
-    static char line[MAX_LEN + 1];
-
-    end_reached = 0;
-    while (*page != '\n') {
-	if (*page == '\0') {
-	    /* Either end of file or end of buffer reached */
-	    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
-		endwin ();
-		fprintf (stderr, "\nError moving file pointer in "
-			 "get_line().\n");
-		exit (-1);
-	    }
-	    if (fpos < file_size) {	/* Not end of file yet */
-		/* We've reached end of buffer, but not end of file yet,
-		   so read next part of file into buffer */
-		if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
-		    endwin ();
-		    fprintf (stderr, "\nError reading file in get_line().\n");
-		    exit (-1);
+	int i = 0;
+	static char line[MAX_LEN + 1];
+
+	end_reached = 0;
+	while (*page != '\n') {
+		if (*page == '\0') {
+			if (!end_reached) {
+				end_reached = 1;
+				break;
+			}
+		} else if (i < MAX_LEN)
+			line[i++] = *(page++);
+		else {
+			/* Truncate lines longer than MAX_LEN characters */
+			if (i == MAX_LEN)
+				line[i++] = '\0';
+			page++;
 		}
 		}
-		buf[bytes_read] = '\0';
-		page = buf;
-	    } else {
-		if (!end_reached)
-		    end_reached = 1;
-		break;
-	    }
-	} else if (i < MAX_LEN)
-	    line[i++] = *(page++);
-	else {
-	    /* Truncate lines longer than MAX_LEN characters */
-	    if (i == MAX_LEN)
-		line[i++] = '\0';
-	    page++;
 	}
 	}
-    }
-    if (i <= MAX_LEN)
-	line[i] = '\0';
-    if (!end_reached)
-	page++;			/* move pass '\n' */
+	if (i <= MAX_LEN)
+		line[i] = '\0';
+	if (!end_reached)
+		page++;		/* move pass '\n' */
 
 
-    return line;
+	return line;
 }
 }
 
 
 /*
 /*
  * Print current position
  * Print current position
  */
  */
-static void
-print_position (WINDOW * win, int height, int width)
+static void print_position(WINDOW * win)
 {
 {
-    int fpos, percent;
-
-    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
-	endwin ();
-	fprintf (stderr, "\nError moving file pointer in print_position().\n");
-	exit (-1);
-    }
-    wattrset (win, position_indicator_attr);
-    wbkgdset (win, position_indicator_attr & A_COLOR);
-    percent = !file_size ?
-	100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
-    wmove (win, height - 3, width - 9);
-    wprintw (win, "(%3d%%)", percent);
+	int percent;
+
+	wattrset(win, dlg.position_indicator.atr);
+	wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
+	percent = (page - buf) * 100 / strlen(buf);
+	wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
+	wprintw(win, "(%3d%%)", percent);
 }
 }

+ 530 - 265
package/config/lxdialog/util.c

@@ -21,172 +21,287 @@
 
 
 #include "dialog.h"
 #include "dialog.h"
 
 
+struct dialog_info dlg;
 
 
-/* use colors by default? */
-bool use_colors = 1;
+static void set_mono_theme(void)
+{
+	dlg.screen.atr = A_NORMAL;
+	dlg.shadow.atr = A_NORMAL;
+	dlg.dialog.atr = A_NORMAL;
+	dlg.title.atr = A_BOLD;
+	dlg.border.atr = A_NORMAL;
+	dlg.button_active.atr = A_REVERSE;
+	dlg.button_inactive.atr = A_DIM;
+	dlg.button_key_active.atr = A_REVERSE;
+	dlg.button_key_inactive.atr = A_BOLD;
+	dlg.button_label_active.atr = A_REVERSE;
+	dlg.button_label_inactive.atr = A_NORMAL;
+	dlg.inputbox.atr = A_NORMAL;
+	dlg.inputbox_border.atr = A_NORMAL;
+	dlg.searchbox.atr = A_NORMAL;
+	dlg.searchbox_title.atr = A_BOLD;
+	dlg.searchbox_border.atr = A_NORMAL;
+	dlg.position_indicator.atr = A_BOLD;
+	dlg.menubox.atr = A_NORMAL;
+	dlg.menubox_border.atr = A_NORMAL;
+	dlg.item.atr = A_NORMAL;
+	dlg.item_selected.atr = A_REVERSE;
+	dlg.tag.atr = A_BOLD;
+	dlg.tag_selected.atr = A_REVERSE;
+	dlg.tag_key.atr = A_BOLD;
+	dlg.tag_key_selected.atr = A_REVERSE;
+	dlg.check.atr = A_BOLD;
+	dlg.check_selected.atr = A_REVERSE;
+	dlg.uarrow.atr = A_BOLD;
+	dlg.darrow.atr = A_BOLD;
+}
 
 
-const char *backtitle = NULL;
+#define DLG_COLOR(dialog, f, b, h) \
+do {                               \
+	dlg.dialog.fg = (f);       \
+	dlg.dialog.bg = (b);       \
+	dlg.dialog.hl = (h);       \
+} while (0)
 
 
-const char *dialog_result;
+static void set_classic_theme(void)
+{
+	DLG_COLOR(screen,                COLOR_CYAN,   COLOR_BLUE,   true);
+	DLG_COLOR(shadow,                COLOR_BLACK,  COLOR_BLACK,  true);
+	DLG_COLOR(dialog,                COLOR_BLACK,  COLOR_WHITE,  false);
+	DLG_COLOR(title,                 COLOR_YELLOW, COLOR_WHITE,  true);
+	DLG_COLOR(border,                COLOR_WHITE,  COLOR_WHITE,  true);
+	DLG_COLOR(button_active,         COLOR_WHITE,  COLOR_BLUE,   true);
+	DLG_COLOR(button_inactive,       COLOR_BLACK,  COLOR_WHITE,  false);
+	DLG_COLOR(button_key_active,     COLOR_WHITE,  COLOR_BLUE,   true);
+	DLG_COLOR(button_key_inactive,   COLOR_RED,    COLOR_WHITE,  false);
+	DLG_COLOR(button_label_active,   COLOR_YELLOW, COLOR_BLUE,   true);
+	DLG_COLOR(button_label_inactive, COLOR_BLACK,  COLOR_WHITE,  true);
+	DLG_COLOR(inputbox,              COLOR_BLACK,  COLOR_WHITE,  false);
+	DLG_COLOR(inputbox_border,       COLOR_BLACK,  COLOR_WHITE,  false);
+	DLG_COLOR(searchbox,             COLOR_BLACK,  COLOR_WHITE,  false);
+	DLG_COLOR(searchbox_title,       COLOR_YELLOW, COLOR_WHITE,  true);
+	DLG_COLOR(searchbox_border,      COLOR_WHITE,  COLOR_WHITE,  true);
+	DLG_COLOR(position_indicator,    COLOR_YELLOW, COLOR_WHITE,  true);
+	DLG_COLOR(menubox,               COLOR_BLACK,  COLOR_WHITE,  false);
+	DLG_COLOR(menubox_border,        COLOR_WHITE,  COLOR_WHITE,  true);
+	DLG_COLOR(item,                  COLOR_BLACK,  COLOR_WHITE,  false);
+	DLG_COLOR(item_selected,         COLOR_WHITE,  COLOR_BLUE,   true);
+	DLG_COLOR(tag,                   COLOR_YELLOW, COLOR_WHITE,  true);
+	DLG_COLOR(tag_selected,          COLOR_YELLOW, COLOR_BLUE,   true);
+	DLG_COLOR(tag_key,               COLOR_YELLOW, COLOR_WHITE,  true);
+	DLG_COLOR(tag_key_selected,      COLOR_YELLOW, COLOR_BLUE,   true);
+	DLG_COLOR(check,                 COLOR_BLACK,  COLOR_WHITE,  false);
+	DLG_COLOR(check_selected,        COLOR_WHITE,  COLOR_BLUE,   true);
+	DLG_COLOR(uarrow,                COLOR_GREEN,  COLOR_WHITE,  true);
+	DLG_COLOR(darrow,                COLOR_GREEN,  COLOR_WHITE,  true);
+}
 
 
-/* 
- * 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"
+static void set_blackbg_theme(void)
+{
+	DLG_COLOR(screen, COLOR_RED,   COLOR_BLACK, true);
+	DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
+	DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
+	DLG_COLOR(title,  COLOR_RED,   COLOR_BLACK, false);
+	DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
 
 
-/*
- * 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 */
+	DLG_COLOR(button_active,         COLOR_YELLOW, COLOR_RED,   false);
+	DLG_COLOR(button_inactive,       COLOR_YELLOW, COLOR_BLACK, false);
+	DLG_COLOR(button_key_active,     COLOR_YELLOW, COLOR_RED,   true);
+	DLG_COLOR(button_key_inactive,   COLOR_RED,    COLOR_BLACK, false);
+	DLG_COLOR(button_label_active,   COLOR_WHITE,  COLOR_RED,   false);
+	DLG_COLOR(button_label_inactive, COLOR_BLACK,  COLOR_BLACK, true);
 
 
-/*
- * Set window to attribute 'attr'
- */
-void
-attr_clear (WINDOW * win, int height, int width, chtype attr)
-{
-    int i, j;
+	DLG_COLOR(inputbox,         COLOR_YELLOW, COLOR_BLACK, false);
+	DLG_COLOR(inputbox_border,  COLOR_YELLOW, COLOR_BLACK, false);
+
+	DLG_COLOR(searchbox,        COLOR_YELLOW, COLOR_BLACK, false);
+	DLG_COLOR(searchbox_title,  COLOR_YELLOW, COLOR_BLACK, true);
+	DLG_COLOR(searchbox_border, COLOR_BLACK,  COLOR_BLACK, true);
+
+	DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK,  false);
 
 
-    wattrset (win, attr);
-    for (i = 0; i < height; i++) {
-	wmove (win, i, 0);
-	for (j = 0; j < width; j++)
-	    waddch (win, ' ');
-    }
-    touchwin (win);
+	DLG_COLOR(menubox,          COLOR_YELLOW, COLOR_BLACK, false);
+	DLG_COLOR(menubox_border,   COLOR_BLACK,  COLOR_BLACK, true);
+
+	DLG_COLOR(item,             COLOR_WHITE, COLOR_BLACK, false);
+	DLG_COLOR(item_selected,    COLOR_WHITE, COLOR_RED,   false);
+
+	DLG_COLOR(tag,              COLOR_RED,    COLOR_BLACK, false);
+	DLG_COLOR(tag_selected,     COLOR_YELLOW, COLOR_RED,   true);
+	DLG_COLOR(tag_key,          COLOR_RED,    COLOR_BLACK, false);
+	DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED,   true);
+
+	DLG_COLOR(check,            COLOR_YELLOW, COLOR_BLACK, false);
+	DLG_COLOR(check_selected,   COLOR_YELLOW, COLOR_RED,   true);
+
+	DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
+	DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
 }
 }
 
 
-void dialog_clear (void)
+static void set_bluetitle_theme(void)
 {
 {
-    attr_clear (stdscr, LINES, COLS, screen_attr);
-    /* Display background title if it exists ... - SLH */
-    if (backtitle != NULL) {
-        int i;
+	set_classic_theme();
+	DLG_COLOR(title,               COLOR_BLUE,   COLOR_WHITE, true);
+	DLG_COLOR(button_key_active,   COLOR_YELLOW, COLOR_BLUE,  true);
+	DLG_COLOR(button_label_active, COLOR_WHITE,  COLOR_BLUE,  true);
+	DLG_COLOR(searchbox_title,     COLOR_BLUE,   COLOR_WHITE, true);
+	DLG_COLOR(position_indicator,  COLOR_BLUE,   COLOR_WHITE, true);
+	DLG_COLOR(tag,                 COLOR_BLUE,   COLOR_WHITE, true);
+	DLG_COLOR(tag_key,             COLOR_BLUE,   COLOR_WHITE, true);
 
 
-        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
+ * Select color theme
  */
  */
-void
-init_dialog (void)
+static int set_theme(const char *theme)
 {
 {
-    initscr ();			/* Init curses */
-    keypad (stdscr, TRUE);
-    cbreak ();
-    noecho ();
-
-
-    if (use_colors)	/* Set up colors */
-	color_setup ();
+	int use_color = 1;
+	if (!theme)
+		set_bluetitle_theme();
+	else if (strcmp(theme, "classic") == 0)
+		set_classic_theme();
+	else if (strcmp(theme, "bluetitle") == 0)
+		set_bluetitle_theme();
+	else if (strcmp(theme, "blackbg") == 0)
+		set_blackbg_theme();
+	else if (strcmp(theme, "mono") == 0)
+		use_color = 0;
+
+	return use_color;
+}
 
 
+static void init_one_color(struct dialog_color *color)
+{
+	static int pair = 0;
+
+	pair++;
+	init_pair(pair, color->fg, color->bg);
+	if (color->hl)
+		color->atr = A_BOLD | COLOR_PAIR(pair);
+	else
+		color->atr = COLOR_PAIR(pair);
+}
 
 
-    dialog_clear ();
+static void init_dialog_colors(void)
+{
+	init_one_color(&dlg.screen);
+	init_one_color(&dlg.shadow);
+	init_one_color(&dlg.dialog);
+	init_one_color(&dlg.title);
+	init_one_color(&dlg.border);
+	init_one_color(&dlg.button_active);
+	init_one_color(&dlg.button_inactive);
+	init_one_color(&dlg.button_key_active);
+	init_one_color(&dlg.button_key_inactive);
+	init_one_color(&dlg.button_label_active);
+	init_one_color(&dlg.button_label_inactive);
+	init_one_color(&dlg.inputbox);
+	init_one_color(&dlg.inputbox_border);
+	init_one_color(&dlg.searchbox);
+	init_one_color(&dlg.searchbox_title);
+	init_one_color(&dlg.searchbox_border);
+	init_one_color(&dlg.position_indicator);
+	init_one_color(&dlg.menubox);
+	init_one_color(&dlg.menubox_border);
+	init_one_color(&dlg.item);
+	init_one_color(&dlg.item_selected);
+	init_one_color(&dlg.tag);
+	init_one_color(&dlg.tag_selected);
+	init_one_color(&dlg.tag_key);
+	init_one_color(&dlg.tag_key_selected);
+	init_one_color(&dlg.check);
+	init_one_color(&dlg.check_selected);
+	init_one_color(&dlg.uarrow);
+	init_one_color(&dlg.darrow);
 }
 }
 
 
 /*
 /*
  * Setup for color display
  * Setup for color display
  */
  */
-void
-color_setup (void)
+static void color_setup(const char *theme)
+{
+	int use_color;
+
+	use_color = set_theme(theme);
+	if (use_color && has_colors()) {
+		start_color();
+		init_dialog_colors();
+	} else
+		set_mono_theme();
+}
+
+/*
+ * Set window to attribute 'attr'
+ */
+void attr_clear(WINDOW * win, int height, int width, chtype attr)
 {
 {
-    int i;
+	int i, j;
 
 
-    if (has_colors ()) {	/* Terminal supports color? */
-	start_color ();
+	wattrset(win, attr);
+	for (i = 0; i < height; i++) {
+		wmove(win, i, 0);
+		for (j = 0; j < width; j++)
+			waddch(win, ' ');
+	}
+	touchwin(win);
+}
 
 
-	/* Initialize color pairs */
-	for (i = 0; i < ATTRIBUTE_COUNT; i++)
-	    init_pair (i + 1, color_table[i][0], color_table[i][1]);
+void dialog_clear(void)
+{
+	attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
+	/* Display background title if it exists ... - SLH */
+	if (dlg.backtitle != NULL) {
+		int i;
+
+		wattrset(stdscr, dlg.screen.atr);
+		mvwaddstr(stdscr, 0, 1, (char *)dlg.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(const char *backtitle)
+{
+	dlg.backtitle = backtitle;
+	color_setup(getenv("MENUCONFIG_COLOR"));
+}
 
 
-	/* Setup color attributes */
-	for (i = 0; i < ATTRIBUTE_COUNT; i++)
-	    attributes[i] = C_ATTR (color_table[i][2], i + 1);
-    }
+void reset_dialog(void)
+{
+	initscr();		/* Init curses */
+	keypad(stdscr, TRUE);
+	cbreak();
+	noecho();
+	dialog_clear();
 }
 }
 
 
 /*
 /*
  * End using dialog functions.
  * End using dialog functions.
  */
  */
-void
-end_dialog (void)
+void end_dialog(void)
 {
 {
-    endwin ();
+	endwin();
 }
 }
 
 
+/* Print the title of the dialog. Center the title and truncate
+ * tile if wider than dialog (- 2 chars).
+ **/
+void print_title(WINDOW *dialog, const char *title, int width)
+{
+	if (title) {
+		int tlen = MIN(width - 2, strlen(title));
+		wattrset(dialog, dlg.title.atr);
+		mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
+		mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
+		waddch(dialog, ' ');
+	}
+}
 
 
 /*
 /*
  * Print a string of text in a window, automatically wrap around to the
  * Print a string of text in a window, automatically wrap around to the
@@ -194,164 +309,166 @@ end_dialog (void)
  * characters '\n' are replaced by spaces.  We start on a new line
  * 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.
  * 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++;
+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_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 == ' ');
+		cur_y = y;
 		newl = 1;
 		newl = 1;
-	    } else
-	        newl = 0;
-	    word = sp;
+		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
  * 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);
+void print_button(WINDOW * win, const char *label, int y, int x, int selected)
+{
+	int i, temp;
+
+	wmove(win, y, x);
+	wattrset(win, selected ? dlg.button_active.atr
+		 : dlg.button_inactive.atr);
+	waddstr(win, "<");
+	temp = strspn(label, " ");
+	label += temp;
+	wattrset(win, selected ? dlg.button_label_active.atr
+		 : dlg.button_label_inactive.atr);
+	for (i = 0; i < temp; i++)
+		waddch(win, ' ');
+	wattrset(win, selected ? dlg.button_key_active.atr
+		 : dlg.button_key_inactive.atr);
+	waddch(win, label[0]);
+	wattrset(win, selected ? dlg.button_label_active.atr
+		 : dlg.button_label_inactive.atr);
+	waddstr(win, (char *)label + 1);
+	wattrset(win, selected ? dlg.button_active.atr
+		 : dlg.button_inactive.atr);
+	waddstr(win, ">");
+	wmove(win, y, x + temp + 1);
 }
 }
 
 
 /*
 /*
  * Draw a rectangular box with line drawing characters
  * Draw a rectangular box with line drawing characters
  */
  */
 void
 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_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
  * Draw shadows along the right and bottom edge to give a more 3D look
  * to the boxes
  * 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);
+void draw_shadow(WINDOW * win, int y, int x, int height, int width)
+{
+	int i;
+
+	if (has_colors()) {	/* Whether terminal supports color? */
+		wattrset(win, dlg.shadow.atr);
+		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);
 	}
 	}
-	wnoutrefresh (win);
-    }
 }
 }
 
 
 /*
 /*
  *  Return the position of the first alphabetic character in a string.
  *  Return the position of the first alphabetic character in a string.
  */
  */
-int
-first_alpha(const char *string, const char *exempt)
+int first_alpha(const char *string, const char *exempt)
 {
 {
-	int i, in_paren=0, c;
+	int i, in_paren = 0, c;
 
 
 	for (i = 0; i < strlen(string); i++) {
 	for (i = 0; i < strlen(string); i++) {
 		c = tolower(string[i]);
 		c = tolower(string[i]);
 
 
-		if (strchr("<[(", c)) ++in_paren;
-		if (strchr(">])", c) && in_paren > 0) --in_paren;
+		if (strchr("<[(", c))
+			++in_paren;
+		if (strchr(">])", c) && in_paren > 0)
+			--in_paren;
 
 
-		if ((! in_paren) && isalpha(c) && 
-		     strchr(exempt, c) == 0)
+		if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
 			return i;
 			return i;
 	}
 	}
 
 
@@ -359,17 +476,165 @@ first_alpha(const char *string, const char *exempt)
 }
 }
 
 
 /*
 /*
- * Get the first selected item in the dialog_list_item list.
+ * ncurses uses ESC to detect escaped char sequences. This resutl in
+ * a small timeout before ESC is actually delivered to the application.
+ * lxdialog suggest <ESC> <ESC> which is correctly translated to two
+ * times esc. But then we need to ignore the second esc to avoid stepping
+ * out one menu too much. Filter away all escaped key sequences since
+ * keypad(FALSE) turn off ncurses support for escape sequences - and thats
+ * needed to make notimeout() do as expected.
  */
  */
-struct dialog_list_item *
-first_sel_item(int item_no, struct dialog_list_item ** items)
+int on_key_esc(WINDOW *win)
 {
 {
-	int i;
+	int key;
+	int key2;
+	int key3;
+
+	nodelay(win, TRUE);
+	keypad(win, FALSE);
+	key = wgetch(win);
+	key2 = wgetch(win);
+	do {
+		key3 = wgetch(win);
+	} while (key3 != ERR);
+	nodelay(win, FALSE);
+	keypad(win, TRUE);
+	if (key == KEY_ESC && key2 == ERR)
+		return KEY_ESC;
+	else if (key != ERR && key != KEY_ESC && key2 == ERR)
+		ungetch(key);
+
+	return -1;
+}
+
+/* redraw screen in new size */
+int on_key_resize(void)
+{
+	dialog_clear();
+	return KEY_RESIZE;
+}
+
+struct dialog_list *item_cur;
+struct dialog_list item_nil;
+struct dialog_list *item_head;
+
+void item_reset(void)
+{
+	struct dialog_list *p, *next;
+
+	for (p = item_head; p; p = next) {
+		next = p->next;
+		free(p);
+	}
+	item_head = NULL;
+	item_cur = &item_nil;
+}
+
+void item_make(const char *fmt, ...)
+{
+	va_list ap;
+	struct dialog_list *p = malloc(sizeof(*p));
+
+	if (item_head)
+		item_cur->next = p;
+	else
+		item_head = p;
+	item_cur = p;
+	memset(p, 0, sizeof(*p));
+
+	va_start(ap, fmt);
+	vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
+	va_end(ap);
+}
+
+void item_add_str(const char *fmt, ...)
+{
+	va_list ap;
+        size_t avail;
+
+	avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
+
+	va_start(ap, fmt);
+	vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
+		  avail, fmt, ap);
+	item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
+	va_end(ap);
+}
+
+void item_set_tag(char tag)
+{
+	item_cur->node.tag = tag;
+}
+void item_set_data(void *ptr)
+{
+	item_cur->node.data = ptr;
+}
+
+void item_set_selected(int val)
+{
+	item_cur->node.selected = val;
+}
+
+int item_activate_selected(void)
+{
+	item_foreach()
+		if (item_is_selected())
+			return 1;
+	return 0;
+}
+
+void *item_data(void)
+{
+	return item_cur->node.data;
+}
+
+char item_tag(void)
+{
+	return item_cur->node.tag;
+}
+
+int item_count(void)
+{
+	int n = 0;
+	struct dialog_list *p;
+
+	for (p = item_head; p; p = p->next)
+		n++;
+	return n;
+}
+
+void item_set(int n)
+{
+	int i = 0;
+	item_foreach()
+		if (i++ == n)
+			return;
+}
 
 
-	for (i = 0; i < item_no; i++) {
-		if (items[i]->selected)
-			return items[i];
+int item_n(void)
+{
+	int n = 0;
+	struct dialog_list *p;
+
+	for (p = item_head; p; p = p->next) {
+		if (p == item_cur)
+			return n;
+		n++;
 	}
 	}
+	return 0;
+}
 
 
-	return NULL;
+const char *item_str(void)
+{
+	return item_cur->node.str;
+}
+
+int item_is_selected(void)
+{
+	return (item_cur->node.selected != 0);
+}
+
+int item_is_tag(char tag)
+{
+	return (item_cur->node.tag == tag);
 }
 }

+ 76 - 80
package/config/lxdialog/yesno.c

@@ -24,95 +24,91 @@
 /*
 /*
  * Display termination buttons
  * Display termination buttons
  */
  */
-static void
-print_buttons(WINDOW *dialog, int height, int width, int selected)
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
 {
 {
-    int x = width / 2 - 10;
-    int y = height - 2;
+	int x = width / 2 - 10;
+	int y = height - 2;
 
 
-    print_button (dialog, " Yes ", y, x, selected == 0);
-    print_button (dialog, "  No  ", y, x + 13, selected == 1);
+	print_button(dialog, " Yes ", y, x, selected == 0);
+	print_button(dialog, "  No  ", y, x + 13, selected == 1);
 
 
-    wmove(dialog, y, x+1 + 13*selected );
-    wrefresh (dialog);
+	wmove(dialog, y, x + 1 + 13 * selected);
+	wrefresh(dialog);
 }
 }
 
 
 /*
 /*
  * Display a dialog box with two buttons - Yes and No
  * Display a dialog box with two buttons - Yes and No
  */
  */
-int
-dialog_yesno (const char *title, const char *prompt, int height, int width)
+int dialog_yesno(const char *title, const char *prompt, int height, int width)
 {
 {
-    int i, x, y, key = 0, button = 0;
-    WINDOW *dialog;
-
-    /* center dialog box on screen */
-    x = (COLS - width) / 2;
-    y = (LINES - height) / 2;
-
-    draw_shadow (stdscr, y, x, height, width);
-
-    dialog = newwin (height, width, y, x);
-    keypad (dialog, TRUE);
-
-    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
-    wattrset (dialog, border_attr);
-    mvwaddch (dialog, height-3, 0, ACS_LTEE);
-    for (i = 0; i < width - 2; i++)
-	waddch (dialog, ACS_HLINE);
-    wattrset (dialog, dialog_attr);
-    waddch (dialog, ACS_RTEE);
-
-    if (title != NULL && strlen(title) >= width-2 ) {
-	/* truncate long title -- mec */
-	char * title2 = malloc(width-2+1);
-	memcpy( title2, title, width-2 );
-	title2[width-2] = '\0';
-	title = title2;
-    }
-
-    if (title != NULL) {
-	wattrset (dialog, title_attr);
-	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
-	waddstr (dialog, (char *)title);
-	waddch (dialog, ' ');
-    }
-
-    wattrset (dialog, dialog_attr);
-    print_autowrap (dialog, prompt, width - 2, 1, 3);
-
-    print_buttons(dialog, height, width, 0);
-
-    while (key != ESC) {
-	key = wgetch (dialog);
-	switch (key) {
-	case 'Y':
-	case 'y':
-	    delwin (dialog);
-	    return 0;
-	case 'N':
-	case 'n':
-	    delwin (dialog);
-	    return 1;
-
-	case TAB:
-	case KEY_LEFT:
-	case KEY_RIGHT:
-	    button = ((key == KEY_LEFT ? --button : ++button) < 0)
-			? 1 : (button > 1 ? 0 : button);
-
-	    print_buttons(dialog, height, width, button);
-	    wrefresh (dialog);
-	    break;
-	case ' ':
-	case '\n':
-	    delwin (dialog);
-	    return button;
-	case ESC:
-	    break;
+	int i, x, y, key = 0, button = 0;
+	WINDOW *dialog;
+
+do_resize:
+	if (getmaxy(stdscr) < (height + 4))
+		return -ERRDISPLAYTOOSMALL;
+	if (getmaxx(stdscr) < (width + 4))
+		return -ERRDISPLAYTOOSMALL;
+
+	/* center dialog box on screen */
+	x = (COLS - width) / 2;
+	y = (LINES - height) / 2;
+
+	draw_shadow(stdscr, y, x, height, width);
+
+	dialog = newwin(height, width, y, x);
+	keypad(dialog, TRUE);
+
+	draw_box(dialog, 0, 0, height, width,
+		 dlg.dialog.atr, dlg.border.atr);
+	wattrset(dialog, dlg.border.atr);
+	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+	for (i = 0; i < width - 2; i++)
+		waddch(dialog, ACS_HLINE);
+	wattrset(dialog, dlg.dialog.atr);
+	waddch(dialog, ACS_RTEE);
+
+	print_title(dialog, title, width);
+
+	wattrset(dialog, dlg.dialog.atr);
+	print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+	print_buttons(dialog, height, width, 0);
+
+	while (key != KEY_ESC) {
+		key = wgetch(dialog);
+		switch (key) {
+		case 'Y':
+		case 'y':
+			delwin(dialog);
+			return 0;
+		case 'N':
+		case 'n':
+			delwin(dialog);
+			return 1;
+
+		case TAB:
+		case KEY_LEFT:
+		case KEY_RIGHT:
+			button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button);
+
+			print_buttons(dialog, height, width, button);
+			wrefresh(dialog);
+			break;
+		case ' ':
+		case '\n':
+			delwin(dialog);
+			return button;
+		case KEY_ESC:
+			key = on_key_esc(dialog);
+			break;
+		case KEY_RESIZE:
+			delwin(dialog);
+			on_key_resize();
+			goto do_resize;
+		}
 	}
 	}
-    }
 
 
-    delwin (dialog);
-    return -1;			/* ESC pressed */
+	delwin(dialog);
+	return key;		/* ESC pressed */
 }
 }

+ 228 - 277
package/config/mconf.c

@@ -5,13 +5,11 @@
  * Introduced single menu mode (show all sub-menus in one large tree).
  * Introduced single menu mode (show all sub-menus in one large tree).
  * 2002-11-06 Petr Baudis <pasky@ucw.cz>
  * 2002-11-06 Petr Baudis <pasky@ucw.cz>
  *
  *
- * Directly use liblxdialog library routines.
- * 2002-11-14 Petr Baudis <pasky@ucw.cz>
+ * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  */
  */
 
 
 #include <sys/ioctl.h>
 #include <sys/ioctl.h>
 #include <sys/wait.h>
 #include <sys/wait.h>
-#include <sys/termios.h>
 #include <ctype.h>
 #include <ctype.h>
 #include <errno.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fcntl.h>
@@ -22,14 +20,14 @@
 #include <string.h>
 #include <string.h>
 #include <termios.h>
 #include <termios.h>
 #include <unistd.h>
 #include <unistd.h>
-
-#include "lxdialog/dialog.h"
+#include <locale.h>
 
 
 #define LKC_DIRECT_LINK
 #define LKC_DIRECT_LINK
 #include "lkc.h"
 #include "lkc.h"
+#include "lxdialog/dialog.h"
 
 
 static char menu_backtitle[128];
 static char menu_backtitle[128];
-static const char mconf_readme[] =
+static const char mconf_readme[] = N_(
 "Overview\n"
 "Overview\n"
 "--------\n"
 "--------\n"
 "Some features may be built directly into Buildroot.  Some features\n"
 "Some features may be built directly into Buildroot.  Some features\n"
@@ -160,39 +158,53 @@ static const char mconf_readme[] =
 "\n"
 "\n"
 "Note that this mode can eventually be a little more CPU expensive\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"
 "(especially with a larger number of unrolled categories) than the\n"
-"default mode.\n",
-menu_instructions[] =
+"default mode.\n"
+"\n"
+"Different color themes available\n"
+"--------------------------------\n"
+"It is possible to select different color themes using the variable\n"
+"MENUCONFIG_COLOR. To select a theme use:\n"
+"\n"
+"make MENUCONFIG_COLOR=<theme> menuconfig\n"
+"\n"
+"Available themes are\n"
+" mono       => selects colors suitable for monochrome displays\n"
+" blackbg    => selects a color scheme with black background\n"
+" classic    => theme with blue background. The classic look\n"
+" bluetitle  => a LCD friendly version of classic. (default)\n"
+"\n"),
+menu_instructions[] = N_(
 	"Arrow keys navigate the menu.  "
 	"Arrow keys navigate the menu.  "
 	"<Enter> selects submenus --->.  "
 	"<Enter> selects submenus --->.  "
 	"Highlighted letters are hotkeys.  "
 	"Highlighted letters are hotkeys.  "
 	"Pressing <Y> selectes a feature, while <N> will exclude a feature.  "
 	"Pressing <Y> selectes a feature, while <N> will exclude a feature.  "
 	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  "
 	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  "
-	"Legend: [*] feature is selected  [ ] feature is excluded",
-radiolist_instructions[] =
+	"Legend: [*] feature is selected  [ ] feature is excluded"),
+radiolist_instructions[] = N_(
 	"Use the arrow keys to navigate this window or "
 	"Use the arrow keys to navigate this window or "
 	"press the hotkey of the item you wish to select "
 	"press the hotkey of the item you wish to select "
 	"followed by the <SPACE BAR>. "
 	"followed by the <SPACE BAR>. "
-	"Press <?> for additional information about this option.",
-inputbox_instructions_int[] =
+	"Press <?> for additional information about this option."),
+inputbox_instructions_int[] = N_(
 	"Please enter a decimal value. "
 	"Please enter a decimal value. "
 	"Fractions will not be accepted.  "
 	"Fractions will not be accepted.  "
-	"Use the <TAB> key to move from the input field to the buttons below it.",
-inputbox_instructions_hex[] =
+	"Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_hex[] = N_(
 	"Please enter a hexadecimal value. "
 	"Please enter a hexadecimal value. "
-	"Use the <TAB> key to move from the input field to the buttons below it.",
-inputbox_instructions_string[] =
+	"Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_string[] = N_(
 	"Please enter a string value. "
 	"Please enter a string value. "
-	"Use the <TAB> key to move from the input field to the buttons below it.",
-setmod_text[] =
+	"Use the <TAB> key to move from the input field to the buttons below it."),
+setmod_text[] = N_(
 	"This feature depends on another which has been configured as a module.\n"
 	"This feature depends on another which has been configured as a module.\n"
-	"As a result, this feature will be built as a module.",
-nohelp_text[] =
-	"There is no help available for this option.\n",
-load_config_text[] =
+	"As a result, this feature will be built as a module."),
+nohelp_text[] = N_(
+	"There is no help available for this option.\n"),
+load_config_text[] = N_(
 	"Enter the name of the configuration file you wish to load.  "
 	"Enter the name of the configuration file you wish to load.  "
 	"Accept the name shown to restore the configuration you "
 	"Accept the name shown to restore the configuration you "
-	"last retrieved.  Leave blank to abort.",
-load_config_help[] =
+	"last retrieved.  Leave blank to abort."),
+load_config_help[] = N_(
 	"\n"
 	"\n"
 	"For various reasons, one may wish to keep several different Buildroot\n"
 	"For various reasons, one may wish to keep several different Buildroot\n"
 	"configurations available on a single machine.\n"
 	"configurations available on a single machine.\n"
@@ -202,11 +214,11 @@ load_config_help[] =
 	"to modify that configuration.\n"
 	"to modify that configuration.\n"
 	"\n"
 	"\n"
 	"If you are uncertain, then you have probably never used alternate\n"
 	"If you are uncertain, then you have probably never used alternate\n"
-	"configuration files.  You should therefor leave this blank to abort.\n",
-save_config_text[] =
+	"configuration files.  You should therefor leave this blank to abort.\n"),
+save_config_text[] = N_(
 	"Enter a filename to which this configuration should be saved "
 	"Enter a filename to which this configuration should be saved "
-	"as an alternate.  Leave blank to abort.",
-save_config_help[] =
+	"as an alternate.  Leave blank to abort."),
+save_config_help[] = N_(
 	"\n"
 	"\n"
 	"For various reasons, one may wish to keep different Buildroot\n"
 	"For various reasons, one may wish to keep different Buildroot\n"
 	"configurations available on a single machine.\n"
 	"configurations available on a single machine.\n"
@@ -216,10 +228,11 @@ save_config_help[] =
 	"configuration options you have selected at that time.\n"
 	"configuration options you have selected at that time.\n"
 	"\n"
 	"\n"
 	"If you are uncertain what all this means then you should probably\n"
 	"If you are uncertain what all this means then you should probably\n"
-	"leave this blank.\n",
-search_help[] =
+	"leave this blank.\n"),
+search_help[] = N_(
 	"\n"
 	"\n"
 	"Search for CONFIG_ symbols and display their relations.\n"
 	"Search for CONFIG_ symbols and display their relations.\n"
+	"Regular expressions are allowed.\n"
 	"Example: search for \"^FOO\"\n"
 	"Example: search for \"^FOO\"\n"
 	"Result:\n"
 	"Result:\n"
 	"-----------------------------------------------------------------\n"
 	"-----------------------------------------------------------------\n"
@@ -254,7 +267,7 @@ search_help[] =
 	"Examples: USB	=> find all CONFIG_ symbols containing USB\n"
 	"Examples: USB	=> find all CONFIG_ symbols containing USB\n"
 	"          ^USB => find all CONFIG_ symbols starting with USB\n"
 	"          ^USB => find all CONFIG_ symbols starting with USB\n"
 	"          USB$ => find all CONFIG_ symbols ending with USB\n"
 	"          USB$ => find all CONFIG_ symbols ending with USB\n"
-	"\n";
+	"\n");
 
 
 static char filename[PATH_MAX+1] = ".config";
 static char filename[PATH_MAX+1] = ".config";
 static int indent;
 static int indent;
@@ -264,9 +277,6 @@ static struct menu *current_menu;
 static int child_count;
 static int child_count;
 static int single_menu_mode;
 static int single_menu_mode;
 
 
-static struct dialog_list_item *items[16384]; /* FIXME: This ought to be dynamic. */
-static int item_no;
-
 static void conf(struct menu *menu);
 static void conf(struct menu *menu);
 static void conf_choice(struct menu *menu);
 static void conf_choice(struct menu *menu);
 static void conf_string(struct menu *menu);
 static void conf_string(struct menu *menu);
@@ -275,7 +285,6 @@ static void conf_save(void);
 static void show_textbox(const char *title, const char *text, int r, int c);
 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_helptext(const char *title, const char *text);
 static void show_help(struct menu *menu);
 static void show_help(struct menu *menu);
-static void show_file(const char *filename, const char *title, int r, int c);
 
 
 static void init_wsize(void)
 static void init_wsize(void)
 {
 {
@@ -303,8 +312,8 @@ static void init_wsize(void)
 	}
 	}
 
 
 	if (rows < 19 || cols < 80) {
 	if (rows < 19 || cols < 80) {
-		fprintf(stderr, "Your display is too small to run Menuconfig!\n");
-		fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
+		fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
+		fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
 		exit(1);
 		exit(1);
 	}
 	}
 
 
@@ -312,65 +321,6 @@ static void init_wsize(void)
 	cols -= 5;
 	cols -= 5;
 }
 }
 
 
-static void cinit(void)
-{
-	item_no = 0;
-}
-
-static void cmake(void)
-{
-	items[item_no] = malloc(sizeof(struct dialog_list_item));
-	memset(items[item_no], 0, sizeof(struct dialog_list_item));
-	items[item_no]->tag = malloc(32); items[item_no]->tag[0] = 0;
-	items[item_no]->name = malloc(512); items[item_no]->name[0] = 0;
-	items[item_no]->namelen = 0;
-	item_no++;
-}
-
-static int cprint_name(const char *fmt, ...)
-{
-	va_list ap;
-	int res;
-
-	if (!item_no)
-		cmake();
-	va_start(ap, fmt);
-	res = vsnprintf(items[item_no - 1]->name + items[item_no - 1]->namelen,
-			512 - items[item_no - 1]->namelen, fmt, ap);
-	if (res > 0)
-		items[item_no - 1]->namelen += res;
-	va_end(ap);
-
-	return res;
-}
-
-static int cprint_tag(const char *fmt, ...)
-{
-	va_list ap;
-	int res;
-
-	if (!item_no)
-		cmake();
-	va_start(ap, fmt);
-	res = vsnprintf(items[item_no - 1]->tag, 32, fmt, ap);
-	va_end(ap);
-
-	return res;
-}
-
-static void cdone(void)
-{
-	int i;
-
-	for (i = 0; i < item_no; i++) {
-		free(items[i]->tag);
-		free(items[i]->name);
-		free(items[i]);
-	}
-
-	item_no = 0;
-}
-
 static void get_prompt_str(struct gstr *r, struct property *prop)
 static void get_prompt_str(struct gstr *r, struct property *prop)
 {
 {
 	int i, j;
 	int i, j;
@@ -447,15 +397,17 @@ static void search_conf(void)
 {
 {
 	struct symbol **sym_arr;
 	struct symbol **sym_arr;
 	struct gstr res;
 	struct gstr res;
-
+	int dres;
 again:
 again:
-	switch (dialog_inputbox("Search Configuration Parameter",
-				"Enter Keyword", 10, 75,
-				NULL)) {
+	dialog_clear();
+	dres = dialog_inputbox(_("Search Configuration Parameter"),
+			      _("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"),
+			      10, 75, "");
+	switch (dres) {
 	case 0:
 	case 0:
 		break;
 		break;
 	case 1:
 	case 1:
-		show_helptext("Search Configuration", search_help);
+		show_helptext(_("Search Configuration"), search_help);
 		goto again;
 		goto again;
 	default:
 	default:
 		return;
 		return;
@@ -464,7 +416,7 @@ again:
 	sym_arr = sym_re_search(dialog_input_result);
 	sym_arr = sym_re_search(dialog_input_result);
 	res = get_relations_str(sym_arr);
 	res = get_relations_str(sym_arr);
 	free(sym_arr);
 	free(sym_arr);
-	show_textbox("Search Results", str_get(&res), 0, 0);
+	show_textbox(_("Search Results"), str_get(&res), 0, 0);
 	str_free(&res);
 	str_free(&res);
 }
 }
 
 
@@ -488,26 +440,24 @@ static void build_conf(struct menu *menu)
 			switch (prop->type) {
 			switch (prop->type) {
 			case P_MENU:
 			case P_MENU:
 				child_count++;
 				child_count++;
-				cmake();
-				cprint_tag("m%p", menu);
-
 				if (single_menu_mode) {
 				if (single_menu_mode) {
-					cprint_name("%s%*c%s",
-						menu->data ? "-->" : "++>",
-						indent + 1, ' ', prompt);
-				} else {
-					cprint_name("   %*c%s  --->", indent + 1, ' ', prompt);
-				}
-
+					item_make("%s%*c%s",
+						  menu->data ? "-->" : "++>",
+						  indent + 1, ' ', prompt);
+				} else
+					item_make("   %*c%s  --->", indent + 1, ' ', prompt);
+
+				item_set_tag('m');
+				item_set_data(menu);
 				if (single_menu_mode && menu->data)
 				if (single_menu_mode && menu->data)
 					goto conf_childs;
 					goto conf_childs;
 				return;
 				return;
 			default:
 			default:
 				if (prompt) {
 				if (prompt) {
 					child_count++;
 					child_count++;
-					cmake();
-					cprint_tag(":%p", menu);
-					cprint_name("---%*c%s", indent + 1, ' ', prompt);
+					item_make("---%*c%s", indent + 1, ' ', prompt);
+					item_set_tag(':');
+					item_set_data(menu);
 				}
 				}
 			}
 			}
 		} else
 		} else
@@ -515,7 +465,6 @@ static void build_conf(struct menu *menu)
 		goto conf_childs;
 		goto conf_childs;
 	}
 	}
 
 
-	cmake();
 	type = sym_get_type(sym);
 	type = sym_get_type(sym);
 	if (sym_is_choice(sym)) {
 	if (sym_is_choice(sym)) {
 		struct symbol *def_sym = sym_get_choice_value(sym);
 		struct symbol *def_sym = sym_get_choice_value(sym);
@@ -529,10 +478,9 @@ static void build_conf(struct menu *menu)
 
 
 		val = sym_get_tristate_value(sym);
 		val = sym_get_tristate_value(sym);
 		if (sym_is_changable(sym)) {
 		if (sym_is_changable(sym)) {
-			cprint_tag("t%p", menu);
 			switch (type) {
 			switch (type) {
 			case S_BOOLEAN:
 			case S_BOOLEAN:
-				cprint_name("[%c]", val == no ? ' ' : '*');
+				item_make("[%c]", val == no ? ' ' : '*');
 				break;
 				break;
 			case S_TRISTATE:
 			case S_TRISTATE:
 				switch (val) {
 				switch (val) {
@@ -540,19 +488,22 @@ static void build_conf(struct menu *menu)
 				case mod: ch = 'M'; break;
 				case mod: ch = 'M'; break;
 				default:  ch = ' '; break;
 				default:  ch = ' '; break;
 				}
 				}
-				cprint_name("<%c>", ch);
+				item_make("<%c>", ch);
 				break;
 				break;
 			}
 			}
+			item_set_tag('t');
+			item_set_data(menu);
 		} else {
 		} else {
-			cprint_tag("%c%p", def_menu ? 't' : ':', menu);
-			cprint_name("   ");
+			item_make("   ");
+			item_set_tag(def_menu ? 't' : ':');
+			item_set_data(menu);
 		}
 		}
 
 
-		cprint_name("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+		item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
 		if (val == yes) {
 		if (val == yes) {
 			if (def_menu) {
 			if (def_menu) {
-				cprint_name(" (%s)", menu_get_prompt(def_menu));
-				cprint_name("  --->");
+				item_add_str(" (%s)", menu_get_prompt(def_menu));
+				item_add_str("  --->");
 				if (def_menu->list) {
 				if (def_menu->list) {
 					indent += 2;
 					indent += 2;
 					build_conf(def_menu);
 					build_conf(def_menu);
@@ -563,53 +514,59 @@ static void build_conf(struct menu *menu)
 		}
 		}
 	} else {
 	} else {
 		if (menu == current_menu) {
 		if (menu == current_menu) {
-			cprint_tag(":%p", menu);
-			cprint_name("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+			item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+			item_set_tag(':');
+			item_set_data(menu);
 			goto conf_childs;
 			goto conf_childs;
 		}
 		}
 		child_count++;
 		child_count++;
 		val = sym_get_tristate_value(sym);
 		val = sym_get_tristate_value(sym);
 		if (sym_is_choice_value(sym) && val == yes) {
 		if (sym_is_choice_value(sym) && val == yes) {
-			cprint_tag(":%p", menu);
-			cprint_name("   ");
+			item_make("   ");
+			item_set_tag(':');
+			item_set_data(menu);
 		} else {
 		} else {
 			switch (type) {
 			switch (type) {
 			case S_BOOLEAN:
 			case S_BOOLEAN:
-				cprint_tag("t%p", menu);
 				if (sym_is_changable(sym))
 				if (sym_is_changable(sym))
-					cprint_name("[%c]", val == no ? ' ' : '*');
+					item_make("[%c]", val == no ? ' ' : '*');
 				else
 				else
-					cprint_name("---");
+					item_make("---");
+				item_set_tag('t');
+				item_set_data(menu);
 				break;
 				break;
 			case S_TRISTATE:
 			case S_TRISTATE:
-				cprint_tag("t%p", menu);
 				switch (val) {
 				switch (val) {
 				case yes: ch = '*'; break;
 				case yes: ch = '*'; break;
 				case mod: ch = 'M'; break;
 				case mod: ch = 'M'; break;
 				default:  ch = ' '; break;
 				default:  ch = ' '; break;
 				}
 				}
 				if (sym_is_changable(sym))
 				if (sym_is_changable(sym))
-					cprint_name("<%c>", ch);
+					item_make("<%c>", ch);
 				else
 				else
-					cprint_name("---");
+					item_make("---");
+				item_set_tag('t');
+				item_set_data(menu);
 				break;
 				break;
 			default:
 			default:
-				cprint_tag("s%p", menu);
-				tmp = cprint_name("(%s)", sym_get_string_value(sym));
+				tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
+				item_make("(%s)", sym_get_string_value(sym));
 				tmp = indent - tmp + 4;
 				tmp = indent - tmp + 4;
 				if (tmp < 0)
 				if (tmp < 0)
 					tmp = 0;
 					tmp = 0;
-				cprint_name("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
-					(sym_has_value(sym) || !sym_is_changable(sym)) ?
-					"" : " (NEW)");
+				item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
+					     (sym_has_value(sym) || !sym_is_changable(sym)) ?
+					     "" : " (NEW)");
+				item_set_tag('s');
+				item_set_data(menu);
 				goto conf_childs;
 				goto conf_childs;
 			}
 			}
 		}
 		}
-		cprint_name("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
-			(sym_has_value(sym) || !sym_is_changable(sym)) ?
-			"" : " (NEW)");
+		item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
+			  (sym_has_value(sym) || !sym_is_changable(sym)) ?
+			  "" : " (NEW)");
 		if (menu->prompt->type == P_MENU) {
 		if (menu->prompt->type == P_MENU) {
-			cprint_name("  --->");
+			item_add_str("  --->");
 			return;
 			return;
 		}
 		}
 	}
 	}
@@ -623,56 +580,48 @@ conf_childs:
 
 
 static void conf(struct menu *menu)
 static void conf(struct menu *menu)
 {
 {
-	struct dialog_list_item *active_item = NULL;
 	struct menu *submenu;
 	struct menu *submenu;
 	const char *prompt = menu_get_prompt(menu);
 	const char *prompt = menu_get_prompt(menu);
 	struct symbol *sym;
 	struct symbol *sym;
-	char active_entry[40];
-	int stat, type;
+	struct menu *active_menu = NULL;
+	int res;
+	int s_scroll = 0;
 
 
-	unlink("lxdialog.scrltmp");
-	active_entry[0] = 0;
 	while (1) {
 	while (1) {
-		indent = 0;
-		child_count = 0;
+		item_reset();
 		current_menu = menu;
 		current_menu = menu;
-		cdone(); cinit();
 		build_conf(menu);
 		build_conf(menu);
 		if (!child_count)
 		if (!child_count)
 			break;
 			break;
 		if (menu == &rootmenu) {
 		if (menu == &rootmenu) {
-			cmake(); cprint_tag(":"); cprint_name("--- ");
-			cmake(); cprint_tag("L"); cprint_name("Load an Alternate Configuration File");
-			cmake(); cprint_tag("S"); cprint_name("Save Configuration to an Alternate File");
+			item_make("--- ");
+			item_set_tag(':');
+			item_make(_("    Load an Alternate Configuration File"));
+			item_set_tag('L');
+			item_make(_("    Save an Alternate Configuration File"));
+			item_set_tag('S');
 		}
 		}
 		dialog_clear();
 		dialog_clear();
-		stat = dialog_menu(prompt ? prompt : "Main Menu",
-				menu_instructions, rows, cols, rows - 10,
-				active_entry, item_no, items);
-		if (stat < 0)
-			return;
-
-		if (stat == 1 || stat == 255)
+		res = dialog_menu(prompt ? prompt : _("Main Menu"),
+				  _(menu_instructions),
+				  active_menu, &s_scroll);
+		if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
 			break;
 			break;
-
-		active_item = first_sel_item(item_no, items);
-		if (!active_item)
+		if (!item_activate_selected())
 			continue;
 			continue;
-		active_item->selected = 0;
-		strncpy(active_entry, active_item->tag, sizeof(active_entry));
-		active_entry[sizeof(active_entry)-1] = 0;
-		type = active_entry[0];
-		if (!type)
+		if (!item_tag())
 			continue;
 			continue;
 
 
-		sym = NULL;
-		submenu = NULL;
-		if (sscanf(active_entry + 1, "%p", &submenu) == 1)
+		submenu = item_data();
+		active_menu = item_data();
+		if (submenu)
 			sym = submenu->sym;
 			sym = submenu->sym;
+		else
+			sym = NULL;
 
 
-		switch (stat) {
+		switch (res) {
 		case 0:
 		case 0:
-			switch (type) {
+			switch (item_tag()) {
 			case 'm':
 			case 'm':
 				if (single_menu_mode)
 				if (single_menu_mode)
 					submenu->data = (void *) (long) !submenu->data;
 					submenu->data = (void *) (long) !submenu->data;
@@ -700,10 +649,10 @@ static void conf(struct menu *menu)
 			if (sym)
 			if (sym)
 				show_help(submenu);
 				show_help(submenu);
 			else
 			else
-				show_helptext("README", mconf_readme);
+				show_helptext("README", _(mconf_readme));
 			break;
 			break;
 		case 3:
 		case 3:
-			if (type == 't') {
+			if (item_is_tag('t')) {
 				if (sym_set_tristate_value(sym, yes))
 				if (sym_set_tristate_value(sym, yes))
 					break;
 					break;
 				if (sym_set_tristate_value(sym, mod))
 				if (sym_set_tristate_value(sym, mod))
@@ -711,17 +660,17 @@ static void conf(struct menu *menu)
 			}
 			}
 			break;
 			break;
 		case 4:
 		case 4:
-			if (type == 't')
+			if (item_is_tag('t'))
 				sym_set_tristate_value(sym, no);
 				sym_set_tristate_value(sym, no);
 			break;
 			break;
 		case 5:
 		case 5:
-			if (type == 't')
+			if (item_is_tag('t'))
 				sym_set_tristate_value(sym, mod);
 				sym_set_tristate_value(sym, mod);
 			break;
 			break;
 		case 6:
 		case 6:
-			if (type == 't')
+			if (item_is_tag('t'))
 				sym_toggle_tristate_value(sym);
 				sym_toggle_tristate_value(sym);
-			else if (type == 'm')
+			else if (item_is_tag('m'))
 				conf(submenu);
 				conf(submenu);
 			break;
 			break;
 		case 7:
 		case 7:
@@ -733,13 +682,8 @@ static void conf(struct menu *menu)
 
 
 static void show_textbox(const char *title, const char *text, int r, int c)
 static void show_textbox(const char *title, const char *text, int r, int c)
 {
 {
-	int fd;
-
-	fd = creat(".help.tmp", 0777);
-	write(fd, text, strlen(text));
-	close(fd);
-	show_file(".help.tmp", title, r, c);
-	unlink(".help.tmp");
+	dialog_clear();
+	dialog_textbox(title, text, r, c);
 }
 }
 
 
 static void show_helptext(const char *title, const char *text)
 static void show_helptext(const char *title, const char *text)
@@ -755,8 +699,8 @@ static void show_help(struct menu *menu)
 	if (sym->help)
 	if (sym->help)
 	{
 	{
 		if (sym->name) {
 		if (sym->name) {
-			str_printf(&help, "%s:\n\n", sym->name);
-			str_append(&help, sym->help);
+			str_printf(&help, "CONFIG_%s:\n\n", sym->name);
+			str_append(&help, _(sym->help));
 			str_append(&help, "\n");
 			str_append(&help, "\n");
 		}
 		}
 	} else {
 	} else {
@@ -767,12 +711,6 @@ static void show_help(struct menu *menu)
 	str_free(&help);
 	str_free(&help);
 }
 }
 
 
-static void show_file(const char *filename, const char *title, int r, int c)
-{
-	while (dialog_textbox(title, filename, r ? r : rows, c ? c : cols) < 0)
-		;
-}
-
 static void conf_choice(struct menu *menu)
 static void conf_choice(struct menu *menu)
 {
 {
 	const char *prompt = menu_get_prompt(menu);
 	const char *prompt = menu_get_prompt(menu);
@@ -781,38 +719,44 @@ static void conf_choice(struct menu *menu)
 
 
 	active = sym_get_choice_value(menu->sym);
 	active = sym_get_choice_value(menu->sym);
 	while (1) {
 	while (1) {
+		int res;
+		int selected;
+		item_reset();
+
 		current_menu = menu;
 		current_menu = menu;
-		cdone(); cinit();
 		for (child = menu->list; child; child = child->next) {
 		for (child = menu->list; child; child = child->next) {
 			if (!menu_is_visible(child))
 			if (!menu_is_visible(child))
 				continue;
 				continue;
-			cmake();
-			cprint_tag("%p", child);
-			cprint_name("%s", menu_get_prompt(child));
+			item_make("%s", menu_get_prompt(child));
+			item_set_data(child);
+			if (child->sym == active)
+				item_set_selected(1);
 			if (child->sym == sym_get_choice_value(menu->sym))
 			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 */
+				item_set_tag('X');
 		}
 		}
-
-		switch (dialog_checklist(prompt ? prompt : "Main Menu",
-					radiolist_instructions, 15, 70, 6,
-					item_no, items, FLAG_RADIO)) {
+		dialog_clear();
+		res = dialog_checklist(prompt ? prompt : _("Main Menu"),
+					_(radiolist_instructions),
+					 15, 70, 6);
+		selected = item_activate_selected();
+		switch (res) {
 		case 0:
 		case 0:
-			if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) != 1)
-				break;
-			sym_set_tristate_value(child->sym, yes);
+			if (selected) {
+				child = item_data();
+				sym_set_tristate_value(child->sym, yes);
+			}
 			return;
 			return;
 		case 1:
 		case 1:
-			if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) == 1) {
+			if (selected) {
+				child = item_data();
 				show_help(child);
 				show_help(child);
 				active = child->sym;
 				active = child->sym;
 			} else
 			} else
 				show_help(menu);
 				show_help(menu);
 			break;
 			break;
-		case 255:
+		case KEY_ESC:
+			return;
+		case -ERRDISPLAYTOOSMALL:
 			return;
 			return;
 		}
 		}
 	}
 	}
@@ -823,35 +767,36 @@ static void conf_string(struct menu *menu)
 	const char *prompt = menu_get_prompt(menu);
 	const char *prompt = menu_get_prompt(menu);
 
 
 	while (1) {
 	while (1) {
+		int res;
 		char *heading;
 		char *heading;
 
 
 		switch (sym_get_type(menu->sym)) {
 		switch (sym_get_type(menu->sym)) {
 		case S_INT:
 		case S_INT:
-			heading = (char *) inputbox_instructions_int;
+			heading = _(inputbox_instructions_int);
 			break;
 			break;
 		case S_HEX:
 		case S_HEX:
-			heading = (char *) inputbox_instructions_hex;
+			heading = _(inputbox_instructions_hex);
 			break;
 			break;
 		case S_STRING:
 		case S_STRING:
-			heading = (char *) inputbox_instructions_string;
+			heading = _(inputbox_instructions_string);
 			break;
 			break;
 		default:
 		default:
 			heading = "Internal mconf error!";
 			heading = "Internal mconf error!";
-			/* panic? */;
 		}
 		}
-
-		switch (dialog_inputbox(prompt ? prompt : "Main Menu",
-					heading, 10, 75,
-					sym_get_string_value(menu->sym))) {
+		dialog_clear();
+		res = dialog_inputbox(prompt ? prompt : _("Main Menu"),
+				      heading, 10, 75,
+				      sym_get_string_value(menu->sym));
+		switch (res) {
 		case 0:
 		case 0:
 			if (sym_set_string_value(menu->sym, dialog_input_result))
 			if (sym_set_string_value(menu->sym, dialog_input_result))
 				return;
 				return;
-			show_textbox(NULL, "You have made an invalid entry.", 5, 43);
+			show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
 			break;
 			break;
 		case 1:
 		case 1:
 			show_help(menu);
 			show_help(menu);
 			break;
 			break;
-		case 255:
+		case KEY_ESC:
 			return;
 			return;
 		}
 		}
 	}
 	}
@@ -859,20 +804,24 @@ static void conf_string(struct menu *menu)
 
 
 static void conf_load(void)
 static void conf_load(void)
 {
 {
+
 	while (1) {
 	while (1) {
-		switch (dialog_inputbox(NULL, load_config_text, 11, 55,
-					filename)) {
+		int res;
+		dialog_clear();
+		res = dialog_inputbox(NULL, load_config_text,
+				      11, 55, filename);
+		switch(res) {
 		case 0:
 		case 0:
 			if (!dialog_input_result[0])
 			if (!dialog_input_result[0])
 				return;
 				return;
 			if (!conf_read(dialog_input_result))
 			if (!conf_read(dialog_input_result))
 				return;
 				return;
-			show_textbox(NULL, "File does not exist!", 5, 38);
+			show_textbox(NULL, _("File does not exist!"), 5, 38);
 			break;
 			break;
 		case 1:
 		case 1:
-			show_helptext("Load Alternate Configuration", load_config_help);
+			show_helptext(_("Load Alternate Configuration"), load_config_help);
 			break;
 			break;
-		case 255:
+		case KEY_ESC:
 			return;
 			return;
 		}
 		}
 	}
 	}
@@ -881,19 +830,22 @@ static void conf_load(void)
 static void conf_save(void)
 static void conf_save(void)
 {
 {
 	while (1) {
 	while (1) {
-		switch (dialog_inputbox(NULL, save_config_text, 11, 55,
-					filename)) {
+		int res;
+		dialog_clear();
+		res = dialog_inputbox(NULL, save_config_text,
+				      11, 55, filename);
+		switch(res) {
 		case 0:
 		case 0:
 			if (!dialog_input_result[0])
 			if (!dialog_input_result[0])
 				return;
 				return;
 			if (!conf_write(dialog_input_result))
 			if (!conf_write(dialog_input_result))
 				return;
 				return;
-			show_textbox(NULL, "Can't create file!  Probably a nonexistent directory.", 5, 60);
+			show_textbox(NULL, _("Can't create file!  Probably a nonexistent directory."), 5, 60);
 			break;
 			break;
 		case 1:
 		case 1:
-			show_helptext("Save Alternate Configuration", save_config_help);
+			show_helptext(_("Save Alternate Configuration"), save_config_help);
 			break;
 			break;
-		case 255:
+		case KEY_ESC:
 			return;
 			return;
 		}
 		}
 	}
 	}
@@ -902,42 +854,25 @@ static void conf_save(void)
 static void conf_cleanup(void)
 static void conf_cleanup(void)
 {
 {
 	tcsetattr(1, TCSAFLUSH, &ios_org);
 	tcsetattr(1, TCSAFLUSH, &ios_org);
-	unlink(".help.tmp");
-}
-
-static void winch_handler(int sig)
-{
-	struct winsize ws;
-
-	if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
-		rows = 24;
-		cols = 80;
-	} else {
-		rows = ws.ws_row;
-		cols = ws.ws_col;
-	}
-
-	if (rows < 19 || cols < 80) {
-		end_dialog();
-		fprintf(stderr, "Your display is too small to run Menuconfig!\n");
-		fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
-		exit(1);
-	}
-
-	rows -= 4;
-	cols -= 5;
-
 }
 }
 
 
 int main(int ac, char **av)
 int main(int ac, char **av)
 {
 {
+	struct symbol *sym;
 	char *mode;
 	char *mode;
-	int stat;
+	int res;
+
+	setlocale(LC_ALL, "");
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
 
 
 	conf_parse(av[1]);
 	conf_parse(av[1]);
 	conf_read(NULL);
 	conf_read(NULL);
 
 
-	snprintf(menu_backtitle, 128, "Buildroot Configuration");
+	sym = sym_lookup("VERSION", 0);
+	sym_calc_value(sym);
+	sprintf(menu_backtitle, _("Buildroot v%s Configuration"),
+		sym_get_string_value(sym));
 
 
 	mode = getenv("MENUCONFIG_MODE");
 	mode = getenv("MENUCONFIG_MODE");
 	if (mode) {
 	if (mode) {
@@ -948,26 +883,42 @@ int main(int ac, char **av)
 	tcgetattr(1, &ios_org);
 	tcgetattr(1, &ios_org);
 	atexit(conf_cleanup);
 	atexit(conf_cleanup);
 	init_wsize();
 	init_wsize();
-	init_dialog();
-	signal(SIGWINCH, winch_handler);
-	conf(&rootmenu);
-	end_dialog();
-
-	/* Restart dialog to act more like when lxdialog was still separate */
-	init_dialog();
+	reset_dialog();
+	init_dialog(menu_backtitle);
 	do {
 	do {
-		stat = dialog_yesno(NULL,
-				    "Do you wish to save your new Buildroot configuration?", 5, 60);
-	} while (stat < 0);
+		conf(&rootmenu);
+		dialog_clear();
+		if (conf_get_changed())
+			res = dialog_yesno(NULL,
+					   _("Do you wish to save your "
+					     "new Buildroot configuration?\n"
+					     "<ESC><ESC> to continue."),
+					   6, 60);
+		else
+			res = -1;
+	} while (res == KEY_ESC);
 	end_dialog();
 	end_dialog();
 
 
-	if (stat == 0) {
-		conf_write(NULL);
-		printf("\n\n"
+	switch (res) {
+	case 0:
+		if (conf_write(NULL)) {
+			fprintf(stderr, _("\n\n"
+				"Error during writing of the Buildroot configuration.\n"
+				"Your Buildroot configuration changes were NOT saved."
+				"\n\n"));
+			return 1;
+		}
+	case -1:
+		printf(_("\n\n"
 			"*** End of Buildroot configuration.\n"
 			"*** End of Buildroot configuration.\n"
-			"*** Check the top-level Makefile for additional configuration options.\n\n");
-	} else
-		printf("\n\nYour Buildroot configuration changes were NOT saved.\n\n");
+			"*** Execute 'make' to build Buildroot or try 'make help'."
+			"\n\n"));
+		break;
+	default:
+		fprintf(stderr, _("\n\n"
+			"Your Buildroot configuration changes were NOT saved."
+			"\n\n"));
+	}
 
 
-	return 0;
+	return conf_write_autoconf();
 }
 }

+ 43 - 14
package/config/menu.c

@@ -61,10 +61,11 @@ void menu_end_entry(void)
 {
 {
 }
 }
 
 
-void menu_add_menu(void)
+struct menu *menu_add_menu(void)
 {
 {
-	current_menu = current_entry;
+	menu_end_entry();
 	last_entry_ptr = &current_entry->list;
 	last_entry_ptr = &current_entry->list;
+	return current_menu = current_entry;
 }
 }
 
 
 void menu_end_menu(void)
 void menu_end_menu(void)
@@ -113,7 +114,7 @@ void menu_set_type(int type)
 		sym->type = type;
 		sym->type = type;
 		return;
 		return;
 	}
 	}
-	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n",
+	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
 	    sym->name ? sym->name : "<choice>",
 	    sym->name ? sym->name : "<choice>",
 	    sym_type_name(sym->type), sym_type_name(type));
 	    sym_type_name(sym->type), sym_type_name(type));
 }
 }
@@ -123,22 +124,27 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
 	struct property *prop = prop_alloc(type, current_entry->sym);
 	struct property *prop = prop_alloc(type, current_entry->sym);
 
 
 	prop->menu = current_entry;
 	prop->menu = current_entry;
-	prop->text = prompt;
 	prop->expr = expr;
 	prop->expr = expr;
 	prop->visible.expr = menu_check_dep(dep);
 	prop->visible.expr = menu_check_dep(dep);
 
 
 	if (prompt) {
 	if (prompt) {
+		if (isspace(*prompt)) {
+			prop_warn(prop, "leading whitespace ignored");
+			while (isspace(*prompt))
+				prompt++;
+		}
 		if (current_entry->prompt)
 		if (current_entry->prompt)
-			menu_warn(current_entry, "prompt redefined\n");
+			prop_warn(prop, "prompt redefined");
 		current_entry->prompt = prop;
 		current_entry->prompt = prop;
 	}
 	}
+	prop->text = prompt;
 
 
 	return prop;
 	return prop;
 }
 }
 
 
-void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
 {
 {
-	menu_add_prop(type, prompt, NULL, dep);
+	return menu_add_prop(type, prompt, NULL, dep);
 }
 }
 
 
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
@@ -151,6 +157,30 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
 	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
 	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
 }
 }
 
 
+void menu_add_option(int token, char *arg)
+{
+	struct property *prop;
+
+	switch (token) {
+	case T_OPT_MODULES:
+		prop = prop_alloc(P_DEFAULT, 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)
+			zconf_error("trying to redefine defconfig symbol");
+		break;
+	}
+}
+
+static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
+{
+	return sym2->type == S_INT || sym2->type == S_HEX ||
+	       (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
+}
+
 void sym_check_prop(struct symbol *sym)
 void sym_check_prop(struct symbol *sym)
 {
 {
 	struct property *prop;
 	struct property *prop;
@@ -185,8 +215,8 @@ void sym_check_prop(struct symbol *sym)
 			if (sym->type != S_INT && sym->type != S_HEX)
 			if (sym->type != S_INT && sym->type != S_HEX)
 				prop_warn(prop, "range is only allowed "
 				prop_warn(prop, "range is only allowed "
 				                "for int or hex symbols");
 				                "for int or hex symbols");
-			if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
-			    !sym_string_valid(sym, prop->expr->right.sym->name))
+			if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
+			    !menu_range_valid_sym(sym, prop->expr->right.sym))
 				prop_warn(prop, "range is invalid");
 				prop_warn(prop, "range is invalid");
 			break;
 			break;
 		default:
 		default:
@@ -318,11 +348,10 @@ void menu_finalize(struct menu *parent)
 
 
 	if (sym && !(sym->flags & SYMBOL_WARNED)) {
 	if (sym && !(sym->flags & SYMBOL_WARNED)) {
 		if (sym->type == S_UNKNOWN)
 		if (sym->type == S_UNKNOWN)
-			menu_warn(parent, "config symbol defined "
-			    "without type\n");
+			menu_warn(parent, "config symbol defined without type");
 
 
 		if (sym_is_choice(sym) && !parent->prompt)
 		if (sym_is_choice(sym) && !parent->prompt)
-			menu_warn(parent, "choice must have a prompt\n");
+			menu_warn(parent, "choice must have a prompt");
 
 
 		/* Check properties connected to this symbol */
 		/* Check properties connected to this symbol */
 		sym_check_prop(sym);
 		sym_check_prop(sym);
@@ -365,9 +394,9 @@ bool menu_is_visible(struct menu *menu)
 const char *menu_get_prompt(struct menu *menu)
 const char *menu_get_prompt(struct menu *menu)
 {
 {
 	if (menu->prompt)
 	if (menu->prompt)
-		return menu->prompt->text;
+		return _(menu->prompt->text);
 	else if (menu->sym)
 	else if (menu->sym)
-		return menu->sym->name;
+		return _(menu->sym->name);
 	return NULL;
 	return NULL;
 }
 }
 
 

+ 1753 - 0
package/config/qconf.cc

@@ -0,0 +1,1753 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <qapplication.h>
+#include <qmainwindow.h>
+#include <qtoolbar.h>
+#include <qlayout.h>
+#include <qvbox.h>
+#include <qsplitter.h>
+#include <qlistview.h>
+#include <qtextbrowser.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qmenubar.h>
+#include <qmessagebox.h>
+#include <qaction.h>
+#include <qheader.h>
+#include <qfiledialog.h>
+#include <qdragobject.h>
+#include <qregexp.h>
+
+#include <stdlib.h>
+
+#include "lkc.h"
+#include "qconf.h"
+
+#include "qconf.moc"
+#include "images.c"
+
+#ifdef _
+# undef _
+# define _ qgettext
+#endif
+
+static QApplication *configApp;
+static ConfigSettings *configSettings;
+
+QAction *ConfigMainWindow::saveAction;
+
+static inline QString qgettext(const char* str)
+{
+	return QString::fromLocal8Bit(gettext(str));
+}
+
+static inline QString qgettext(const QString& str)
+{
+	return QString::fromLocal8Bit(gettext(str.latin1()));
+}
+
+/**
+ * Reads a list of integer values from the application settings.
+ */
+QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
+{
+	QValueList<int> result;
+	QStringList entryList = readListEntry(key, ok);
+	if (ok) {
+		QStringList::Iterator it;
+		for (it = entryList.begin(); it != entryList.end(); ++it)
+			result.push_back((*it).toInt());
+	}
+
+	return result;
+}
+
+/**
+ * Writes a list of integer values to the application settings.
+ */
+bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
+{
+	QStringList stringList;
+	QValueList<int>::ConstIterator it;
+
+	for (it = value.begin(); it != value.end(); ++it)
+		stringList.push_back(QString::number(*it));
+	return writeEntry(key, stringList);
+}
+
+
+#if QT_VERSION >= 300
+/*
+ * set the new data
+ * TODO check the value
+ */
+void ConfigItem::okRename(int col)
+{
+	Parent::okRename(col);
+	sym_set_string_value(menu->sym, text(dataColIdx).latin1());
+	listView()->updateList(this);
+}
+#endif
+
+/*
+ * update the displayed of a menu entry
+ */
+void ConfigItem::updateMenu(void)
+{
+	ConfigList* list;
+	struct symbol* sym;
+	struct property *prop;
+	QString prompt;
+	int type;
+	tristate expr;
+
+	list = listView();
+	if (goParent) {
+		setPixmap(promptColIdx, list->menuBackPix);
+		prompt = "..";
+		goto set_prompt;
+	}
+
+	sym = menu->sym;
+	prop = menu->prompt;
+	prompt = QString::fromLocal8Bit(menu_get_prompt(menu));
+
+	if (prop) switch (prop->type) {
+	case P_MENU:
+		if (list->mode == singleMode || list->mode == symbolMode) {
+			/* a menuconfig entry is displayed differently
+			 * depending whether it's at the view root or a child.
+			 */
+			if (sym && list->rootEntry == menu)
+				break;
+			setPixmap(promptColIdx, list->menuPix);
+		} else {
+			if (sym)
+				break;
+			setPixmap(promptColIdx, 0);
+		}
+		goto set_prompt;
+	case P_COMMENT:
+		setPixmap(promptColIdx, 0);
+		goto set_prompt;
+	default:
+		;
+	}
+	if (!sym)
+		goto set_prompt;
+
+	setText(nameColIdx, QString::fromLocal8Bit(sym->name));
+
+	type = sym_get_type(sym);
+	switch (type) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		char ch;
+
+		if (!sym_is_changable(sym) && !list->showAll) {
+			setPixmap(promptColIdx, 0);
+			setText(noColIdx, QString::null);
+			setText(modColIdx, QString::null);
+			setText(yesColIdx, QString::null);
+			break;
+		}
+		expr = sym_get_tristate_value(sym);
+		switch (expr) {
+		case yes:
+			if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+				setPixmap(promptColIdx, list->choiceYesPix);
+			else
+				setPixmap(promptColIdx, list->symbolYesPix);
+			setText(yesColIdx, "Y");
+			ch = 'Y';
+			break;
+		case mod:
+			setPixmap(promptColIdx, list->symbolModPix);
+			setText(modColIdx, "M");
+			ch = 'M';
+			break;
+		default:
+			if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+				setPixmap(promptColIdx, list->choiceNoPix);
+			else
+				setPixmap(promptColIdx, list->symbolNoPix);
+			setText(noColIdx, "N");
+			ch = 'N';
+			break;
+		}
+		if (expr != no)
+			setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
+		if (expr != mod)
+			setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
+		if (expr != yes)
+			setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
+
+		setText(dataColIdx, QChar(ch));
+		break;
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		const char* data;
+
+		data = sym_get_string_value(sym);
+
+#if QT_VERSION >= 300
+		int i = list->mapIdx(dataColIdx);
+		if (i >= 0)
+			setRenameEnabled(i, TRUE);
+#endif
+		setText(dataColIdx, data);
+		if (type == S_STRING)
+			prompt = QString("%1: %2").arg(prompt).arg(data);
+		else
+			prompt = QString("(%2) %1").arg(prompt).arg(data);
+		break;
+	}
+	if (!sym_has_value(sym) && visible)
+		prompt += " (NEW)";
+set_prompt:
+	setText(promptColIdx, prompt);
+}
+
+void ConfigItem::testUpdateMenu(bool v)
+{
+	ConfigItem* i;
+
+	visible = v;
+	if (!menu)
+		return;
+
+	sym_calc_value(menu->sym);
+	if (menu->flags & MENU_CHANGED) {
+		/* the menu entry changed, so update all list items */
+		menu->flags &= ~MENU_CHANGED;
+		for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
+			i->updateMenu();
+	} else if (listView()->updateAll)
+		updateMenu();
+}
+
+void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
+{
+	ConfigList* list = listView();
+
+	if (visible) {
+		if (isSelected() && !list->hasFocus() && list->mode == menuMode)
+			Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
+		else
+			Parent::paintCell(p, cg, column, width, align);
+	} else
+		Parent::paintCell(p, list->disabledColorGroup, column, width, align);
+}
+
+/*
+ * construct a menu entry
+ */
+void ConfigItem::init(void)
+{
+	if (menu) {
+		ConfigList* list = listView();
+		nextItem = (ConfigItem*)menu->data;
+		menu->data = this;
+
+		if (list->mode != fullMode)
+			setOpen(TRUE);
+		sym_calc_value(menu->sym);
+	}
+	updateMenu();
+}
+
+/*
+ * destruct a menu entry
+ */
+ConfigItem::~ConfigItem(void)
+{
+	if (menu) {
+		ConfigItem** ip = (ConfigItem**)&menu->data;
+		for (; *ip; ip = &(*ip)->nextItem) {
+			if (*ip == this) {
+				*ip = nextItem;
+				break;
+			}
+		}
+	}
+}
+
+ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
+	: Parent(parent)
+{
+	connect(this, SIGNAL(lostFocus()), SLOT(hide()));
+}
+
+void ConfigLineEdit::show(ConfigItem* i)
+{
+	item = i;
+	if (sym_get_string_value(item->menu->sym))
+		setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
+	else
+		setText(QString::null);
+	Parent::show();
+	setFocus();
+}
+
+void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
+{
+	switch (e->key()) {
+	case Key_Escape:
+		break;
+	case Key_Return:
+	case Key_Enter:
+		sym_set_string_value(item->menu->sym, text().latin1());
+		parent()->updateList(item);
+		break;
+	default:
+		Parent::keyPressEvent(e);
+		return;
+	}
+	e->accept();
+	parent()->list->setFocus();
+	hide();
+}
+
+ConfigList::ConfigList(ConfigView* p, const char *name)
+	: Parent(p, name),
+	  updateAll(false),
+	  symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
+	  choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
+	  menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
+	  showAll(false), showName(false), showRange(false), showData(false),
+	  rootEntry(0), headerPopup(0)
+{
+	int i;
+
+	setSorting(-1);
+	setRootIsDecorated(TRUE);
+	disabledColorGroup = palette().active();
+	disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
+	inactivedColorGroup = palette().active();
+	inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
+
+	connect(this, SIGNAL(selectionChanged(void)),
+		SLOT(updateSelection(void)));
+
+	if (name) {
+		configSettings->beginGroup(name);
+		showAll = configSettings->readBoolEntry("/showAll", false);
+		showName = configSettings->readBoolEntry("/showName", false);
+		showRange = configSettings->readBoolEntry("/showRange", false);
+		showData = configSettings->readBoolEntry("/showData", false);
+		configSettings->endGroup();
+		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+	}
+
+	for (i = 0; i < colNr; i++)
+		colMap[i] = colRevMap[i] = -1;
+	addColumn(promptColIdx, "Option");
+
+	reinit();
+}
+
+void ConfigList::reinit(void)
+{
+	removeColumn(dataColIdx);
+	removeColumn(yesColIdx);
+	removeColumn(modColIdx);
+	removeColumn(noColIdx);
+	removeColumn(nameColIdx);
+
+	if (showName)
+		addColumn(nameColIdx, "Name");
+	if (showRange) {
+		addColumn(noColIdx, "N");
+		addColumn(modColIdx, "M");
+		addColumn(yesColIdx, "Y");
+	}
+	if (showData)
+		addColumn(dataColIdx, "Value");
+
+	updateListAll();
+}
+
+void ConfigList::saveSettings(void)
+{
+	if (name()) {
+		configSettings->beginGroup(name());
+		configSettings->writeEntry("/showName", showName);
+		configSettings->writeEntry("/showRange", showRange);
+		configSettings->writeEntry("/showData", showData);
+		configSettings->writeEntry("/showAll", showAll);
+		configSettings->endGroup();
+	}
+}
+
+ConfigItem* ConfigList::findConfigItem(struct menu *menu)
+{
+	ConfigItem* item = (ConfigItem*)menu->data;
+
+	for (; item; item = item->nextItem) {
+		if (this == item->listView())
+			break;
+	}
+
+	return item;
+}
+
+void ConfigList::updateSelection(void)
+{
+	struct menu *menu;
+	enum prop_type type;
+
+	ConfigItem* item = (ConfigItem*)selectedItem();
+	if (!item)
+		return;
+
+	menu = item->menu;
+	emit menuChanged(menu);
+	if (!menu)
+		return;
+	type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+	if (mode == menuMode && type == P_MENU)
+		emit menuSelected(menu);
+}
+
+void ConfigList::updateList(ConfigItem* item)
+{
+	ConfigItem* last = 0;
+
+	if (!rootEntry) {
+		if (mode != listMode)
+			goto update;
+		QListViewItemIterator it(this);
+		ConfigItem* item;
+
+		for (; it.current(); ++it) {
+			item = (ConfigItem*)it.current();
+			if (!item->menu)
+				continue;
+			item->testUpdateMenu(menu_is_visible(item->menu));
+		}
+		return;
+	}
+
+	if (rootEntry != &rootmenu && (mode == singleMode ||
+	    (mode == symbolMode && rootEntry->parent != &rootmenu))) {
+		item = firstChild();
+		if (!item)
+			item = new ConfigItem(this, 0, true);
+		last = item;
+	}
+	if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
+	    rootEntry->sym && rootEntry->prompt) {
+		item = last ? last->nextSibling() : firstChild();
+		if (!item)
+			item = new ConfigItem(this, last, rootEntry, true);
+		else
+			item->testUpdateMenu(true);
+
+		updateMenuList(item, rootEntry);
+		triggerUpdate();
+		return;
+	}
+update:
+	updateMenuList(this, rootEntry);
+	triggerUpdate();
+}
+
+void ConfigList::setValue(ConfigItem* item, tristate val)
+{
+	struct symbol* sym;
+	int type;
+	tristate oldval;
+
+	sym = item->menu ? item->menu->sym : 0;
+	if (!sym)
+		return;
+
+	type = sym_get_type(sym);
+	switch (type) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		oldval = sym_get_tristate_value(sym);
+
+		if (!sym_set_tristate_value(sym, val))
+			return;
+		if (oldval == no && item->menu->list)
+			item->setOpen(TRUE);
+		parent()->updateList(item);
+		break;
+	}
+}
+
+void ConfigList::changeValue(ConfigItem* item)
+{
+	struct symbol* sym;
+	struct menu* menu;
+	int type, oldexpr, newexpr;
+
+	menu = item->menu;
+	if (!menu)
+		return;
+	sym = menu->sym;
+	if (!sym) {
+		if (item->menu->list)
+			item->setOpen(!item->isOpen());
+		return;
+	}
+
+	type = sym_get_type(sym);
+	switch (type) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		oldexpr = sym_get_tristate_value(sym);
+		newexpr = sym_toggle_tristate_value(sym);
+		if (item->menu->list) {
+			if (oldexpr == newexpr)
+				item->setOpen(!item->isOpen());
+			else if (oldexpr == no)
+				item->setOpen(TRUE);
+		}
+		if (oldexpr != newexpr)
+			parent()->updateList(item);
+		break;
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+#if QT_VERSION >= 300
+		if (colMap[dataColIdx] >= 0)
+			item->startRename(colMap[dataColIdx]);
+		else
+#endif
+			parent()->lineEdit->show(item);
+		break;
+	}
+}
+
+void ConfigList::setRootMenu(struct menu *menu)
+{
+	enum prop_type type;
+
+	if (rootEntry == menu)
+		return;
+	type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
+	if (type != P_MENU)
+		return;
+	updateMenuList(this, 0);
+	rootEntry = menu;
+	updateListAll();
+	setSelected(currentItem(), hasFocus());
+	ensureItemVisible(currentItem());
+}
+
+void ConfigList::setParentMenu(void)
+{
+	ConfigItem* item;
+	struct menu *oldroot;
+
+	oldroot = rootEntry;
+	if (rootEntry == &rootmenu)
+		return;
+	setRootMenu(menu_get_parent_menu(rootEntry->parent));
+
+	QListViewItemIterator it(this);
+	for (; (item = (ConfigItem*)it.current()); it++) {
+		if (item->menu == oldroot) {
+			setCurrentItem(item);
+			ensureItemVisible(item);
+			break;
+		}
+	}
+}
+
+/*
+ * update all the children of a menu entry
+ *   removes/adds the entries from the parent widget as necessary
+ *
+ * parent: either the menu list widget or a menu entry widget
+ * menu: entry to be updated
+ */
+template <class P>
+void ConfigList::updateMenuList(P* parent, struct menu* menu)
+{
+	struct menu* child;
+	ConfigItem* item;
+	ConfigItem* last;
+	bool visible;
+	enum prop_type type;
+
+	if (!menu) {
+		while ((item = parent->firstChild()))
+			delete item;
+		return;
+	}
+
+	last = parent->firstChild();
+	if (last && !last->goParent)
+		last = 0;
+	for (child = menu->list; child; child = child->next) {
+		item = last ? last->nextSibling() : parent->firstChild();
+		type = child->prompt ? child->prompt->type : P_UNKNOWN;
+
+		switch (mode) {
+		case menuMode:
+			if (!(child->flags & MENU_ROOT))
+				goto hide;
+			break;
+		case symbolMode:
+			if (child->flags & MENU_ROOT)
+				goto hide;
+			break;
+		default:
+			break;
+		}
+
+		visible = menu_is_visible(child);
+		if (showAll || visible) {
+			if (!child->sym && !child->list && !child->prompt)
+				continue;
+			if (!item || item->menu != child)
+				item = new ConfigItem(parent, last, child, visible);
+			else
+				item->testUpdateMenu(visible);
+
+			if (mode == fullMode || mode == menuMode || type != P_MENU)
+				updateMenuList(item, child);
+			else
+				updateMenuList(item, 0);
+			last = item;
+			continue;
+		}
+	hide:
+		if (item && item->menu == child) {
+			last = parent->firstChild();
+			if (last == item)
+				last = 0;
+			else while (last->nextSibling() != item)
+				last = last->nextSibling();
+			delete item;
+		}
+	}
+}
+
+void ConfigList::keyPressEvent(QKeyEvent* ev)
+{
+	QListViewItem* i = currentItem();
+	ConfigItem* item;
+	struct menu *menu;
+	enum prop_type type;
+
+	if (ev->key() == Key_Escape && mode != fullMode && mode != listMode) {
+		emit parentSelected();
+		ev->accept();
+		return;
+	}
+
+	if (!i) {
+		Parent::keyPressEvent(ev);
+		return;
+	}
+	item = (ConfigItem*)i;
+
+	switch (ev->key()) {
+	case Key_Return:
+	case Key_Enter:
+		if (item->goParent) {
+			emit parentSelected();
+			break;
+		}
+		menu = item->menu;
+		if (!menu)
+			break;
+		type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+		if (type == P_MENU && rootEntry != menu &&
+		    mode != fullMode && mode != menuMode) {
+			emit menuSelected(menu);
+			break;
+		}
+	case Key_Space:
+		changeValue(item);
+		break;
+	case Key_N:
+		setValue(item, no);
+		break;
+	case Key_M:
+		setValue(item, mod);
+		break;
+	case Key_Y:
+		setValue(item, yes);
+		break;
+	default:
+		Parent::keyPressEvent(ev);
+		return;
+	}
+	ev->accept();
+}
+
+void ConfigList::contentsMousePressEvent(QMouseEvent* e)
+{
+	//QPoint p(contentsToViewport(e->pos()));
+	//printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
+	Parent::contentsMousePressEvent(e);
+}
+
+void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
+{
+	QPoint p(contentsToViewport(e->pos()));
+	ConfigItem* item = (ConfigItem*)itemAt(p);
+	struct menu *menu;
+	enum prop_type ptype;
+	const QPixmap* pm;
+	int idx, x;
+
+	if (!item)
+		goto skip;
+
+	menu = item->menu;
+	x = header()->offset() + p.x();
+	idx = colRevMap[header()->sectionAt(x)];
+	switch (idx) {
+	case promptColIdx:
+		pm = item->pixmap(promptColIdx);
+		if (pm) {
+			int off = header()->sectionPos(0) + itemMargin() +
+				treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
+			if (x >= off && x < off + pm->width()) {
+				if (item->goParent) {
+					emit parentSelected();
+					break;
+				} else if (!menu)
+					break;
+				ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+				if (ptype == P_MENU && rootEntry != menu &&
+				    mode != fullMode && mode != menuMode)
+					emit menuSelected(menu);
+				else
+					changeValue(item);
+			}
+		}
+		break;
+	case noColIdx:
+		setValue(item, no);
+		break;
+	case modColIdx:
+		setValue(item, mod);
+		break;
+	case yesColIdx:
+		setValue(item, yes);
+		break;
+	case dataColIdx:
+		changeValue(item);
+		break;
+	}
+
+skip:
+	//printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
+	Parent::contentsMouseReleaseEvent(e);
+}
+
+void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
+{
+	//QPoint p(contentsToViewport(e->pos()));
+	//printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
+	Parent::contentsMouseMoveEvent(e);
+}
+
+void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
+{
+	QPoint p(contentsToViewport(e->pos()));
+	ConfigItem* item = (ConfigItem*)itemAt(p);
+	struct menu *menu;
+	enum prop_type ptype;
+
+	if (!item)
+		goto skip;
+	if (item->goParent) {
+		emit parentSelected();
+		goto skip;
+	}
+	menu = item->menu;
+	if (!menu)
+		goto skip;
+	ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+	if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
+		emit menuSelected(menu);
+	else if (menu->sym)
+		changeValue(item);
+
+skip:
+	//printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
+	Parent::contentsMouseDoubleClickEvent(e);
+}
+
+void ConfigList::focusInEvent(QFocusEvent *e)
+{
+	struct menu *menu = NULL;
+
+	Parent::focusInEvent(e);
+
+	ConfigItem* item = (ConfigItem *)currentItem();
+	if (item) {
+		setSelected(item, TRUE);
+		menu = item->menu;
+	}
+	emit gotFocus(menu);
+}
+
+void ConfigList::contextMenuEvent(QContextMenuEvent *e)
+{
+	if (e->y() <= header()->geometry().bottom()) {
+		if (!headerPopup) {
+			QAction *action;
+
+			headerPopup = new QPopupMenu(this);
+			action = new QAction(NULL, "Show Name", 0, this);
+			  action->setToggleAction(TRUE);
+			  connect(action, SIGNAL(toggled(bool)),
+				  parent(), SLOT(setShowName(bool)));
+			  connect(parent(), SIGNAL(showNameChanged(bool)),
+				  action, SLOT(setOn(bool)));
+			  action->setOn(showName);
+			  action->addTo(headerPopup);
+			action = new QAction(NULL, "Show Range", 0, this);
+			  action->setToggleAction(TRUE);
+			  connect(action, SIGNAL(toggled(bool)),
+				  parent(), SLOT(setShowRange(bool)));
+			  connect(parent(), SIGNAL(showRangeChanged(bool)),
+				  action, SLOT(setOn(bool)));
+			  action->setOn(showRange);
+			  action->addTo(headerPopup);
+			action = new QAction(NULL, "Show Data", 0, this);
+			  action->setToggleAction(TRUE);
+			  connect(action, SIGNAL(toggled(bool)),
+				  parent(), SLOT(setShowData(bool)));
+			  connect(parent(), SIGNAL(showDataChanged(bool)),
+				  action, SLOT(setOn(bool)));
+			  action->setOn(showData);
+			  action->addTo(headerPopup);
+		}
+		headerPopup->exec(e->globalPos());
+		e->accept();
+	} else
+		e->ignore();
+}
+
+ConfigView* ConfigView::viewList;
+
+ConfigView::ConfigView(QWidget* parent, const char *name)
+	: Parent(parent, name)
+{
+	list = new ConfigList(this, name);
+	lineEdit = new ConfigLineEdit(this);
+	lineEdit->hide();
+
+	this->nextView = viewList;
+	viewList = this;
+}
+
+ConfigView::~ConfigView(void)
+{
+	ConfigView** vp;
+
+	for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
+		if (*vp == this) {
+			*vp = nextView;
+			break;
+		}
+	}
+}
+
+void ConfigView::setShowAll(bool b)
+{
+	if (list->showAll != b) {
+		list->showAll = b;
+		list->updateListAll();
+		emit showAllChanged(b);
+	}
+}
+
+void ConfigView::setShowName(bool b)
+{
+	if (list->showName != b) {
+		list->showName = b;
+		list->reinit();
+		emit showNameChanged(b);
+	}
+}
+
+void ConfigView::setShowRange(bool b)
+{
+	if (list->showRange != b) {
+		list->showRange = b;
+		list->reinit();
+		emit showRangeChanged(b);
+	}
+}
+
+void ConfigView::setShowData(bool b)
+{
+	if (list->showData != b) {
+		list->showData = b;
+		list->reinit();
+		emit showDataChanged(b);
+	}
+}
+
+void ConfigList::setAllOpen(bool open)
+{
+	QListViewItemIterator it(this);
+
+	for (; it.current(); it++)
+		it.current()->setOpen(open);
+}
+
+void ConfigView::updateList(ConfigItem* item)
+{
+	ConfigView* v;
+
+	for (v = viewList; v; v = v->nextView)
+		v->list->updateList(item);
+}
+
+void ConfigView::updateListAll(void)
+{
+	ConfigView* v;
+
+	for (v = viewList; v; v = v->nextView)
+		v->list->updateListAll();
+}
+
+ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
+	: Parent(parent, name), menu(0), sym(0)
+{
+	if (name) {
+		configSettings->beginGroup(name);
+		_showDebug = configSettings->readBoolEntry("/showDebug", false);
+		configSettings->endGroup();
+		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+	}
+}
+
+void ConfigInfoView::saveSettings(void)
+{
+	if (name()) {
+		configSettings->beginGroup(name());
+		configSettings->writeEntry("/showDebug", showDebug());
+		configSettings->endGroup();
+	}
+}
+
+void ConfigInfoView::setShowDebug(bool b)
+{
+	if (_showDebug != b) {
+		_showDebug = b;
+		if (menu)
+			menuInfo();
+		else if (sym)
+			symbolInfo();
+		emit showDebugChanged(b);
+	}
+}
+
+void ConfigInfoView::setInfo(struct menu *m)
+{
+	if (menu == m)
+		return;
+	menu = m;
+	sym = NULL;
+	if (!menu)
+		clear();
+	else
+		menuInfo();
+}
+
+void ConfigInfoView::setSource(const QString& name)
+{
+	const char *p = name.latin1();
+
+	menu = NULL;
+	sym = NULL;
+
+	switch (p[0]) {
+	case 'm':
+		struct menu *m;
+
+		if (sscanf(p, "m%p", &m) == 1 && menu != m) {
+			menu = m;
+			menuInfo();
+			emit menuSelected(menu);
+		}
+		break;
+	case 's':
+		struct symbol *s;
+
+		if (sscanf(p, "s%p", &s) == 1 && sym != s) {
+			sym = s;
+			symbolInfo();
+		}
+		break;
+	}
+}
+
+void ConfigInfoView::symbolInfo(void)
+{
+	QString str;
+
+	str += "<big>Symbol: <b>";
+	str += print_filter(sym->name);
+	str += "</b></big><br><br>value: ";
+	str += print_filter(sym_get_string_value(sym));
+	str += "<br>visibility: ";
+	str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
+	str += "<br>";
+	str += debug_info(sym);
+
+	setText(str);
+}
+
+void ConfigInfoView::menuInfo(void)
+{
+	struct symbol* sym;
+	QString head, debug, help;
+
+	sym = menu->sym;
+	if (sym) {
+		if (menu->prompt) {
+			head += "<big><b>";
+			head += print_filter(_(menu->prompt->text));
+			head += "</b></big>";
+			if (sym->name) {
+				head += " (";
+				if (showDebug())
+					head += QString().sprintf("<a href=\"s%p\">", sym);
+				head += print_filter(sym->name);
+				if (showDebug())
+					head += "</a>";
+				head += ")";
+			}
+		} else if (sym->name) {
+			head += "<big><b>";
+			if (showDebug())
+				head += QString().sprintf("<a href=\"s%p\">", sym);
+			head += print_filter(sym->name);
+			if (showDebug())
+				head += "</a>";
+			head += "</b></big>";
+		}
+		head += "<br><br>";
+
+		if (showDebug())
+			debug = debug_info(sym);
+
+		help = print_filter(_(sym->help));
+	} else if (menu->prompt) {
+		head += "<big><b>";
+		head += print_filter(_(menu->prompt->text));
+		head += "</b></big><br><br>";
+		if (showDebug()) {
+			if (menu->prompt->visible.expr) {
+				debug += "&nbsp;&nbsp;dep: ";
+				expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
+				debug += "<br><br>";
+			}
+		}
+	}
+	if (showDebug())
+		debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
+
+	setText(head + debug + help);
+}
+
+QString ConfigInfoView::debug_info(struct symbol *sym)
+{
+	QString debug;
+
+	debug += "type: ";
+	debug += print_filter(sym_type_name(sym->type));
+	if (sym_is_choice(sym))
+		debug += " (choice)";
+	debug += "<br>";
+	if (sym->rev_dep.expr) {
+		debug += "reverse dep: ";
+		expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
+		debug += "<br>";
+	}
+	for (struct property *prop = sym->prop; prop; prop = prop->next) {
+		switch (prop->type) {
+		case P_PROMPT:
+		case P_MENU:
+			debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
+			debug += print_filter(_(prop->text));
+			debug += "</a><br>";
+			break;
+		case P_DEFAULT:
+			debug += "default: ";
+			expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+			debug += "<br>";
+			break;
+		case P_CHOICE:
+			if (sym_is_choice(sym)) {
+				debug += "choice: ";
+				expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+				debug += "<br>";
+			}
+			break;
+		case P_SELECT:
+			debug += "select: ";
+			expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+			debug += "<br>";
+			break;
+		case P_RANGE:
+			debug += "range: ";
+			expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+			debug += "<br>";
+			break;
+		default:
+			debug += "unknown property: ";
+			debug += prop_get_type_name(prop->type);
+			debug += "<br>";
+		}
+		if (prop->visible.expr) {
+			debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
+			expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
+			debug += "<br>";
+		}
+	}
+	debug += "<br>";
+
+	return debug;
+}
+
+QString ConfigInfoView::print_filter(const QString &str)
+{
+	QRegExp re("[<>&\"\\n]");
+	QString res = str;
+	for (int i = 0; (i = res.find(re, i)) >= 0;) {
+		switch (res[i].latin1()) {
+		case '<':
+			res.replace(i, 1, "&lt;");
+			i += 4;
+			break;
+		case '>':
+			res.replace(i, 1, "&gt;");
+			i += 4;
+			break;
+		case '&':
+			res.replace(i, 1, "&amp;");
+			i += 5;
+			break;
+		case '"':
+			res.replace(i, 1, "&quot;");
+			i += 6;
+			break;
+		case '\n':
+			res.replace(i, 1, "<br>");
+			i += 4;
+			break;
+		}
+	}
+	return res;
+}
+
+void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
+{
+	QString* text = reinterpret_cast<QString*>(data);
+	QString str2 = print_filter(str);
+
+	if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
+		*text += QString().sprintf("<a href=\"s%p\">", sym);
+		*text += str2;
+		*text += "</a>";
+	} else
+		*text += str2;
+}
+
+QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
+{
+	QPopupMenu* popup = Parent::createPopupMenu(pos);
+	QAction* action = new QAction(NULL,"Show Debug Info", 0, popup);
+	  action->setToggleAction(TRUE);
+	  connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
+	  connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
+	  action->setOn(showDebug());
+	popup->insertSeparator();
+	action->addTo(popup);
+	return popup;
+}
+
+void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
+{
+	Parent::contentsContextMenuEvent(e);
+}
+
+ConfigSearchWindow::ConfigSearchWindow(QWidget* parent, const char *name)
+	: Parent(parent, name), result(NULL)
+{
+	setCaption("Search Config");
+
+	QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
+	QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
+	layout2->addWidget(new QLabel("Find:", this));
+	editField = new QLineEdit(this);
+	connect(editField, SIGNAL(returnPressed()), SLOT(search()));
+	layout2->addWidget(editField);
+	searchButton = new QPushButton("Search", this);
+	searchButton->setAutoDefault(FALSE);
+	connect(searchButton, SIGNAL(clicked()), SLOT(search()));
+	layout2->addWidget(searchButton);
+	layout1->addLayout(layout2);
+
+	split = new QSplitter(this);
+	split->setOrientation(QSplitter::Vertical);
+	list = new ConfigView(split, name);
+	list->list->mode = listMode;
+	info = new ConfigInfoView(split, name);
+	connect(list->list, SIGNAL(menuChanged(struct menu *)),
+		info, SLOT(setInfo(struct menu *)));
+	layout1->addWidget(split);
+
+	if (name) {
+		int x, y, width, height;
+		bool ok;
+
+		configSettings->beginGroup(name);
+		width = configSettings->readNumEntry("/window width", parent->width() / 2);
+		height = configSettings->readNumEntry("/window height", parent->height() / 2);
+		resize(width, height);
+		x = configSettings->readNumEntry("/window x", 0, &ok);
+		if (ok)
+			y = configSettings->readNumEntry("/window y", 0, &ok);
+		if (ok)
+			move(x, y);
+		QValueList<int> sizes = configSettings->readSizes("/split", &ok);
+		if (ok)
+			split->setSizes(sizes);
+		configSettings->endGroup();
+		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+	}
+}
+
+void ConfigSearchWindow::saveSettings(void)
+{
+	if (name()) {
+		configSettings->beginGroup(name());
+		configSettings->writeEntry("/window x", pos().x());
+		configSettings->writeEntry("/window y", pos().y());
+		configSettings->writeEntry("/window width", size().width());
+		configSettings->writeEntry("/window height", size().height());
+		configSettings->writeSizes("/split", split->sizes());
+		configSettings->endGroup();
+	}
+}
+
+void ConfigSearchWindow::search(void)
+{
+	struct symbol **p;
+	struct property *prop;
+	ConfigItem *lastItem = NULL;
+
+	free(result);
+	list->list->clear();
+	info->clear();
+
+	result = sym_re_search(editField->text().latin1());
+	if (!result)
+		return;
+	for (p = result; *p; p++) {
+		for_all_prompts((*p), prop)
+			lastItem = new ConfigItem(list->list, lastItem, prop->menu,
+						  menu_is_visible(prop->menu));
+	}
+}
+
+/*
+ * Construct the complete config widget
+ */
+ConfigMainWindow::ConfigMainWindow(void)
+	: searchWindow(0)
+{
+	QMenuBar* menu;
+	bool ok;
+	int x, y, width, height;
+
+	QWidget *d = configApp->desktop();
+
+	width = configSettings->readNumEntry("/window width", d->width() - 64);
+	height = configSettings->readNumEntry("/window height", d->height() - 64);
+	resize(width, height);
+	x = configSettings->readNumEntry("/window x", 0, &ok);
+	if (ok)
+		y = configSettings->readNumEntry("/window y", 0, &ok);
+	if (ok)
+		move(x, y);
+
+	split1 = new QSplitter(this);
+	split1->setOrientation(QSplitter::Horizontal);
+	setCentralWidget(split1);
+
+	menuView = new ConfigView(split1, "menu");
+	menuList = menuView->list;
+
+	split2 = new QSplitter(split1);
+	split2->setOrientation(QSplitter::Vertical);
+
+	// create config tree
+	configView = new ConfigView(split2, "config");
+	configList = configView->list;
+
+	helpText = new ConfigInfoView(split2, "help");
+	helpText->setTextFormat(Qt::RichText);
+
+	setTabOrder(configList, helpText);
+	configList->setFocus();
+
+	menu = menuBar();
+	toolBar = new QToolBar("Tools", this);
+
+	backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
+	  connect(backAction, SIGNAL(activated()), SLOT(goBack()));
+	  backAction->setEnabled(FALSE);
+	QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
+	  connect(quitAction, SIGNAL(activated()), SLOT(close()));
+	QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
+	  connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
+	saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
+	  connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
+	conf_set_changed_callback(conf_changed);
+	// Set saveAction's initial state
+	conf_changed();
+	QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
+	  connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
+	QAction *searchAction = new QAction("Find", "&Find", CTRL+Key_F, this);
+	  connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
+	QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
+	  connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
+	QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
+	  connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
+	QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
+	  connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
+
+	QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
+	  showNameAction->setToggleAction(TRUE);
+	  connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
+	  connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
+	  showNameAction->setOn(configView->showName());
+	QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
+	  showRangeAction->setToggleAction(TRUE);
+	  connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
+	  connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
+	  showRangeAction->setOn(configList->showRange);
+	QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
+	  showDataAction->setToggleAction(TRUE);
+	  connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
+	  connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
+	  showDataAction->setOn(configList->showData);
+	QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
+	  showAllAction->setToggleAction(TRUE);
+	  connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool)));
+	  connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool)));
+	  showAllAction->setOn(configList->showAll);
+	QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
+	  showDebugAction->setToggleAction(TRUE);
+	  connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
+	  connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
+	  showDebugAction->setOn(helpText->showDebug());
+
+	QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this);
+	  connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
+	QAction *showAboutAction = new QAction(NULL, "About", 0, this);
+	  connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
+
+	// init tool bar
+	backAction->addTo(toolBar);
+	toolBar->addSeparator();
+	loadAction->addTo(toolBar);
+	saveAction->addTo(toolBar);
+	toolBar->addSeparator();
+	singleViewAction->addTo(toolBar);
+	splitViewAction->addTo(toolBar);
+	fullViewAction->addTo(toolBar);
+
+	// create config menu
+	QPopupMenu* config = new QPopupMenu(this);
+	menu->insertItem("&File", config);
+	loadAction->addTo(config);
+	saveAction->addTo(config);
+	saveAsAction->addTo(config);
+	config->insertSeparator();
+	quitAction->addTo(config);
+
+	// create edit menu
+	QPopupMenu* editMenu = new QPopupMenu(this);
+	menu->insertItem("&Edit", editMenu);
+	searchAction->addTo(editMenu);
+
+	// create options menu
+	QPopupMenu* optionMenu = new QPopupMenu(this);
+	menu->insertItem("&Option", optionMenu);
+	showNameAction->addTo(optionMenu);
+	showRangeAction->addTo(optionMenu);
+	showDataAction->addTo(optionMenu);
+	optionMenu->insertSeparator();
+	showAllAction->addTo(optionMenu);
+	showDebugAction->addTo(optionMenu);
+
+	// create help menu
+	QPopupMenu* helpMenu = new QPopupMenu(this);
+	menu->insertSeparator();
+	menu->insertItem("&Help", helpMenu);
+	showIntroAction->addTo(helpMenu);
+	showAboutAction->addTo(helpMenu);
+
+	connect(configList, SIGNAL(menuChanged(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(configList, SIGNAL(menuSelected(struct menu *)),
+		SLOT(changeMenu(struct menu *)));
+	connect(configList, SIGNAL(parentSelected()),
+		SLOT(goBack()));
+	connect(menuList, SIGNAL(menuChanged(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(menuList, SIGNAL(menuSelected(struct menu *)),
+		SLOT(changeMenu(struct menu *)));
+
+	connect(configList, SIGNAL(gotFocus(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(menuList, SIGNAL(gotFocus(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(menuList, SIGNAL(gotFocus(struct menu *)),
+		SLOT(listFocusChanged(void)));
+	connect(helpText, SIGNAL(menuSelected(struct menu *)),
+		SLOT(setMenuLink(struct menu *)));
+
+	QString listMode = configSettings->readEntry("/listMode", "symbol");
+	if (listMode == "single")
+		showSingleView();
+	else if (listMode == "full")
+		showFullView();
+	else /*if (listMode == "split")*/
+		showSplitView();
+
+	// UI setup done, restore splitter positions
+	QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
+	if (ok)
+		split1->setSizes(sizes);
+
+	sizes = configSettings->readSizes("/split2", &ok);
+	if (ok)
+		split2->setSizes(sizes);
+}
+
+void ConfigMainWindow::loadConfig(void)
+{
+	QString s = QFileDialog::getOpenFileName(".config", NULL, this);
+	if (s.isNull())
+		return;
+	if (conf_read(QFile::encodeName(s)))
+		QMessageBox::information(this, "qconf", "Unable to load configuration!");
+	ConfigView::updateListAll();
+}
+
+void ConfigMainWindow::saveConfig(void)
+{
+	if (conf_write(NULL))
+		QMessageBox::information(this, "qconf", "Unable to save configuration!");
+}
+
+void ConfigMainWindow::saveConfigAs(void)
+{
+	QString s = QFileDialog::getSaveFileName(".config", NULL, this);
+	if (s.isNull())
+		return;
+	if (conf_write(QFile::encodeName(s)))
+		QMessageBox::information(this, "qconf", "Unable to save configuration!");
+}
+
+void ConfigMainWindow::searchConfig(void)
+{
+	if (!searchWindow)
+		searchWindow = new ConfigSearchWindow(this, "search");
+	searchWindow->show();
+}
+
+void ConfigMainWindow::changeMenu(struct menu *menu)
+{
+	configList->setRootMenu(menu);
+	if (configList->rootEntry->parent == &rootmenu)
+		backAction->setEnabled(FALSE);
+	else
+		backAction->setEnabled(TRUE);
+}
+
+void ConfigMainWindow::setMenuLink(struct menu *menu)
+{
+	struct menu *parent;
+	ConfigList* list = NULL;
+	ConfigItem* item;
+
+	if (!menu_is_visible(menu) && !configView->showAll())
+		return;
+
+	switch (configList->mode) {
+	case singleMode:
+		list = configList;
+		parent = menu_get_parent_menu(menu);
+		if (!parent)
+			return;
+		list->setRootMenu(parent);
+		break;
+	case symbolMode:
+		if (menu->flags & MENU_ROOT) {
+			configList->setRootMenu(menu);
+			configList->clearSelection();
+			list = menuList;
+		} else {
+			list = configList;
+			parent = menu_get_parent_menu(menu->parent);
+			if (!parent)
+				return;
+			item = menuList->findConfigItem(parent);
+			if (item) {
+				menuList->setSelected(item, TRUE);
+				menuList->ensureItemVisible(item);
+			}
+			list->setRootMenu(parent);
+		}
+		break;
+	case fullMode:
+		list = configList;
+		break;
+	}
+
+	if (list) {
+		item = list->findConfigItem(menu);
+		if (item) {
+			list->setSelected(item, TRUE);
+			list->ensureItemVisible(item);
+			list->setFocus();
+		}
+	}
+}
+
+void ConfigMainWindow::listFocusChanged(void)
+{
+	if (menuList->mode == menuMode)
+		configList->clearSelection();
+}
+
+void ConfigMainWindow::goBack(void)
+{
+	ConfigItem* item;
+
+	configList->setParentMenu();
+	if (configList->rootEntry == &rootmenu)
+		backAction->setEnabled(FALSE);
+	item = (ConfigItem*)menuList->selectedItem();
+	while (item) {
+		if (item->menu == configList->rootEntry) {
+			menuList->setSelected(item, TRUE);
+			break;
+		}
+		item = (ConfigItem*)item->parent();
+	}
+}
+
+void ConfigMainWindow::showSingleView(void)
+{
+	menuView->hide();
+	menuList->setRootMenu(0);
+	configList->mode = singleMode;
+	if (configList->rootEntry == &rootmenu)
+		configList->updateListAll();
+	else
+		configList->setRootMenu(&rootmenu);
+	configList->setAllOpen(TRUE);
+	configList->setFocus();
+}
+
+void ConfigMainWindow::showSplitView(void)
+{
+	configList->mode = symbolMode;
+	if (configList->rootEntry == &rootmenu)
+		configList->updateListAll();
+	else
+		configList->setRootMenu(&rootmenu);
+	configList->setAllOpen(TRUE);
+	configApp->processEvents();
+	menuList->mode = menuMode;
+	menuList->setRootMenu(&rootmenu);
+	menuList->setAllOpen(TRUE);
+	menuView->show();
+	menuList->setFocus();
+}
+
+void ConfigMainWindow::showFullView(void)
+{
+	menuView->hide();
+	menuList->setRootMenu(0);
+	configList->mode = fullMode;
+	if (configList->rootEntry == &rootmenu)
+		configList->updateListAll();
+	else
+		configList->setRootMenu(&rootmenu);
+	configList->setAllOpen(FALSE);
+	configList->setFocus();
+}
+
+/*
+ * ask for saving configuration before quitting
+ * TODO ask only when something changed
+ */
+void ConfigMainWindow::closeEvent(QCloseEvent* e)
+{
+	if (!conf_get_changed()) {
+		e->accept();
+		return;
+	}
+	QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
+			QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
+	mb.setButtonText(QMessageBox::Yes, "&Save Changes");
+	mb.setButtonText(QMessageBox::No, "&Discard Changes");
+	mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
+	switch (mb.exec()) {
+	case QMessageBox::Yes:
+		conf_write(NULL);
+	case QMessageBox::No:
+		e->accept();
+		break;
+	case QMessageBox::Cancel:
+		e->ignore();
+		break;
+	}
+}
+
+void ConfigMainWindow::showIntro(void)
+{
+	static char str[] = "Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
+		"For each option, a blank box indicates the feature is disabled, a check\n"
+		"indicates it is enabled, and a dot indicates that it is to be compiled\n"
+		"as a module.  Clicking on the box will cycle through the three states.\n\n"
+		"If you do not see an option (e.g., a device driver) that you believe\n"
+		"should be present, try turning on Show All Options under the Options menu.\n"
+		"Although there is no cross reference yet to help you figure out what other\n"
+		"options must be enabled to support the option you are interested in, you can\n"
+		"still view the help of a grayed-out option.\n\n"
+		"Toggling Show Debug Info under the Options menu will show the dependencies,\n"
+		"which you can then match by examining other options.\n\n";
+
+	QMessageBox::information(this, "qconf", str);
+}
+
+void ConfigMainWindow::showAbout(void)
+{
+	static char str[] = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
+		"Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
+
+	QMessageBox::information(this, "qconf", str);
+}
+
+void ConfigMainWindow::saveSettings(void)
+{
+	configSettings->writeEntry("/window x", pos().x());
+	configSettings->writeEntry("/window y", pos().y());
+	configSettings->writeEntry("/window width", size().width());
+	configSettings->writeEntry("/window height", size().height());
+
+	QString entry;
+	switch(configList->mode) {
+	case singleMode :
+		entry = "single";
+		break;
+
+	case symbolMode :
+		entry = "split";
+		break;
+
+	case fullMode :
+		entry = "full";
+		break;
+	}
+	configSettings->writeEntry("/listMode", entry);
+
+	configSettings->writeSizes("/split1", split1->sizes());
+	configSettings->writeSizes("/split2", split2->sizes());
+}
+
+void ConfigMainWindow::conf_changed(void)
+{
+	if (saveAction)
+		saveAction->setEnabled(conf_get_changed());
+}
+
+void fixup_rootmenu(struct menu *menu)
+{
+	struct menu *child;
+	static int menu_cnt = 0;
+
+	menu->flags |= MENU_ROOT;
+	for (child = menu->list; child; child = child->next) {
+		if (child->prompt && child->prompt->type == P_MENU) {
+			menu_cnt++;
+			fixup_rootmenu(child);
+			menu_cnt--;
+		} else if (!menu_cnt)
+			fixup_rootmenu(child);
+	}
+}
+
+static const char *progname;
+
+static void usage(void)
+{
+	printf("%s <config>\n", progname);
+	exit(0);
+}
+
+int main(int ac, char** av)
+{
+	ConfigMainWindow* v;
+	const char *name;
+
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
+
+#ifndef LKC_DIRECT_LINK
+	kconfig_load();
+#endif
+
+	progname = av[0];
+	configApp = new QApplication(ac, av);
+	if (ac > 1 && av[1][0] == '-') {
+		switch (av[1][1]) {
+		case 'h':
+		case '?':
+			usage();
+		}
+		name = av[2];
+	} else
+		name = av[1];
+	if (!name)
+		usage();
+
+	conf_parse(name);
+	fixup_rootmenu(&rootmenu);
+	conf_read(NULL);
+	//zconfdump(stdout);
+
+	configSettings = new ConfigSettings();
+	configSettings->beginGroup("/kconfig/qconf");
+	v = new ConfigMainWindow();
+
+	//zconfdump(stdout);
+	configApp->setMainWidget(v);
+	configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
+	configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
+	v->show();
+	configApp->exec();
+
+	configSettings->endGroup();
+	delete configSettings;
+
+	return 0;
+}

+ 334 - 0
package/config/qconf.h

@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <qlistview.h>
+#if QT_VERSION >= 300
+#include <qsettings.h>
+#else
+class QSettings {
+public:
+	void beginGroup(const QString& group) { }
+	void endGroup(void) { }
+	bool readBoolEntry(const QString& key, bool def = FALSE, bool* ok = 0) const
+	{ if (ok) *ok = FALSE; return def; }
+	int readNumEntry(const QString& key, int def = 0, bool* ok = 0) const
+	{ if (ok) *ok = FALSE; return def; }
+	QString readEntry(const QString& key, const QString& def = QString::null, bool* ok = 0) const
+	{ if (ok) *ok = FALSE; return def; }
+	QStringList readListEntry(const QString& key, bool* ok = 0) const
+	{ if (ok) *ok = FALSE; return QStringList(); }
+	template <class t>
+	bool writeEntry(const QString& key, t value)
+	{ return TRUE; }
+};
+#endif
+
+class ConfigView;
+class ConfigList;
+class ConfigItem;
+class ConfigLineEdit;
+class ConfigMainWindow;
+
+
+class ConfigSettings : public QSettings {
+public:
+	QValueList<int> readSizes(const QString& key, bool *ok);
+	bool writeSizes(const QString& key, const QValueList<int>& value);
+};
+
+enum colIdx {
+	promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
+};
+enum listMode {
+	singleMode, menuMode, symbolMode, fullMode, listMode
+};
+
+class ConfigList : public QListView {
+	Q_OBJECT
+	typedef class QListView Parent;
+public:
+	ConfigList(ConfigView* p, const char *name = 0);
+	void reinit(void);
+	ConfigView* parent(void) const
+	{
+		return (ConfigView*)Parent::parent();
+	}
+	ConfigItem* findConfigItem(struct menu *);
+
+protected:
+	void keyPressEvent(QKeyEvent *e);
+	void contentsMousePressEvent(QMouseEvent *e);
+	void contentsMouseReleaseEvent(QMouseEvent *e);
+	void contentsMouseMoveEvent(QMouseEvent *e);
+	void contentsMouseDoubleClickEvent(QMouseEvent *e);
+	void focusInEvent(QFocusEvent *e);
+	void contextMenuEvent(QContextMenuEvent *e);
+
+public slots:
+	void setRootMenu(struct menu *menu);
+
+	void updateList(ConfigItem *item);
+	void setValue(ConfigItem* item, tristate val);
+	void changeValue(ConfigItem* item);
+	void updateSelection(void);
+	void saveSettings(void);
+signals:
+	void menuChanged(struct menu *menu);
+	void menuSelected(struct menu *menu);
+	void parentSelected(void);
+	void gotFocus(struct menu *);
+
+public:
+	void updateListAll(void)
+	{
+		updateAll = true;
+		updateList(NULL);
+		updateAll = false;
+	}
+	ConfigList* listView()
+	{
+		return this;
+	}
+	ConfigItem* firstChild() const
+	{
+		return (ConfigItem *)Parent::firstChild();
+	}
+	int mapIdx(colIdx idx)
+	{
+		return colMap[idx];
+	}
+	void addColumn(colIdx idx, const QString& label)
+	{
+		colMap[idx] = Parent::addColumn(label);
+		colRevMap[colMap[idx]] = idx;
+	}
+	void removeColumn(colIdx idx)
+	{
+		int col = colMap[idx];
+		if (col >= 0) {
+			Parent::removeColumn(col);
+			colRevMap[col] = colMap[idx] = -1;
+		}
+	}
+	void setAllOpen(bool open);
+	void setParentMenu(void);
+
+	template <class P>
+	void updateMenuList(P*, struct menu*);
+
+	bool updateAll;
+
+	QPixmap symbolYesPix, symbolModPix, symbolNoPix;
+	QPixmap choiceYesPix, choiceNoPix;
+	QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
+
+	bool showAll, showName, showRange, showData;
+	enum listMode mode;
+	struct menu *rootEntry;
+	QColorGroup disabledColorGroup;
+	QColorGroup inactivedColorGroup;
+	QPopupMenu* headerPopup;
+
+private:
+	int colMap[colNr];
+	int colRevMap[colNr];
+};
+
+class ConfigItem : public QListViewItem {
+	typedef class QListViewItem Parent;
+public:
+	ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v)
+	: Parent(parent, after), menu(m), visible(v), goParent(false)
+	{
+		init();
+	}
+	ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
+	: Parent(parent, after), menu(m), visible(v), goParent(false)
+	{
+		init();
+	}
+	ConfigItem(QListView *parent, ConfigItem *after, bool v)
+	: Parent(parent, after), menu(0), visible(v), goParent(true)
+	{
+		init();
+	}
+	~ConfigItem(void);
+	void init(void);
+#if QT_VERSION >= 300
+	void okRename(int col);
+#endif
+	void updateMenu(void);
+	void testUpdateMenu(bool v);
+	ConfigList* listView() const
+	{
+		return (ConfigList*)Parent::listView();
+	}
+	ConfigItem* firstChild() const
+	{
+		return (ConfigItem *)Parent::firstChild();
+	}
+	ConfigItem* nextSibling() const
+	{
+		return (ConfigItem *)Parent::nextSibling();
+	}
+	void setText(colIdx idx, const QString& text)
+	{
+		Parent::setText(listView()->mapIdx(idx), text);
+	}
+	QString text(colIdx idx) const
+	{
+		return Parent::text(listView()->mapIdx(idx));
+	}
+	void setPixmap(colIdx idx, const QPixmap& pm)
+	{
+		Parent::setPixmap(listView()->mapIdx(idx), pm);
+	}
+	const QPixmap* pixmap(colIdx idx) const
+	{
+		return Parent::pixmap(listView()->mapIdx(idx));
+	}
+	void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
+
+	ConfigItem* nextItem;
+	struct menu *menu;
+	bool visible;
+	bool goParent;
+};
+
+class ConfigLineEdit : public QLineEdit {
+	Q_OBJECT
+	typedef class QLineEdit Parent;
+public:
+	ConfigLineEdit(ConfigView* parent);
+	ConfigView* parent(void) const
+	{
+		return (ConfigView*)Parent::parent();
+	}
+	void show(ConfigItem *i);
+	void keyPressEvent(QKeyEvent *e);
+
+public:
+	ConfigItem *item;
+};
+
+class ConfigView : public QVBox {
+	Q_OBJECT
+	typedef class QVBox Parent;
+public:
+	ConfigView(QWidget* parent, const char *name = 0);
+	~ConfigView(void);
+	static void updateList(ConfigItem* item);
+	static void updateListAll(void);
+
+	bool showAll(void) const { return list->showAll; }
+	bool showName(void) const { return list->showName; }
+	bool showRange(void) const { return list->showRange; }
+	bool showData(void) const { return list->showData; }
+public slots:
+	void setShowAll(bool);
+	void setShowName(bool);
+	void setShowRange(bool);
+	void setShowData(bool);
+signals:
+	void showAllChanged(bool);
+	void showNameChanged(bool);
+	void showRangeChanged(bool);
+	void showDataChanged(bool);
+public:
+	ConfigList* list;
+	ConfigLineEdit* lineEdit;
+
+	static ConfigView* viewList;
+	ConfigView* nextView;
+};
+
+class ConfigInfoView : public QTextBrowser {
+	Q_OBJECT
+	typedef class QTextBrowser Parent;
+public:
+	ConfigInfoView(QWidget* parent, const char *name = 0);
+	bool showDebug(void) const { return _showDebug; }
+
+public slots:
+	void setInfo(struct menu *menu);
+	void saveSettings(void);
+	void setSource(const QString& name);
+	void setShowDebug(bool);
+
+signals:
+	void showDebugChanged(bool);
+	void menuSelected(struct menu *);
+
+protected:
+	void symbolInfo(void);
+	void menuInfo(void);
+	QString debug_info(struct symbol *sym);
+	static QString print_filter(const QString &str);
+	static void expr_print_help(void *data, struct symbol *sym, const char *str);
+	QPopupMenu* createPopupMenu(const QPoint& pos);
+	void contentsContextMenuEvent(QContextMenuEvent *e);
+
+	struct symbol *sym;
+	struct menu *menu;
+	bool _showDebug;
+};
+
+class ConfigSearchWindow : public QDialog {
+	Q_OBJECT
+	typedef class QDialog Parent;
+public:
+	ConfigSearchWindow(QWidget* parent, const char *name = 0);
+
+public slots:
+	void saveSettings(void);
+	void search(void);
+
+protected:
+	QLineEdit* editField;
+	QPushButton* searchButton;
+	QSplitter* split;
+	ConfigView* list;
+	ConfigInfoView* info;
+
+	struct symbol **result;
+};
+
+class ConfigMainWindow : public QMainWindow {
+	Q_OBJECT
+
+	static QAction *saveAction;
+	static void conf_changed(void);
+public:
+	ConfigMainWindow(void);
+public slots:
+	void changeMenu(struct menu *);
+	void setMenuLink(struct menu *);
+	void listFocusChanged(void);
+	void goBack(void);
+	void loadConfig(void);
+	void saveConfig(void);
+	void saveConfigAs(void);
+	void searchConfig(void);
+	void showSingleView(void);
+	void showSplitView(void);
+	void showFullView(void);
+	void showIntro(void);
+	void showAbout(void);
+	void saveSettings(void);
+
+protected:
+	void closeEvent(QCloseEvent *e);
+
+	ConfigSearchWindow *searchWindow;
+	ConfigView *menuView;
+	ConfigList *menuList;
+	ConfigView *configView;
+	ConfigList *configList;
+	ConfigInfoView *helpText;
+	QToolBar *toolBar;
+	QAction *backAction;
+	QSplitter* split1;
+	QSplitter* split2;
+};

+ 109 - 37
package/config/symbol.c

@@ -15,22 +15,22 @@
 struct symbol symbol_yes = {
 struct symbol symbol_yes = {
 	.name = "y",
 	.name = "y",
 	.curr = { "y", yes },
 	.curr = { "y", yes },
-	.flags = SYMBOL_YES|SYMBOL_VALID,
+	.flags = SYMBOL_CONST|SYMBOL_VALID,
 }, symbol_mod = {
 }, symbol_mod = {
 	.name = "m",
 	.name = "m",
 	.curr = { "m", mod },
 	.curr = { "m", mod },
-	.flags = SYMBOL_MOD|SYMBOL_VALID,
+	.flags = SYMBOL_CONST|SYMBOL_VALID,
 }, symbol_no = {
 }, symbol_no = {
 	.name = "n",
 	.name = "n",
 	.curr = { "n", no },
 	.curr = { "n", no },
-	.flags = SYMBOL_NO|SYMBOL_VALID,
+	.flags = SYMBOL_CONST|SYMBOL_VALID,
 }, symbol_empty = {
 }, symbol_empty = {
 	.name = "",
 	.name = "",
 	.curr = { "", no },
 	.curr = { "", no },
 	.flags = SYMBOL_VALID,
 	.flags = SYMBOL_VALID,
 };
 };
 
 
-int sym_change_count;
+struct symbol *sym_defconfig_list;
 struct symbol *modules_sym;
 struct symbol *modules_sym;
 tristate modules_val;
 tristate modules_val;
 
 
@@ -44,6 +44,7 @@ void sym_add_default(struct symbol *sym, const char *def)
 void sym_init(void)
 void sym_init(void)
 {
 {
 	struct symbol *sym;
 	struct symbol *sym;
+	struct utsname uts;
 	char *p;
 	char *p;
 	static bool inited = false;
 	static bool inited = false;
 
 
@@ -51,20 +52,26 @@ void sym_init(void)
 		return;
 		return;
 	inited = true;
 	inited = true;
 
 
-	sym = sym_lookup("VERSION", 0);
+	uname(&uts);
+
+	sym = sym_lookup("ARCH", 0);
 	sym->type = S_STRING;
 	sym->type = S_STRING;
 	sym->flags |= SYMBOL_AUTO;
 	sym->flags |= SYMBOL_AUTO;
-	p = getenv("VERSION");
+	p = getenv("ARCH");
 	if (p)
 	if (p)
 		sym_add_default(sym, p);
 		sym_add_default(sym, p);
 
 
-	sym = sym_lookup("TARGET_ARCH", 0);
+	sym = sym_lookup("VERSION", 0);
 	sym->type = S_STRING;
 	sym->type = S_STRING;
 	sym->flags |= SYMBOL_AUTO;
 	sym->flags |= SYMBOL_AUTO;
-	p = getenv("TARGET_ARCH");
+	p = getenv("VERSION");
 	if (p)
 	if (p)
 		sym_add_default(sym, p);
 		sym_add_default(sym, p);
 
 
+	sym = sym_lookup("UNAME_RELEASE", 0);
+	sym->type = S_STRING;
+	sym->flags |= SYMBOL_AUTO;
+	sym_add_default(sym, uts.release);
 }
 }
 
 
 enum symbol_type sym_get_type(struct symbol *sym)
 enum symbol_type sym_get_type(struct symbol *sym)
@@ -134,6 +141,55 @@ struct property *sym_get_range_prop(struct symbol *sym)
 	return NULL;
 	return NULL;
 }
 }
 
 
+static int sym_get_range_val(struct symbol *sym, int base)
+{
+	sym_calc_value(sym);
+	switch (sym->type) {
+	case S_INT:
+		base = 10;
+		break;
+	case S_HEX:
+		base = 16;
+		break;
+	default:
+		break;
+	}
+	return strtol(sym->curr.val, NULL, base);
+}
+
+static void sym_validate_range(struct symbol *sym)
+{
+	struct property *prop;
+	int base, val, val2;
+	char str[64];
+
+	switch (sym->type) {
+	case S_INT:
+		base = 10;
+		break;
+	case S_HEX:
+		base = 16;
+		break;
+	default:
+		return;
+	}
+	prop = sym_get_range_prop(sym);
+	if (!prop)
+		return;
+	val = strtol(sym->curr.val, NULL, base);
+	val2 = sym_get_range_val(prop->expr->left.sym, base);
+	if (val >= val2) {
+		val2 = sym_get_range_val(prop->expr->right.sym, base);
+		if (val <= val2)
+			return;
+	}
+	if (sym->type == S_INT)
+		sprintf(str, "%d", val2);
+	else
+		sprintf(str, "0x%x", val2);
+	sym->curr.val = strdup(str);
+}
+
 static void sym_calc_visibility(struct symbol *sym)
 static void sym_calc_visibility(struct symbol *sym)
 {
 {
 	struct property *prop;
 	struct property *prop;
@@ -171,7 +227,7 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
 	struct expr *e;
 	struct expr *e;
 
 
 	/* is the user choice visible? */
 	/* is the user choice visible? */
-	def_sym = sym->user.val;
+	def_sym = sym->def[S_DEF_USER].val;
 	if (def_sym) {
 	if (def_sym) {
 		sym_calc_visibility(def_sym);
 		sym_calc_visibility(def_sym);
 		if (def_sym->visible != no)
 		if (def_sym->visible != no)
@@ -250,7 +306,7 @@ void sym_calc_value(struct symbol *sym)
 		} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
 		} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
 			sym->flags |= SYMBOL_WRITE;
 			sym->flags |= SYMBOL_WRITE;
 			if (sym_has_value(sym))
 			if (sym_has_value(sym))
-				newval.tri = sym->user.tri;
+				newval.tri = sym->def[S_DEF_USER].tri;
 			else if (!sym_is_choice(sym)) {
 			else if (!sym_is_choice(sym)) {
 				prop = sym_get_default_prop(sym);
 				prop = sym_get_default_prop(sym);
 				if (prop)
 				if (prop)
@@ -273,7 +329,7 @@ void sym_calc_value(struct symbol *sym)
 		if (sym->visible != no) {
 		if (sym->visible != no) {
 			sym->flags |= SYMBOL_WRITE;
 			sym->flags |= SYMBOL_WRITE;
 			if (sym_has_value(sym)) {
 			if (sym_has_value(sym)) {
-				newval.val = sym->user.val;
+				newval.val = sym->def[S_DEF_USER].val;
 				break;
 				break;
 			}
 			}
 		}
 		}
@@ -294,11 +350,15 @@ void sym_calc_value(struct symbol *sym)
 	sym->curr = newval;
 	sym->curr = newval;
 	if (sym_is_choice(sym) && newval.tri == yes)
 	if (sym_is_choice(sym) && newval.tri == yes)
 		sym->curr.val = sym_calc_choice(sym);
 		sym->curr.val = sym_calc_choice(sym);
+	sym_validate_range(sym);
 
 
-	if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
+	if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
 		sym_set_changed(sym);
 		sym_set_changed(sym);
-	if (modules_sym == sym)
-		modules_val = modules_sym->curr.tri;
+		if (modules_sym == sym) {
+			sym_set_all_changed();
+			modules_val = modules_sym->curr.tri;
+		}
+	}
 
 
 	if (sym_is_choice(sym)) {
 	if (sym_is_choice(sym)) {
 		int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
 		int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
@@ -318,7 +378,7 @@ void sym_clear_all_valid(void)
 
 
 	for_all_symbols(i, sym)
 	for_all_symbols(i, sym)
 		sym->flags &= ~SYMBOL_VALID;
 		sym->flags &= ~SYMBOL_VALID;
-	sym_change_count++;
+	sym_add_change_count(1);
 	if (modules_sym)
 	if (modules_sym)
 		sym_calc_value(modules_sym);
 		sym_calc_value(modules_sym);
 }
 }
@@ -369,23 +429,31 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val)
 	if (oldval != val && !sym_tristate_within_range(sym, val))
 	if (oldval != val && !sym_tristate_within_range(sym, val))
 		return false;
 		return false;
 
 
-	if (sym->flags & SYMBOL_NEW) {
-		sym->flags &= ~SYMBOL_NEW;
+	if (!(sym->flags & SYMBOL_DEF_USER)) {
+		sym->flags |= SYMBOL_DEF_USER;
 		sym_set_changed(sym);
 		sym_set_changed(sym);
 	}
 	}
+	/*
+	 * setting a choice value also resets the new flag of the choice
+	 * symbol and all other choice values.
+	 */
 	if (sym_is_choice_value(sym) && val == yes) {
 	if (sym_is_choice_value(sym) && val == yes) {
 		struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
 		struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
+		struct property *prop;
+		struct expr *e;
 
 
-		cs->user.val = sym;
-		cs->flags &= ~SYMBOL_NEW;
+		cs->def[S_DEF_USER].val = sym;
+		cs->flags |= SYMBOL_DEF_USER;
+		prop = sym_get_choice_prop(cs);
+		for (e = prop->expr; e; e = e->left.expr) {
+			if (e->right.sym->visible != no)
+				e->right.sym->flags |= SYMBOL_DEF_USER;
+		}
 	}
 	}
 
 
-	sym->user.tri = val;
-	if (oldval != val) {
+	sym->def[S_DEF_USER].tri = val;
+	if (oldval != val)
 		sym_clear_all_valid();
 		sym_clear_all_valid();
-		if (sym == modules_sym)
-			sym_set_all_changed();
-	}
 
 
 	return true;
 	return true;
 }
 }
@@ -471,8 +539,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
 		if (!prop)
 		if (!prop)
 			return true;
 			return true;
 		val = strtol(str, NULL, 10);
 		val = strtol(str, NULL, 10);
-		return val >= strtol(prop->expr->left.sym->name, NULL, 10) &&
-		       val <= strtol(prop->expr->right.sym->name, NULL, 10);
+		return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
+		       val <= sym_get_range_val(prop->expr->right.sym, 10);
 	case S_HEX:
 	case S_HEX:
 		if (!sym_string_valid(sym, str))
 		if (!sym_string_valid(sym, str))
 			return false;
 			return false;
@@ -480,8 +548,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
 		if (!prop)
 		if (!prop)
 			return true;
 			return true;
 		val = strtol(str, NULL, 16);
 		val = strtol(str, NULL, 16);
-		return val >= strtol(prop->expr->left.sym->name, NULL, 16) &&
-		       val <= strtol(prop->expr->right.sym->name, NULL, 16);
+		return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
+		       val <= sym_get_range_val(prop->expr->right.sym, 16);
 	case S_BOOLEAN:
 	case S_BOOLEAN:
 	case S_TRISTATE:
 	case S_TRISTATE:
 		switch (str[0]) {
 		switch (str[0]) {
@@ -523,20 +591,20 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
 	if (!sym_string_within_range(sym, newval))
 	if (!sym_string_within_range(sym, newval))
 		return false;
 		return false;
 
 
-	if (sym->flags & SYMBOL_NEW) {
-		sym->flags &= ~SYMBOL_NEW;
+	if (!(sym->flags & SYMBOL_DEF_USER)) {
+		sym->flags |= SYMBOL_DEF_USER;
 		sym_set_changed(sym);
 		sym_set_changed(sym);
 	}
 	}
 
 
-	oldval = sym->user.val;
+	oldval = sym->def[S_DEF_USER].val;
 	size = strlen(newval) + 1;
 	size = strlen(newval) + 1;
 	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
 	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
 		size += 2;
 		size += 2;
-		sym->user.val = val = malloc(size);
+		sym->def[S_DEF_USER].val = val = malloc(size);
 		*val++ = '0';
 		*val++ = '0';
 		*val++ = 'x';
 		*val++ = 'x';
 	} else if (!oldval || strcmp(oldval, newval))
 	} else if (!oldval || strcmp(oldval, newval))
-		sym->user.val = val = malloc(size);
+		sym->def[S_DEF_USER].val = val = malloc(size);
 	else
 	else
 		return true;
 		return true;
 
 
@@ -611,7 +679,6 @@ struct symbol *sym_lookup(const char *name, int isconst)
 	memset(symbol, 0, sizeof(*symbol));
 	memset(symbol, 0, sizeof(*symbol));
 	symbol->name = new_name;
 	symbol->name = new_name;
 	symbol->type = S_UNKNOWN;
 	symbol->type = S_UNKNOWN;
-	symbol->flags = SYMBOL_NEW;
 	if (isconst)
 	if (isconst)
 		symbol->flags |= SYMBOL_CONST;
 		symbol->flags |= SYMBOL_CONST;
 
 
@@ -724,12 +791,12 @@ struct symbol *sym_check_deps(struct symbol *sym)
 	struct symbol *sym2;
 	struct symbol *sym2;
 	struct property *prop;
 	struct property *prop;
 
 
-	if (sym->flags & SYMBOL_CHECK_DONE)
-		return NULL;
 	if (sym->flags & SYMBOL_CHECK) {
 	if (sym->flags & SYMBOL_CHECK) {
 		printf("Warning! Found recursive dependency: %s", sym->name);
 		printf("Warning! Found recursive dependency: %s", sym->name);
 		return sym;
 		return sym;
 	}
 	}
+	if (sym->flags & SYMBOL_CHECKED)
+		return NULL;
 
 
 	sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
 	sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
 	sym2 = sym_check_expr_deps(sym->rev_dep.expr);
 	sym2 = sym_check_expr_deps(sym->rev_dep.expr);
@@ -749,8 +816,13 @@ struct symbol *sym_check_deps(struct symbol *sym)
 			goto out;
 			goto out;
 	}
 	}
 out:
 out:
-	if (sym2)
+	if (sym2) {
 		printf(" %s", sym->name);
 		printf(" %s", sym->name);
+		if (sym2 == sym) {
+			printf("\n");
+			sym2 = NULL;
+		}
+	}
 	sym->flags &= ~SYMBOL_CHECK;
 	sym->flags &= ~SYMBOL_CHECK;
 	return sym2;
 	return sym2;
 }
 }

+ 8 - 5
package/config/util.c

@@ -33,8 +33,8 @@ int file_write_dep(const char *name)
 	FILE *out;
 	FILE *out;
 
 
 	if (!name)
 	if (!name)
-		name = ".config.cmd";
-	out = fopen(".config.tmp", "w");
+		name = ".kconfig.d";
+	out = fopen("..config.tmp", "w");
 	if (!out)
 	if (!out)
 		return 1;
 		return 1;
 	fprintf(out, "deps_config := \\\n");
 	fprintf(out, "deps_config := \\\n");
@@ -44,12 +44,15 @@ int file_write_dep(const char *name)
 		else
 		else
 			fprintf(out, "\t%s\n", file->name);
 			fprintf(out, "\t%s\n", file->name);
 	}
 	}
-	fprintf(out, "\n.config include/config.h: $(deps_config)\n\n$(deps_config):\n");
+	fprintf(out, "\ninclude/config/auto.conf: \\\n"
+		     "\t$(deps_config)\n\n"
+		     "$(deps_config): ;\n");
 	fclose(out);
 	fclose(out);
-	rename(".config.tmp", name);
+	rename("..config.tmp", name);
 	return 0;
 	return 0;
 }
 }
 
 
+
 /* Allocate initial growable sting */
 /* Allocate initial growable sting */
 struct gstr str_new(void)
 struct gstr str_new(void)
 {
 {
@@ -100,7 +103,7 @@ void str_printf(struct gstr *gs, const char *fmt, ...)
 	va_end(ap);
 	va_end(ap);
 }
 }
 
 
-/* Retreive value of growable string */
+/* Retrieve value of growable string */
 const char *str_get(struct gstr *gs)
 const char *str_get(struct gstr *gs)
 {
 {
 	return gs->s;
 	return gs->s;

+ 46 - 0
package/config/zconf.gperf

@@ -0,0 +1,46 @@
+%language=ANSI-C
+%define hash-function-name kconf_id_hash
+%define lookup-function-name kconf_id_lookup
+%define string-pool-name kconf_id_strings
+%compare-strncmp
+%enum
+%pic
+%struct-type
+
+struct kconf_id;
+
+%%
+mainmenu,	T_MAINMENU,	TF_COMMAND
+menu,		T_MENU,		TF_COMMAND
+endmenu,	T_ENDMENU,	TF_COMMAND
+source,		T_SOURCE,	TF_COMMAND
+choice,		T_CHOICE,	TF_COMMAND
+endchoice,	T_ENDCHOICE,	TF_COMMAND
+comment,	T_COMMENT,	TF_COMMAND
+config,		T_CONFIG,	TF_COMMAND
+menuconfig,	T_MENUCONFIG,	TF_COMMAND
+help,		T_HELP,		TF_COMMAND
+if,		T_IF,		TF_COMMAND|TF_PARAM
+endif,		T_ENDIF,	TF_COMMAND
+depends,	T_DEPENDS,	TF_COMMAND
+requires,	T_REQUIRES,	TF_COMMAND
+optional,	T_OPTIONAL,	TF_COMMAND
+default,	T_DEFAULT,	TF_COMMAND, S_UNKNOWN
+prompt,		T_PROMPT,	TF_COMMAND
+tristate,	T_TYPE,		TF_COMMAND, S_TRISTATE
+def_tristate,	T_DEFAULT,	TF_COMMAND, S_TRISTATE
+bool,		T_TYPE,		TF_COMMAND, S_BOOLEAN
+boolean,	T_TYPE,		TF_COMMAND, S_BOOLEAN
+def_bool,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN
+def_boolean,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN
+int,		T_TYPE,		TF_COMMAND, S_INT
+hex,		T_TYPE,		TF_COMMAND, S_HEX
+string,		T_TYPE,		TF_COMMAND, S_STRING
+select,		T_SELECT,	TF_COMMAND
+enable,		T_SELECT,	TF_COMMAND
+range,		T_RANGE,	TF_COMMAND
+option,		T_OPTION,	TF_COMMAND
+on,		T_ON,		TF_PARAM
+modules,	T_OPT_MODULES,	TF_OPTION
+defconfig_list,	T_OPT_DEFCONFIG_LIST,TF_OPTION
+%%

+ 242 - 0
package/config/zconf.hash.c_shipped

@@ -0,0 +1,242 @@
+/* ANSI-C code produced by gperf version 3.0.1 */
+/* Command-line: gperf  */
+/* Computed positions: -k'1,3' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+struct kconf_id;
+/* maximum key range = 45, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+kconf_id_hash (register const char *str, register unsigned int len)
+{
+  static unsigned char asso_values[] =
+    {
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 25, 30, 15,
+       0, 15,  0, 47,  5, 15, 47, 47, 30, 20,
+       5,  0, 25, 15,  0,  0, 10, 35, 47, 47,
+       5, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47
+    };
+  register int hval = len;
+
+  switch (hval)
+    {
+      default:
+        hval += asso_values[(unsigned char)str[2]];
+      /*FALLTHROUGH*/
+      case 2:
+      case 1:
+        hval += asso_values[(unsigned char)str[0]];
+        break;
+    }
+  return hval;
+}
+
+struct kconf_id_strings_t
+  {
+    char kconf_id_strings_str2[sizeof("on")];
+    char kconf_id_strings_str6[sizeof("string")];
+    char kconf_id_strings_str7[sizeof("default")];
+    char kconf_id_strings_str8[sizeof("def_bool")];
+    char kconf_id_strings_str10[sizeof("range")];
+    char kconf_id_strings_str11[sizeof("def_boolean")];
+    char kconf_id_strings_str12[sizeof("def_tristate")];
+    char kconf_id_strings_str13[sizeof("hex")];
+    char kconf_id_strings_str14[sizeof("defconfig_list")];
+    char kconf_id_strings_str16[sizeof("option")];
+    char kconf_id_strings_str17[sizeof("if")];
+    char kconf_id_strings_str18[sizeof("optional")];
+    char kconf_id_strings_str20[sizeof("endif")];
+    char kconf_id_strings_str21[sizeof("choice")];
+    char kconf_id_strings_str22[sizeof("endmenu")];
+    char kconf_id_strings_str23[sizeof("requires")];
+    char kconf_id_strings_str24[sizeof("endchoice")];
+    char kconf_id_strings_str26[sizeof("config")];
+    char kconf_id_strings_str27[sizeof("modules")];
+    char kconf_id_strings_str28[sizeof("int")];
+    char kconf_id_strings_str29[sizeof("menu")];
+    char kconf_id_strings_str31[sizeof("prompt")];
+    char kconf_id_strings_str32[sizeof("depends")];
+    char kconf_id_strings_str33[sizeof("tristate")];
+    char kconf_id_strings_str34[sizeof("bool")];
+    char kconf_id_strings_str35[sizeof("menuconfig")];
+    char kconf_id_strings_str36[sizeof("select")];
+    char kconf_id_strings_str37[sizeof("boolean")];
+    char kconf_id_strings_str39[sizeof("help")];
+    char kconf_id_strings_str41[sizeof("source")];
+    char kconf_id_strings_str42[sizeof("comment")];
+    char kconf_id_strings_str43[sizeof("mainmenu")];
+    char kconf_id_strings_str46[sizeof("enable")];
+  };
+static struct kconf_id_strings_t kconf_id_strings_contents =
+  {
+    "on",
+    "string",
+    "default",
+    "def_bool",
+    "range",
+    "def_boolean",
+    "def_tristate",
+    "hex",
+    "defconfig_list",
+    "option",
+    "if",
+    "optional",
+    "endif",
+    "choice",
+    "endmenu",
+    "requires",
+    "endchoice",
+    "config",
+    "modules",
+    "int",
+    "menu",
+    "prompt",
+    "depends",
+    "tristate",
+    "bool",
+    "menuconfig",
+    "select",
+    "boolean",
+    "help",
+    "source",
+    "comment",
+    "mainmenu",
+    "enable"
+  };
+#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
+#ifdef __GNUC__
+__inline
+#endif
+struct kconf_id *
+kconf_id_lookup (register const char *str, register unsigned int len)
+{
+  enum
+    {
+      TOTAL_KEYWORDS = 33,
+      MIN_WORD_LENGTH = 2,
+      MAX_WORD_LENGTH = 14,
+      MIN_HASH_VALUE = 2,
+      MAX_HASH_VALUE = 46
+    };
+
+  static struct kconf_id wordlist[] =
+    {
+      {-1}, {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2,		T_ON,		TF_PARAM},
+      {-1}, {-1}, {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6,		T_TYPE,		TF_COMMAND, S_STRING},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7,	T_DEFAULT,	TF_COMMAND, S_UNKNOWN},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10,		T_RANGE,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,	T_DEFAULT,	TF_COMMAND, S_TRISTATE},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13,		T_TYPE,		TF_COMMAND, S_HEX},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,	T_OPT_DEFCONFIG_LIST,TF_OPTION},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16,		T_OPTION,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,		T_IF,		TF_COMMAND|TF_PARAM},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,	T_OPTIONAL,	TF_COMMAND},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20,		T_ENDIF,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21,		T_CHOICE,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,	T_ENDMENU,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,	T_REQUIRES,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str24,	T_ENDCHOICE,	TF_COMMAND},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26,		T_CONFIG,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27,	T_OPT_MODULES,	TF_OPTION},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28,		T_TYPE,		TF_COMMAND, S_INT},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29,		T_MENU,		TF_COMMAND},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31,		T_PROMPT,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32,	T_DEPENDS,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33,	T_TYPE,		TF_COMMAND, S_TRISTATE},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34,		T_TYPE,		TF_COMMAND, S_BOOLEAN},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35,	T_MENUCONFIG,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36,		T_SELECT,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37,	T_TYPE,		TF_COMMAND, S_BOOLEAN},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39,		T_HELP,		TF_COMMAND},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,		T_SOURCE,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,	T_COMMENT,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43,	T_MAINMENU,	TF_COMMAND},
+      {-1}, {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,		T_SELECT,	TF_COMMAND}
+    };
+
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = kconf_id_hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= 0)
+        {
+          register int o = wordlist[key].name;
+          if (o >= 0)
+            {
+              register const char *s = o + kconf_id_strings;
+
+              if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+                return &wordlist[key];
+            }
+        }
+    }
+  return 0;
+}
+

+ 40 - 56
package/config/zconf.l

@@ -18,8 +18,12 @@
 
 
 #define START_STRSIZE	16
 #define START_STRSIZE	16
 
 
-char *text;
-static char *text_ptr;
+static struct {
+	struct file *file;
+	int lineno;
+} current_pos;
+
+static char *text;
 static int text_size, text_asize;
 static int text_size, text_asize;
 
 
 struct buffer {
 struct buffer {
@@ -32,29 +36,28 @@ struct buffer *current_buf;
 static int last_ts, first_ts;
 static int last_ts, first_ts;
 
 
 static void zconf_endhelp(void);
 static void zconf_endhelp(void);
-static struct buffer *zconf_endfile(void);
+static void zconf_endfile(void);
 
 
 void new_string(void)
 void new_string(void)
 {
 {
 	text = malloc(START_STRSIZE);
 	text = malloc(START_STRSIZE);
 	text_asize = START_STRSIZE;
 	text_asize = START_STRSIZE;
-	text_ptr = text;
 	text_size = 0;
 	text_size = 0;
-	*text_ptr = 0;
+	*text = 0;
 }
 }
 
 
 void append_string(const char *str, int size)
 void append_string(const char *str, int size)
 {
 {
 	int new_size = text_size + size + 1;
 	int new_size = text_size + size + 1;
 	if (new_size > text_asize) {
 	if (new_size > text_asize) {
+		new_size += START_STRSIZE - 1;
+		new_size &= -START_STRSIZE;
 		text = realloc(text, new_size);
 		text = realloc(text, new_size);
 		text_asize = new_size;
 		text_asize = new_size;
-		text_ptr = text + text_size;
 	}
 	}
-	memcpy(text_ptr, str, size);
-	text_ptr += size;
+	memcpy(text + text_size, str, size);
 	text_size += size;
 	text_size += size;
-	*text_ptr = 0;
+	text[text_size] = 0;
 }
 }
 
 
 void alloc_string(const char *str, int size)
 void alloc_string(const char *str, int size)
@@ -72,10 +75,13 @@ n	[A-Za-z0-9_]
 	int str = 0;
 	int str = 0;
 	int ts, i;
 	int ts, i;
 
 
-[ \t]*#.*\n	current_file->lineno++;
+[ \t]*#.*\n	|
+[ \t]*\n	{
+	current_file->lineno++;
+	return T_EOL;
+}
 [ \t]*#.*
 [ \t]*#.*
 
 
-[ \t]*\n	current_file->lineno++; return T_EOL;
 
 
 [ \t]+	{
 [ \t]+	{
 	BEGIN(COMMAND);
 	BEGIN(COMMAND);
@@ -88,42 +94,25 @@ n	[A-Za-z0-9_]
 
 
 
 
 <COMMAND>{
 <COMMAND>{
-	"mainmenu"		BEGIN(PARAM); return T_MAINMENU;
-	"menu"			BEGIN(PARAM); return T_MENU;
-	"endmenu"		BEGIN(PARAM); return T_ENDMENU;
-	"source"		BEGIN(PARAM); return T_SOURCE;
-	"choice"		BEGIN(PARAM); return T_CHOICE;
-	"endchoice"		BEGIN(PARAM); return T_ENDCHOICE;
-	"comment"		BEGIN(PARAM); return T_COMMENT;
-	"config"		BEGIN(PARAM); return T_CONFIG;
-	"menuconfig"		BEGIN(PARAM); return T_MENUCONFIG;
-	"help"			BEGIN(PARAM); return T_HELP;
-	"if"			BEGIN(PARAM); return T_IF;
-	"endif"			BEGIN(PARAM); return T_ENDIF;
-	"depends"		BEGIN(PARAM); return T_DEPENDS;
-	"requires"		BEGIN(PARAM); return T_REQUIRES;
-	"optional"		BEGIN(PARAM); return T_OPTIONAL;
-	"default"		BEGIN(PARAM); return T_DEFAULT;
-	"prompt"		BEGIN(PARAM); return T_PROMPT;
-	"tristate"		BEGIN(PARAM); return T_TRISTATE;
-	"def_tristate"		BEGIN(PARAM); return T_DEF_TRISTATE;
-	"bool"			BEGIN(PARAM); return T_BOOLEAN;
-	"boolean"		BEGIN(PARAM); return T_BOOLEAN;
-	"def_bool"		BEGIN(PARAM); return T_DEF_BOOLEAN;
-	"def_boolean"		BEGIN(PARAM); return T_DEF_BOOLEAN;
-	"int"			BEGIN(PARAM); return T_INT;
-	"hex"			BEGIN(PARAM); return T_HEX;
-	"string"		BEGIN(PARAM); return T_STRING;
-	"select"		BEGIN(PARAM); return T_SELECT;
-	"enable"		BEGIN(PARAM); return T_SELECT;
-	"range"			BEGIN(PARAM); return T_RANGE;
 	{n}+	{
 	{n}+	{
+		struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+		BEGIN(PARAM);
+		current_pos.file = current_file;
+		current_pos.lineno = current_file->lineno;
+		if (id && id->flags & TF_COMMAND) {
+			zconflval.id = id;
+			return id->token;
+		}
 		alloc_string(yytext, yyleng);
 		alloc_string(yytext, yyleng);
 		zconflval.string = text;
 		zconflval.string = text;
 		return T_WORD;
 		return T_WORD;
 	}
 	}
 	.
 	.
-	\n	current_file->lineno++; BEGIN(INITIAL);
+	\n	{
+		BEGIN(INITIAL);
+		current_file->lineno++;
+		return T_EOL;
+	}
 }
 }
 
 
 <PARAM>{
 <PARAM>{
@@ -134,8 +123,6 @@ n	[A-Za-z0-9_]
 	"!"	return T_NOT;
 	"!"	return T_NOT;
 	"="	return T_EQUAL;
 	"="	return T_EQUAL;
 	"!="	return T_UNEQUAL;
 	"!="	return T_UNEQUAL;
-	"if"	return T_IF;
-	"on"	return T_ON;
 	\"|\'	{
 	\"|\'	{
 		str = yytext[0];
 		str = yytext[0];
 		new_string();
 		new_string();
@@ -144,6 +131,11 @@ n	[A-Za-z0-9_]
 	\n	BEGIN(INITIAL); current_file->lineno++; return T_EOL;
 	\n	BEGIN(INITIAL); current_file->lineno++; return T_EOL;
 	---	/* ignore */
 	---	/* ignore */
 	({n}|[-/.])+	{
 	({n}|[-/.])+	{
+		struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+		if (id && id->flags & TF_PARAM) {
+			zconflval.id = id;
+			return id->token;
+		}
 		alloc_string(yytext, yyleng);
 		alloc_string(yytext, yyleng);
 		zconflval.string = text;
 		zconflval.string = text;
 		return T_WORD;
 		return T_WORD;
@@ -236,9 +228,9 @@ n	[A-Za-z0-9_]
 }
 }
 
 
 <<EOF>>	{
 <<EOF>>	{
-	if (current_buf) {
+	if (current_file) {
 		zconf_endfile();
 		zconf_endfile();
-		return T_EOF;
+		return T_EOL;
 	}
 	}
 	fclose(yyin);
 	fclose(yyin);
 	yyterminate();
 	yyterminate();
@@ -329,7 +321,7 @@ void zconf_nextfile(const char *name)
 	current_file = file;
 	current_file = file;
 }
 }
 
 
-static struct buffer *zconf_endfile(void)
+static void zconf_endfile(void)
 {
 {
 	struct buffer *parent;
 	struct buffer *parent;
 
 
@@ -345,22 +337,14 @@ static struct buffer *zconf_endfile(void)
 	}
 	}
 	free(current_buf);
 	free(current_buf);
 	current_buf = parent;
 	current_buf = parent;
-
-	return parent;
 }
 }
 
 
 int zconf_lineno(void)
 int zconf_lineno(void)
 {
 {
-	if (current_buf)
-		return current_file->lineno - 1;
-	else
-		return 0;
+	return current_pos.lineno;
 }
 }
 
 
 char *zconf_curname(void)
 char *zconf_curname(void)
 {
 {
-	if (current_buf)
-		return current_file->name;
-	else
-		return "<none>";
+	return current_pos.file ? current_pos.file->name : "<none>";
 }
 }

+ 859 - 644
package/config/zconf.tab.c_shipped

@@ -1,7 +1,7 @@
-/* A Bison parser, made by GNU Bison 1.875a.  */
+/* A Bison parser, made by GNU Bison 2.1.  */
 
 
 /* Skeleton parser for Yacc-like parsing with Bison,
 /* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 
    This program is free software; you can redistribute it and/or modify
    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
    it under the terms of the GNU General Public License as published by
@@ -15,8 +15,8 @@
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 
 /* As a special exception, when this file is copied by Bison into a
 /* As a special exception, when this file is copied by Bison into a
    Bison output file, you may use that output file without restriction.
    Bison output file, you may use that output file without restriction.
@@ -36,6 +36,9 @@
 /* Identify Bison output.  */
 /* Identify Bison output.  */
 #define YYBISON 1
 #define YYBISON 1
 
 
+/* Bison version.  */
+#define YYBISON_VERSION "2.1"
+
 /* Skeleton name.  */
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 #define YYSKELETON_NAME "yacc.c"
 
 
@@ -45,8 +48,7 @@
 /* Using locations.  */
 /* Using locations.  */
 #define YYLSP_NEEDED 0
 #define YYLSP_NEEDED 0
 
 
-/* If NAME_PREFIX is specified substitute the variables and functions
-   names.  */
+/* Substitute the variable and function names.  */
 #define yyparse zconfparse
 #define yyparse zconfparse
 #define yylex   zconflex
 #define yylex   zconflex
 #define yyerror zconferror
 #define yyerror zconferror
@@ -79,30 +81,25 @@
      T_REQUIRES = 272,
      T_REQUIRES = 272,
      T_OPTIONAL = 273,
      T_OPTIONAL = 273,
      T_PROMPT = 274,
      T_PROMPT = 274,
-     T_DEFAULT = 275,
-     T_TRISTATE = 276,
-     T_DEF_TRISTATE = 277,
-     T_BOOLEAN = 278,
-     T_DEF_BOOLEAN = 279,
-     T_STRING = 280,
-     T_INT = 281,
-     T_HEX = 282,
-     T_WORD = 283,
-     T_WORD_QUOTE = 284,
-     T_UNEQUAL = 285,
-     T_EOF = 286,
-     T_EOL = 287,
-     T_CLOSE_PAREN = 288,
-     T_OPEN_PAREN = 289,
-     T_ON = 290,
-     T_SELECT = 291,
-     T_RANGE = 292,
-     T_OR = 293,
-     T_AND = 294,
-     T_EQUAL = 295,
-     T_NOT = 296
+     T_TYPE = 275,
+     T_DEFAULT = 276,
+     T_SELECT = 277,
+     T_RANGE = 278,
+     T_OPTION = 279,
+     T_ON = 280,
+     T_WORD = 281,
+     T_WORD_QUOTE = 282,
+     T_UNEQUAL = 283,
+     T_CLOSE_PAREN = 284,
+     T_OPEN_PAREN = 285,
+     T_EOL = 286,
+     T_OR = 287,
+     T_AND = 288,
+     T_EQUAL = 289,
+     T_NOT = 290
    };
    };
 #endif
 #endif
+/* Tokens.  */
 #define T_MAINMENU 258
 #define T_MAINMENU 258
 #define T_MENU 259
 #define T_MENU 259
 #define T_ENDMENU 260
 #define T_ENDMENU 260
@@ -120,28 +117,22 @@
 #define T_REQUIRES 272
 #define T_REQUIRES 272
 #define T_OPTIONAL 273
 #define T_OPTIONAL 273
 #define T_PROMPT 274
 #define T_PROMPT 274
-#define T_DEFAULT 275
-#define T_TRISTATE 276
-#define T_DEF_TRISTATE 277
-#define T_BOOLEAN 278
-#define T_DEF_BOOLEAN 279
-#define T_STRING 280
-#define T_INT 281
-#define T_HEX 282
-#define T_WORD 283
-#define T_WORD_QUOTE 284
-#define T_UNEQUAL 285
-#define T_EOF 286
-#define T_EOL 287
-#define T_CLOSE_PAREN 288
-#define T_OPEN_PAREN 289
-#define T_ON 290
-#define T_SELECT 291
-#define T_RANGE 292
-#define T_OR 293
-#define T_AND 294
-#define T_EQUAL 295
-#define T_NOT 296
+#define T_TYPE 275
+#define T_DEFAULT 276
+#define T_SELECT 277
+#define T_RANGE 278
+#define T_OPTION 279
+#define T_ON 280
+#define T_WORD 281
+#define T_WORD_QUOTE 282
+#define T_UNEQUAL 283
+#define T_CLOSE_PAREN 284
+#define T_OPEN_PAREN 285
+#define T_EOL 286
+#define T_OR 287
+#define T_AND 288
+#define T_EQUAL 289
+#define T_NOT 290
 
 
 
 
 
 
@@ -161,6 +152,11 @@
 #include <string.h>
 #include <string.h>
 #include <stdbool.h>
 #include <stdbool.h>
 
 
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#include "zconf.hash.c"
+
 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
 
 
 #define PRINTD		0x0001
 #define PRINTD		0x0001
@@ -170,14 +166,18 @@ int cdebug = PRINTD;
 
 
 extern int zconflex(void);
 extern int zconflex(void);
 static void zconfprint(const char *err, ...);
 static void zconfprint(const char *err, ...);
+static void zconf_error(const char *err, ...);
 static void zconferror(const char *err);
 static void zconferror(const char *err);
-static bool zconf_endtoken(int token, int starttoken, int endtoken);
+static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
 
 
 struct symbol *symbol_hash[257];
 struct symbol *symbol_hash[257];
 
 
 static struct menu *current_menu, *current_entry;
 static struct menu *current_menu, *current_entry;
 
 
+#define YYDEBUG 0
+#if YYDEBUG
 #define YYERROR_VERBOSE
 #define YYERROR_VERBOSE
+#endif
 
 
 
 
 /* Enabling traces.  */
 /* Enabling traces.  */
@@ -193,16 +193,22 @@ static struct menu *current_menu, *current_entry;
 # define YYERROR_VERBOSE 0
 # define YYERROR_VERBOSE 0
 #endif
 #endif
 
 
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
 
 
 typedef union YYSTYPE {
 typedef union YYSTYPE {
-	int token;
 	char *string;
 	char *string;
+	struct file *file;
 	struct symbol *symbol;
 	struct symbol *symbol;
 	struct expr *expr;
 	struct expr *expr;
 	struct menu *menu;
 	struct menu *menu;
+	struct kconf_id *id;
 } YYSTYPE;
 } YYSTYPE;
-/* Line 191 of yacc.c.  */
+/* Line 196 of yacc.c.  */
 
 
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 # define YYSTYPE_IS_DECLARED 1
@@ -214,26 +220,48 @@ typedef union YYSTYPE {
 /* Copy the second part of user declarations.  */
 /* Copy the second part of user declarations.  */
 
 
 
 
-#define LKC_DIRECT_LINK
-#include "lkc.h"
+/* Line 219 of yacc.c.  */
 
 
 
 
-/* Line 214 of yacc.c.  */
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus))
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
 
 
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
 
 
 #if ! defined (yyoverflow) || YYERROR_VERBOSE
 #if ! defined (yyoverflow) || YYERROR_VERBOSE
 
 
 /* The parser invokes alloca or malloc; define the necessary symbols.  */
 /* The parser invokes alloca or malloc; define the necessary symbols.  */
 
 
-# if YYSTACK_USE_ALLOCA
-#  define YYSTACK_ALLOC alloca
-# else
-#  ifndef YYSTACK_USE_ALLOCA
-#   if defined (alloca) || defined (_ALLOCA_H)
-#    define YYSTACK_ALLOC alloca
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
 #   else
 #   else
-#    ifdef __GNUC__
-#     define YYSTACK_ALLOC __builtin_alloca
+#    define YYSTACK_ALLOC alloca
+#    if defined (__STDC__) || defined (__cplusplus)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     define YYINCLUDED_STDLIB_H
 #    endif
 #    endif
 #   endif
 #   endif
 #  endif
 #  endif
@@ -242,25 +270,51 @@ typedef union YYSTYPE {
 # ifdef YYSTACK_ALLOC
 # ifdef YYSTACK_ALLOC
    /* Pacify GCC's `empty if-body' warning. */
    /* Pacify GCC's `empty if-body' warning. */
 #  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
 #  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */
+#  endif
 # else
 # else
-#  if defined (__STDC__) || defined (__cplusplus)
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   define YYSIZE_T size_t
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1)
+#  endif
+#  ifdef __cplusplus
+extern "C" {
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \
+	&& (defined (__STDC__) || defined (__cplusplus)))
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \
+	&& (defined (__STDC__) || defined (__cplusplus)))
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifdef __cplusplus
+}
 #  endif
 #  endif
-#  define YYSTACK_ALLOC malloc
-#  define YYSTACK_FREE free
 # endif
 # endif
 #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
 #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
 
 
 
 
 #if (! defined (yyoverflow) \
 #if (! defined (yyoverflow) \
      && (! defined (__cplusplus) \
      && (! defined (__cplusplus) \
-	 || (YYSTYPE_IS_TRIVIAL)))
+	 || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
 
 
 /* A type that is properly aligned for any stack member.  */
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 union yyalloc
 {
 {
-  short yyss;
+  short int yyss;
   YYSTYPE yyvs;
   YYSTYPE yyvs;
   };
   };
 
 
@@ -270,20 +324,20 @@ union yyalloc
 /* The size of an array large to enough to hold all stacks, each with
 /* The size of an array large to enough to hold all stacks, each with
    N elements.  */
    N elements.  */
 # define YYSTACK_BYTES(N) \
 # define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (short) + sizeof (YYSTYPE))				\
+     ((N) * (sizeof (short int) + sizeof (YYSTYPE))			\
       + YYSTACK_GAP_MAXIMUM)
       + YYSTACK_GAP_MAXIMUM)
 
 
 /* Copy COUNT objects from FROM to TO.  The source and destination do
 /* Copy COUNT objects from FROM to TO.  The source and destination do
    not overlap.  */
    not overlap.  */
 # ifndef YYCOPY
 # ifndef YYCOPY
-#  if 1 < __GNUC__
+#  if defined (__GNUC__) && 1 < __GNUC__
 #   define YYCOPY(To, From, Count) \
 #   define YYCOPY(To, From, Count) \
       __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
       __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
 #  else
 #  else
 #   define YYCOPY(To, From, Count)		\
 #   define YYCOPY(To, From, Count)		\
       do					\
       do					\
 	{					\
 	{					\
-	  register YYSIZE_T yyi;		\
+	  YYSIZE_T yyi;				\
 	  for (yyi = 0; yyi < (Count); yyi++)	\
 	  for (yyi = 0; yyi < (Count); yyi++)	\
 	    (To)[yyi] = (From)[yyi];		\
 	    (To)[yyi] = (From)[yyi];		\
 	}					\
 	}					\
@@ -312,28 +366,28 @@ union yyalloc
 #if defined (__STDC__) || defined (__cplusplus)
 #if defined (__STDC__) || defined (__cplusplus)
    typedef signed char yysigned_char;
    typedef signed char yysigned_char;
 #else
 #else
-   typedef short yysigned_char;
+   typedef short int yysigned_char;
 #endif
 #endif
 
 
 /* YYFINAL -- State number of the termination state. */
 /* YYFINAL -- State number of the termination state. */
-#define YYFINAL  2
+#define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   201
+#define YYLAST   275
 
 
 /* YYNTOKENS -- Number of terminals. */
 /* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  42
+#define YYNTOKENS  36
 /* YYNNTS -- Number of nonterminals. */
 /* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  41
+#define YYNNTS  45
 /* YYNRULES -- Number of rules. */
 /* YYNRULES -- Number of rules. */
-#define YYNRULES  104
+#define YYNRULES  110
 /* YYNRULES -- Number of states. */
 /* YYNRULES -- Number of states. */
-#define YYNSTATES  182
+#define YYNSTATES  183
 
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   296
+#define YYMAXUTOK   290
 
 
-#define YYTRANSLATE(YYX) 						\
+#define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 
 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
@@ -368,148 +422,152 @@ static const unsigned char yytranslate[] =
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41
+      35
 };
 };
 
 
 #if YYDEBUG
 #if YYDEBUG
 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
    YYRHS.  */
    YYRHS.  */
-static const unsigned short yyprhs[] =
+static const unsigned short int yyprhs[] =
 {
 {
-       0,     0,     3,     4,     7,     9,    11,    13,    17,    19,
-      21,    23,    26,    28,    30,    32,    34,    36,    38,    42,
-      45,    49,    52,    53,    56,    59,    62,    65,    69,    74,
-      78,    83,    87,    91,    95,   100,   105,   110,   116,   119,
-     122,   124,   128,   131,   132,   135,   138,   141,   144,   149,
-     153,   157,   160,   165,   166,   169,   173,   175,   179,   182,
-     183,   186,   189,   192,   196,   199,   201,   205,   208,   209,
-     212,   215,   218,   222,   226,   228,   232,   235,   238,   241,
-     242,   245,   248,   253,   257,   261,   262,   265,   267,   269,
-     272,   275,   278,   280,   282,   283,   286,   288,   292,   296,
-     300,   303,   307,   311,   313
+       0,     0,     3,     5,     6,     9,    12,    15,    20,    23,
+      28,    33,    37,    39,    41,    43,    45,    47,    49,    51,
+      53,    55,    57,    59,    61,    63,    67,    70,    74,    77,
+      81,    84,    85,    88,    91,    94,    97,   100,   103,   107,
+     112,   117,   122,   128,   132,   133,   137,   138,   141,   144,
+     147,   149,   153,   154,   157,   160,   163,   166,   169,   174,
+     178,   181,   186,   187,   190,   194,   196,   200,   201,   204,
+     207,   210,   214,   217,   219,   223,   224,   227,   230,   233,
+     237,   241,   244,   247,   250,   251,   254,   257,   260,   265,
+     269,   273,   274,   277,   279,   281,   284,   287,   290,   292,
+     295,   296,   299,   301,   305,   309,   313,   316,   320,   324,
+     326
 };
 };
 
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
 static const yysigned_char yyrhs[] =
 static const yysigned_char yyrhs[] =
 {
 {
-      43,     0,    -1,    -1,    43,    44,    -1,    45,    -1,    55,
-      -1,    66,    -1,     3,    77,    79,    -1,     5,    -1,    15,
-      -1,     8,    -1,     1,    79,    -1,    61,    -1,    71,    -1,
-      47,    -1,    49,    -1,    69,    -1,    79,    -1,    10,    28,
-      32,    -1,    46,    50,    -1,    11,    28,    32,    -1,    48,
-      50,    -1,    -1,    50,    51,    -1,    50,    75,    -1,    50,
-      73,    -1,    50,    32,    -1,    21,    76,    32,    -1,    22,
-      81,    80,    32,    -1,    23,    76,    32,    -1,    24,    81,
-      80,    32,    -1,    26,    76,    32,    -1,    27,    76,    32,
-      -1,    25,    76,    32,    -1,    19,    77,    80,    32,    -1,
-      20,    81,    80,    32,    -1,    36,    28,    80,    32,    -1,
-      37,    82,    82,    80,    32,    -1,     7,    32,    -1,    52,
-      56,    -1,    78,    -1,    53,    58,    54,    -1,    53,    58,
-      -1,    -1,    56,    57,    -1,    56,    75,    -1,    56,    73,
-      -1,    56,    32,    -1,    19,    77,    80,    32,    -1,    21,
-      76,    32,    -1,    23,    76,    32,    -1,    18,    32,    -1,
-      20,    28,    80,    32,    -1,    -1,    58,    45,    -1,    14,
-      81,    32,    -1,    78,    -1,    59,    62,    60,    -1,    59,
-      62,    -1,    -1,    62,    45,    -1,    62,    66,    -1,    62,
-      55,    -1,     4,    77,    32,    -1,    63,    74,    -1,    78,
-      -1,    64,    67,    65,    -1,    64,    67,    -1,    -1,    67,
-      45,    -1,    67,    66,    -1,    67,    55,    -1,    67,     1,
-      32,    -1,     6,    77,    32,    -1,    68,    -1,     9,    77,
-      32,    -1,    70,    74,    -1,    12,    32,    -1,    72,    13,
-      -1,    -1,    74,    75,    -1,    74,    32,    -1,    16,    35,
-      81,    32,    -1,    16,    81,    32,    -1,    17,    81,    32,
-      -1,    -1,    77,    80,    -1,    28,    -1,    29,    -1,     5,
-      79,    -1,     8,    79,    -1,    15,    79,    -1,    32,    -1,
-      31,    -1,    -1,    14,    81,    -1,    82,    -1,    82,    40,
-      82,    -1,    82,    30,    82,    -1,    34,    81,    33,    -1,
-      41,    81,    -1,    81,    38,    81,    -1,    81,    39,    81,
-      -1,    28,    -1,    29,    -1
+      37,     0,    -1,    38,    -1,    -1,    38,    40,    -1,    38,
+      54,    -1,    38,    65,    -1,    38,     3,    75,    77,    -1,
+      38,    76,    -1,    38,    26,     1,    31,    -1,    38,    39,
+       1,    31,    -1,    38,     1,    31,    -1,    16,    -1,    19,
+      -1,    20,    -1,    22,    -1,    18,    -1,    23,    -1,    21,
+      -1,    31,    -1,    60,    -1,    69,    -1,    43,    -1,    45,
+      -1,    67,    -1,    26,     1,    31,    -1,     1,    31,    -1,
+      10,    26,    31,    -1,    42,    46,    -1,    11,    26,    31,
+      -1,    44,    46,    -1,    -1,    46,    47,    -1,    46,    48,
+      -1,    46,    73,    -1,    46,    71,    -1,    46,    41,    -1,
+      46,    31,    -1,    20,    74,    31,    -1,    19,    75,    78,
+      31,    -1,    21,    79,    78,    31,    -1,    22,    26,    78,
+      31,    -1,    23,    80,    80,    78,    31,    -1,    24,    49,
+      31,    -1,    -1,    49,    26,    50,    -1,    -1,    34,    75,
+      -1,     7,    31,    -1,    51,    55,    -1,    76,    -1,    52,
+      57,    53,    -1,    -1,    55,    56,    -1,    55,    73,    -1,
+      55,    71,    -1,    55,    31,    -1,    55,    41,    -1,    19,
+      75,    78,    31,    -1,    20,    74,    31,    -1,    18,    31,
+      -1,    21,    26,    78,    31,    -1,    -1,    57,    40,    -1,
+      14,    79,    77,    -1,    76,    -1,    58,    61,    59,    -1,
+      -1,    61,    40,    -1,    61,    65,    -1,    61,    54,    -1,
+       4,    75,    31,    -1,    62,    72,    -1,    76,    -1,    63,
+      66,    64,    -1,    -1,    66,    40,    -1,    66,    65,    -1,
+      66,    54,    -1,     6,    75,    31,    -1,     9,    75,    31,
+      -1,    68,    72,    -1,    12,    31,    -1,    70,    13,    -1,
+      -1,    72,    73,    -1,    72,    31,    -1,    72,    41,    -1,
+      16,    25,    79,    31,    -1,    16,    79,    31,    -1,    17,
+      79,    31,    -1,    -1,    75,    78,    -1,    26,    -1,    27,
+      -1,     5,    31,    -1,     8,    31,    -1,    15,    31,    -1,
+      31,    -1,    77,    31,    -1,    -1,    14,    79,    -1,    80,
+      -1,    80,    34,    80,    -1,    80,    28,    80,    -1,    30,
+      79,    29,    -1,    35,    79,    -1,    79,    32,    79,    -1,
+      79,    33,    79,    -1,    26,    -1,    27,    -1
 };
 };
 
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const unsigned short yyrline[] =
+static const unsigned short int yyrline[] =
 {
 {
-       0,    94,    94,    95,    98,    99,   100,   101,   102,   103,
-     104,   105,   109,   110,   111,   112,   113,   114,   120,   128,
-     134,   142,   152,   154,   155,   156,   157,   160,   166,   173,
-     179,   186,   192,   198,   204,   210,   216,   222,   230,   239,
-     245,   254,   255,   261,   263,   264,   265,   266,   269,   275,
-     281,   287,   293,   299,   301,   306,   315,   324,   325,   331,
-     333,   334,   335,   340,   347,   353,   362,   363,   369,   371,
-     372,   373,   374,   377,   383,   390,   397,   404,   410,   417,
-     418,   419,   422,   427,   432,   440,   442,   447,   448,   451,
-     452,   453,   457,   457,   459,   460,   463,   464,   465,   466,
-     467,   468,   469,   472,   473
+       0,   105,   105,   107,   109,   110,   111,   112,   113,   114,
+     115,   119,   123,   123,   123,   123,   123,   123,   123,   127,
+     128,   129,   130,   131,   132,   136,   137,   143,   151,   157,
+     165,   175,   177,   178,   179,   180,   181,   182,   185,   193,
+     199,   209,   215,   221,   224,   226,   237,   238,   243,   252,
+     257,   265,   268,   270,   271,   272,   273,   274,   277,   283,
+     294,   300,   310,   312,   317,   325,   333,   336,   338,   339,
+     340,   345,   352,   357,   365,   368,   370,   371,   372,   375,
+     383,   390,   397,   403,   410,   412,   413,   414,   417,   422,
+     427,   435,   437,   442,   443,   446,   447,   448,   452,   453,
+     456,   457,   460,   461,   462,   463,   464,   465,   466,   469,
+     470
 };
 };
 #endif
 #endif
 
 
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals. */
    First, the terminals, then, starting at YYNTOKENS, nonterminals. */
 static const char *const yytname[] =
 static const char *const yytname[] =
 {
 {
-  "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", 
-  "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", 
-  "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", 
-  "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE", 
-  "T_DEF_TRISTATE", "T_BOOLEAN", "T_DEF_BOOLEAN", "T_STRING", "T_INT", 
-  "T_HEX", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", "T_EOF", "T_EOL", 
-  "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", "T_SELECT", "T_RANGE", "T_OR", 
-  "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block", 
-  "common_block", "config_entry_start", "config_stmt", 
-  "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", 
-  "config_option", "choice", "choice_entry", "choice_end", "choice_stmt", 
-  "choice_option_list", "choice_option", "choice_block", "if", "if_end", 
-  "if_stmt", "if_block", "menu", "menu_entry", "menu_end", "menu_stmt", 
-  "menu_block", "source", "source_stmt", "comment", "comment_stmt", 
-  "help_start", "help", "depends_list", "depends", "prompt_stmt_opt", 
-  "prompt", "end", "nl_or_eof", "if_expr", "expr", "symbol", 0
+  "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU",
+  "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
+  "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
+  "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT",
+  "T_SELECT", "T_RANGE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE",
+  "T_UNEQUAL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND",
+  "T_EQUAL", "T_NOT", "$accept", "input", "stmt_list", "option_name",
+  "common_stmt", "option_error", "config_entry_start", "config_stmt",
+  "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
+  "config_option", "symbol_option", "symbol_option_list",
+  "symbol_option_arg", "choice", "choice_entry", "choice_end",
+  "choice_stmt", "choice_option_list", "choice_option", "choice_block",
+  "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry",
+  "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment",
+  "comment_stmt", "help_start", "help", "depends_list", "depends",
+  "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", 0
 };
 };
 #endif
 #endif
 
 
 # ifdef YYPRINT
 # ifdef YYPRINT
 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
    token YYLEX-NUM.  */
    token YYLEX-NUM.  */
-static const unsigned short yytoknum[] =
+static const unsigned short int yytoknum[] =
 {
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296
+     285,   286,   287,   288,   289,   290
 };
 };
 # endif
 # endif
 
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const unsigned char yyr1[] =
 static const unsigned char yyr1[] =
 {
 {
-       0,    42,    43,    43,    44,    44,    44,    44,    44,    44,
-      44,    44,    45,    45,    45,    45,    45,    45,    46,    47,
-      48,    49,    50,    50,    50,    50,    50,    51,    51,    51,
-      51,    51,    51,    51,    51,    51,    51,    51,    52,    53,
-      54,    55,    55,    56,    56,    56,    56,    56,    57,    57,
-      57,    57,    57,    58,    58,    59,    60,    61,    61,    62,
-      62,    62,    62,    63,    64,    65,    66,    66,    67,    67,
-      67,    67,    67,    68,    69,    70,    71,    72,    73,    74,
-      74,    74,    75,    75,    75,    76,    76,    77,    77,    78,
-      78,    78,    79,    79,    80,    80,    81,    81,    81,    81,
-      81,    81,    81,    82,    82
+       0,    36,    37,    38,    38,    38,    38,    38,    38,    38,
+      38,    38,    39,    39,    39,    39,    39,    39,    39,    40,
+      40,    40,    40,    40,    40,    41,    41,    42,    43,    44,
+      45,    46,    46,    46,    46,    46,    46,    46,    47,    47,
+      47,    47,    47,    48,    49,    49,    50,    50,    51,    52,
+      53,    54,    55,    55,    55,    55,    55,    55,    56,    56,
+      56,    56,    57,    57,    58,    59,    60,    61,    61,    61,
+      61,    62,    63,    64,    65,    66,    66,    66,    66,    67,
+      68,    69,    70,    71,    72,    72,    72,    72,    73,    73,
+      73,    74,    74,    75,    75,    76,    76,    76,    77,    77,
+      78,    78,    79,    79,    79,    79,    79,    79,    79,    80,
+      80
 };
 };
 
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const unsigned char yyr2[] =
 static const unsigned char yyr2[] =
 {
 {
-       0,     2,     0,     2,     1,     1,     1,     3,     1,     1,
-       1,     2,     1,     1,     1,     1,     1,     1,     3,     2,
-       3,     2,     0,     2,     2,     2,     2,     3,     4,     3,
-       4,     3,     3,     3,     4,     4,     4,     5,     2,     2,
-       1,     3,     2,     0,     2,     2,     2,     2,     4,     3,
-       3,     2,     4,     0,     2,     3,     1,     3,     2,     0,
-       2,     2,     2,     3,     2,     1,     3,     2,     0,     2,
-       2,     2,     3,     3,     1,     3,     2,     2,     2,     0,
-       2,     2,     4,     3,     3,     0,     2,     1,     1,     2,
-       2,     2,     1,     1,     0,     2,     1,     3,     3,     3,
-       2,     3,     3,     1,     1
+       0,     2,     1,     0,     2,     2,     2,     4,     2,     4,
+       4,     3,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     3,     2,     3,     2,     3,
+       2,     0,     2,     2,     2,     2,     2,     2,     3,     4,
+       4,     4,     5,     3,     0,     3,     0,     2,     2,     2,
+       1,     3,     0,     2,     2,     2,     2,     2,     4,     3,
+       2,     4,     0,     2,     3,     1,     3,     0,     2,     2,
+       2,     3,     2,     1,     3,     0,     2,     2,     2,     3,
+       3,     2,     2,     2,     0,     2,     2,     2,     4,     3,
+       3,     0,     2,     1,     1,     2,     2,     2,     1,     2,
+       0,     2,     1,     3,     3,     3,     2,     3,     3,     1,
+       1
 };
 };
 
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -517,169 +575,167 @@ static const unsigned char yyr2[] =
    means the default is an error.  */
    means the default is an error.  */
 static const unsigned char yydefact[] =
 static const unsigned char yydefact[] =
 {
 {
-       2,     0,     1,     0,     0,     0,     8,     0,     0,    10,
-       0,     0,     0,     0,     9,    93,    92,     3,     4,    22,
-      14,    22,    15,    43,    53,     5,    59,    12,    79,    68,
-       6,    74,    16,    79,    13,    17,    11,    87,    88,     0,
-       0,     0,    38,     0,     0,     0,   103,   104,     0,     0,
-       0,    96,    19,    21,    39,    42,    58,    64,     0,    76,
-       7,    63,    73,    75,    18,    20,     0,   100,    55,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    85,     0,
-      85,     0,    85,    85,    85,    26,     0,     0,    23,     0,
-      25,    24,     0,     0,     0,    85,    85,    47,    44,    46,
-      45,     0,     0,     0,    54,    41,    40,    60,    62,    57,
-      61,    56,    81,    80,     0,    69,    71,    66,    70,    65,
-      99,   101,   102,    98,    97,    77,     0,     0,     0,    94,
-      94,     0,    94,    94,     0,    94,     0,     0,     0,    94,
-       0,    78,    51,    94,    94,     0,     0,    89,    90,    91,
-      72,     0,    83,    84,     0,     0,     0,    27,    86,     0,
-      29,     0,    33,    31,    32,     0,    94,     0,     0,    49,
-      50,    82,    95,    34,    35,    28,    30,    36,     0,    48,
-      52,    37
+       3,     0,     0,     1,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    12,    16,    13,    14,
+      18,    15,    17,     0,    19,     0,     4,    31,    22,    31,
+      23,    52,    62,     5,    67,    20,    84,    75,     6,    24,
+      84,    21,     8,    11,    93,    94,     0,     0,    95,     0,
+      48,    96,     0,     0,     0,   109,   110,     0,     0,     0,
+     102,    97,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    98,     7,    71,    79,    80,    27,    29,     0,
+     106,     0,     0,    64,     0,     0,     9,    10,     0,     0,
+       0,     0,     0,    91,     0,     0,     0,    44,     0,    37,
+      36,    32,    33,     0,    35,    34,     0,     0,    91,     0,
+      56,    57,    53,    55,    54,    63,    51,    50,    68,    70,
+      66,    69,    65,    86,    87,    85,    76,    78,    74,    77,
+      73,    99,   105,   107,   108,   104,   103,    26,    82,     0,
+       0,     0,   100,     0,   100,   100,   100,     0,     0,     0,
+      83,    60,   100,     0,   100,     0,    89,    90,     0,     0,
+      38,    92,     0,     0,   100,    46,    43,    25,     0,    59,
+       0,    88,   101,    39,    40,    41,     0,     0,    45,    58,
+      61,    42,    47
 };
 };
 
 
 /* YYDEFGOTO[NTERM-NUM]. */
 /* YYDEFGOTO[NTERM-NUM]. */
-static const short yydefgoto[] =
+static const short int yydefgoto[] =
 {
 {
-      -1,     1,    17,    18,    19,    20,    21,    22,    52,    88,
-      23,    24,   105,    25,    54,    98,    55,    26,   109,    27,
-      56,    28,    29,   117,    30,    58,    31,    32,    33,    34,
-      89,    90,    57,    91,   131,   132,   106,    35,   155,    50,
-      51
+      -1,     1,     2,    25,    26,   100,    27,    28,    29,    30,
+      64,   101,   102,   148,   178,    31,    32,   116,    33,    66,
+     112,    67,    34,   120,    35,    68,    36,    37,   128,    38,
+      70,    39,    40,    41,   103,   104,    69,   105,   143,   144,
+      42,    73,   159,    59,    60
 };
 };
 
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
    STATE-NUM.  */
-#define YYPACT_NINF -99
-static const short yypact[] =
+#define YYPACT_NINF -135
+static const short int yypact[] =
 {
 {
-     -99,    48,   -99,    38,    46,    46,   -99,    46,   -29,   -99,
-      46,   -17,    -3,   -11,   -99,   -99,   -99,   -99,   -99,   -99,
-     -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,
-     -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,    38,
-      12,    15,   -99,    18,    51,    62,   -99,   -99,   -11,   -11,
-       4,   -24,   138,   138,   160,   121,   110,    -4,    81,    -4,
-     -99,   -99,   -99,   -99,   -99,   -99,   -19,   -99,   -99,   -11,
-     -11,    70,    70,    73,    32,   -11,    46,   -11,    46,   -11,
-      46,   -11,    46,    46,    46,   -99,    36,    70,   -99,    95,
-     -99,   -99,    96,    46,   106,    46,    46,   -99,   -99,   -99,
-     -99,    38,    38,    38,   -99,   -99,   -99,   -99,   -99,   -99,
-     -99,   -99,   -99,   -99,   112,   -99,   -99,   -99,   -99,   -99,
-     -99,   117,   -99,   -99,   -99,   -99,   -11,    33,    65,   131,
-       1,   119,   131,     1,   136,     1,   153,   154,   155,   131,
-      70,   -99,   -99,   131,   131,   156,   157,   -99,   -99,   -99,
-     -99,   101,   -99,   -99,   -11,   158,   159,   -99,   -99,   161,
-     -99,   162,   -99,   -99,   -99,   163,   131,   164,   165,   -99,
-     -99,   -99,    99,   -99,   -99,   -99,   -99,   -99,   166,   -99,
-     -99,   -99
+    -135,     2,   170,  -135,   -14,    56,    56,    -8,    56,    24,
+      67,    56,     7,    14,    62,    97,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,   156,  -135,   166,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,   138,   151,  -135,   152,
+    -135,  -135,   163,   167,   176,  -135,  -135,    62,    62,   185,
+     -19,  -135,   188,   190,    42,   103,   194,    85,    70,   222,
+      70,   132,  -135,   191,  -135,  -135,  -135,  -135,  -135,   127,
+    -135,    62,    62,   191,   104,   104,  -135,  -135,   193,   203,
+       9,    62,    56,    56,    62,   161,   104,  -135,   196,  -135,
+    -135,  -135,  -135,   233,  -135,  -135,   204,    56,    56,   221,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,   219,  -135,  -135,  -135,  -135,  -135,    62,
+     209,   212,   240,   224,   240,    -1,   240,   104,    41,   225,
+    -135,  -135,   240,   226,   240,   218,  -135,  -135,    62,   227,
+    -135,  -135,   228,   229,   240,   230,  -135,  -135,   231,  -135,
+     232,  -135,   112,  -135,  -135,  -135,   234,    56,  -135,  -135,
+    -135,  -135,  -135
 };
 };
 
 
 /* YYPGOTO[NTERM-NUM].  */
 /* YYPGOTO[NTERM-NUM].  */
-static const short yypgoto[] =
+static const short int yypgoto[] =
 {
 {
-     -99,   -99,   -99,   111,   -99,   -99,   -99,   -99,   178,   -99,
-     -99,   -99,   -99,    91,   -99,   -99,   -99,   -99,   -99,   -99,
-     -99,   -99,   -99,   -99,   115,   -99,   -99,   -99,   -99,   -99,
-     -99,   146,   168,    89,    27,     0,   126,    -1,   -98,   -48,
-     -63
+    -135,  -135,  -135,  -135,    94,   -45,  -135,  -135,  -135,  -135,
+     237,  -135,  -135,  -135,  -135,  -135,  -135,  -135,   -54,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,     1,
+    -135,  -135,  -135,  -135,  -135,   195,   235,   -44,   159,    -5,
+      98,   210,  -134,   -53,   -77
 };
 };
 
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -68
-static const short yytable[] =
+#define YYTABLE_NINF -82
+static const short int yytable[] =
 {
 {
-      66,    67,    36,    42,    39,    40,    71,    41,   123,   124,
-      43,    44,    74,    75,   120,   154,    72,    46,    47,    69,
-      70,   121,   122,    48,   140,    45,   127,   128,   112,   130,
-      49,   133,   156,   135,   158,   159,    68,   161,    60,    69,
-      70,   165,    69,    70,    61,   167,   168,    62,     2,     3,
-      63,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-      46,    47,    13,    14,   139,   152,    48,   126,   178,    15,
-      16,    69,    70,    49,    37,    38,   129,   166,   151,    15,
-      16,   -67,   114,    64,   -67,     5,   101,     7,     8,   102,
-      10,    11,    12,   143,    65,    13,   103,   153,    46,    47,
-     147,   148,   149,    69,    70,   125,   172,   134,   141,   136,
-     137,   138,    15,    16,     5,   101,     7,     8,   102,    10,
-      11,    12,   145,   146,    13,   103,   101,     7,   142,   102,
-      10,    11,    12,   171,   144,    13,   103,    69,    70,    69,
-      70,    15,    16,   100,   150,   154,   113,   108,   113,   116,
-      73,   157,    15,    16,    74,    75,    70,    76,    77,    78,
-      79,    80,    81,    82,    83,    84,   104,   107,   160,   115,
-      85,   110,    73,   118,    86,    87,    74,    75,    92,    93,
-      94,    95,   111,    96,   119,   162,   163,   164,   169,   170,
-     173,   174,    97,   175,   176,   177,   179,   180,   181,    53,
-      99,    59
+      46,    47,     3,    49,    79,    80,    52,   135,   136,    84,
+     161,   162,   163,   158,   119,    85,   127,    43,   168,   147,
+     170,   111,   114,    48,   124,   125,   124,   125,   133,   134,
+     176,    81,    82,    53,   139,    55,    56,   140,   141,    57,
+      54,   145,   -28,    88,    58,   -28,   -28,   -28,   -28,   -28,
+     -28,   -28,   -28,   -28,    89,    50,   -28,   -28,    90,    91,
+     -28,    92,    93,    94,    95,    96,    97,   165,    98,   121,
+     164,   129,   166,    99,     6,     7,     8,     9,    10,    11,
+      12,    13,    44,    45,    14,    15,   155,   142,    55,    56,
+       7,     8,    57,    10,    11,    12,    13,    58,    51,    14,
+      15,    24,   152,   -30,    88,   172,   -30,   -30,   -30,   -30,
+     -30,   -30,   -30,   -30,   -30,    89,    24,   -30,   -30,    90,
+      91,   -30,    92,    93,    94,    95,    96,    97,    61,    98,
+      55,    56,   -81,    88,    99,   -81,   -81,   -81,   -81,   -81,
+     -81,   -81,   -81,   -81,    81,    82,   -81,   -81,    90,    91,
+     -81,   -81,   -81,   -81,   -81,   -81,   132,    62,    98,    81,
+      82,   115,   118,   123,   126,   117,   122,    63,   130,    72,
+      -2,     4,   182,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    74,    75,    14,    15,    16,   146,    17,    18,
+      19,    20,    21,    22,    76,    88,    23,   149,    77,   -49,
+     -49,    24,   -49,   -49,   -49,   -49,    89,    78,   -49,   -49,
+      90,    91,   106,   107,   108,   109,    72,    81,    82,    86,
+      98,    87,   131,    88,   137,   110,   -72,   -72,   -72,   -72,
+     -72,   -72,   -72,   -72,   138,   151,   -72,   -72,    90,    91,
+     156,    81,    82,   157,    81,    82,   150,   154,    98,   171,
+      81,    82,    82,   123,   158,   160,   167,   169,   173,   174,
+     175,   113,   179,   180,   177,   181,    65,   153,     0,    83,
+       0,     0,     0,     0,     0,    71
 };
 };
 
 
-static const unsigned char yycheck[] =
+static const short int yycheck[] =
 {
 {
-      48,    49,     3,    32,     4,     5,    30,     7,    71,    72,
-      10,    28,    16,    17,    33,    14,    40,    28,    29,    38,
-      39,    69,    70,    34,    87,    28,    74,    75,    32,    77,
-      41,    79,   130,    81,   132,   133,    32,   135,    39,    38,
-      39,   139,    38,    39,    32,   143,   144,    32,     0,     1,
-      32,     3,     4,     5,     6,     7,     8,     9,    10,    11,
-      28,    29,    14,    15,    28,    32,    34,    35,   166,    31,
-      32,    38,    39,    41,    28,    29,    76,   140,   126,    31,
-      32,     0,     1,    32,     3,     4,     5,     6,     7,     8,
-       9,    10,    11,    93,    32,    14,    15,    32,    28,    29,
-     101,   102,   103,    38,    39,    32,   154,    80,    13,    82,
-      83,    84,    31,    32,     4,     5,     6,     7,     8,     9,
-      10,    11,    95,    96,    14,    15,     5,     6,    32,     8,
-       9,    10,    11,    32,    28,    14,    15,    38,    39,    38,
-      39,    31,    32,    54,    32,    14,    57,    56,    59,    58,
-      12,    32,    31,    32,    16,    17,    39,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    55,    56,    32,    58,
-      32,    56,    12,    58,    36,    37,    16,    17,    18,    19,
-      20,    21,    56,    23,    58,    32,    32,    32,    32,    32,
-      32,    32,    32,    32,    32,    32,    32,    32,    32,    21,
-      54,    33
+       5,     6,     0,     8,    57,    58,    11,    84,    85,    28,
+     144,   145,   146,    14,    68,    34,    70,    31,   152,    96,
+     154,    66,    66,    31,    69,    69,    71,    71,    81,    82,
+     164,    32,    33,    26,    25,    26,    27,    90,    91,    30,
+      26,    94,     0,     1,    35,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    31,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    26,    26,    68,
+     147,    70,    31,    31,     4,     5,     6,     7,     8,     9,
+      10,    11,    26,    27,    14,    15,   139,    92,    26,    27,
+       5,     6,    30,     8,     9,    10,    11,    35,    31,    14,
+      15,    31,   107,     0,     1,   158,     3,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    31,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    31,    26,
+      26,    27,     0,     1,    31,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    32,    33,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    29,     1,    26,    32,
+      33,    67,    68,    31,    70,    67,    68,     1,    70,    31,
+       0,     1,   177,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    31,    31,    14,    15,    16,    26,    18,    19,
+      20,    21,    22,    23,    31,     1,    26,     1,    31,     5,
+       6,    31,     8,     9,    10,    11,    12,    31,    14,    15,
+      16,    17,    18,    19,    20,    21,    31,    32,    33,    31,
+      26,    31,    31,     1,    31,    31,     4,     5,     6,     7,
+       8,     9,    10,    11,    31,    31,    14,    15,    16,    17,
+      31,    32,    33,    31,    32,    33,    13,    26,    26,    31,
+      32,    33,    33,    31,    14,    31,    31,    31,    31,    31,
+      31,    66,    31,    31,    34,    31,    29,   108,    -1,    59,
+      -1,    -1,    -1,    -1,    -1,    40
 };
 };
 
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
    symbol of state STATE-NUM.  */
 static const unsigned char yystos[] =
 static const unsigned char yystos[] =
 {
 {
-       0,    43,     0,     1,     3,     4,     5,     6,     7,     8,
-       9,    10,    11,    14,    15,    31,    32,    44,    45,    46,
-      47,    48,    49,    52,    53,    55,    59,    61,    63,    64,
-      66,    68,    69,    70,    71,    79,    79,    28,    29,    77,
-      77,    77,    32,    77,    28,    28,    28,    29,    34,    41,
-      81,    82,    50,    50,    56,    58,    62,    74,    67,    74,
-      79,    32,    32,    32,    32,    32,    81,    81,    32,    38,
-      39,    30,    40,    12,    16,    17,    19,    20,    21,    22,
-      23,    24,    25,    26,    27,    32,    36,    37,    51,    72,
-      73,    75,    18,    19,    20,    21,    23,    32,    57,    73,
-      75,     5,     8,    15,    45,    54,    78,    45,    55,    60,
-      66,    78,    32,    75,     1,    45,    55,    65,    66,    78,
-      33,    81,    81,    82,    82,    32,    35,    81,    81,    77,
-      81,    76,    77,    81,    76,    81,    76,    76,    76,    28,
-      82,    13,    32,    77,    28,    76,    76,    79,    79,    79,
-      32,    81,    32,    32,    14,    80,    80,    32,    80,    80,
-      32,    80,    32,    32,    32,    80,    82,    80,    80,    32,
-      32,    32,    81,    32,    32,    32,    32,    32,    80,    32,
-      32,    32
+       0,    37,    38,     0,     1,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    14,    15,    16,    18,    19,    20,
+      21,    22,    23,    26,    31,    39,    40,    42,    43,    44,
+      45,    51,    52,    54,    58,    60,    62,    63,    65,    67,
+      68,    69,    76,    31,    26,    27,    75,    75,    31,    75,
+      31,    31,    75,    26,    26,    26,    27,    30,    35,    79,
+      80,    31,     1,     1,    46,    46,    55,    57,    61,    72,
+      66,    72,    31,    77,    31,    31,    31,    31,    31,    79,
+      79,    32,    33,    77,    28,    34,    31,    31,     1,    12,
+      16,    17,    19,    20,    21,    22,    23,    24,    26,    31,
+      41,    47,    48,    70,    71,    73,    18,    19,    20,    21,
+      31,    41,    56,    71,    73,    40,    53,    76,    40,    54,
+      59,    65,    76,    31,    41,    73,    40,    54,    64,    65,
+      76,    31,    29,    79,    79,    80,    80,    31,    31,    25,
+      79,    79,    75,    74,    75,    79,    26,    80,    49,     1,
+      13,    31,    75,    74,    26,    79,    31,    31,    14,    78,
+      31,    78,    78,    78,    80,    26,    31,    31,    78,    31,
+      78,    31,    79,    31,    31,    31,    78,    34,    50,    31,
+      31,    31,    75
 };
 };
 
 
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
 #define yyerrok		(yyerrstatus = 0)
 #define yyerrok		(yyerrstatus = 0)
 #define yyclearin	(yychar = YYEMPTY)
 #define yyclearin	(yychar = YYEMPTY)
 #define YYEMPTY		(-2)
 #define YYEMPTY		(-2)
@@ -687,7 +743,7 @@ static const unsigned char yystos[] =
 
 
 #define YYACCEPT	goto yyacceptlab
 #define YYACCEPT	goto yyacceptlab
 #define YYABORT		goto yyabortlab
 #define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrlab1
+#define YYERROR		goto yyerrorlab
 
 
 
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
 /* Like YYERROR except do call yyerror.  This remains here temporarily
@@ -709,26 +765,59 @@ do								\
       goto yybackup;						\
       goto yybackup;						\
     }								\
     }								\
   else								\
   else								\
-    { 								\
-      yyerror ("syntax error: cannot back up");\
+    {								\
+      yyerror (YY_("syntax error: cannot back up")); \
       YYERROR;							\
       YYERROR;							\
     }								\
     }								\
 while (0)
 while (0)
 
 
+
 #define YYTERROR	1
 #define YYTERROR	1
 #define YYERRCODE	256
 #define YYERRCODE	256
 
 
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions
-   are run).  */
 
 
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
 #ifndef YYLLOC_DEFAULT
 #ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)         \
-  Current.first_line   = Rhs[1].first_line;      \
-  Current.first_column = Rhs[1].first_column;    \
-  Current.last_line    = Rhs[N].last_line;       \
-  Current.last_column  = Rhs[N].last_column;
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (N)								\
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (0)
 #endif
 #endif
 
 
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+              (Loc).first_line, (Loc).first_column,	\
+              (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
 /* YYLEX -- calling `yylex' with the right arguments.  */
 /* YYLEX -- calling `yylex' with the right arguments.  */
 
 
 #ifdef YYLEX_PARAM
 #ifdef YYLEX_PARAM
@@ -751,36 +840,30 @@ do {						\
     YYFPRINTF Args;				\
     YYFPRINTF Args;				\
 } while (0)
 } while (0)
 
 
-# define YYDSYMPRINT(Args)			\
-do {						\
-  if (yydebug)					\
-    yysymprint Args;				\
-} while (0)
-
-# define YYDSYMPRINTF(Title, Token, Value, Location)		\
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)		\
 do {								\
 do {								\
   if (yydebug)							\
   if (yydebug)							\
     {								\
     {								\
       YYFPRINTF (stderr, "%s ", Title);				\
       YYFPRINTF (stderr, "%s ", Title);				\
-      yysymprint (stderr, 					\
-                  Token, Value);	\
+      yysymprint (stderr,					\
+                  Type, Value);	\
       YYFPRINTF (stderr, "\n");					\
       YYFPRINTF (stderr, "\n");					\
     }								\
     }								\
 } while (0)
 } while (0)
 
 
 /*------------------------------------------------------------------.
 /*------------------------------------------------------------------.
 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (cinluded).                                                   |
+| TOP (included).                                                   |
 `------------------------------------------------------------------*/
 `------------------------------------------------------------------*/
 
 
 #if defined (__STDC__) || defined (__cplusplus)
 #if defined (__STDC__) || defined (__cplusplus)
 static void
 static void
-yy_stack_print (short *bottom, short *top)
+yy_stack_print (short int *bottom, short int *top)
 #else
 #else
 static void
 static void
 yy_stack_print (bottom, top)
 yy_stack_print (bottom, top)
-    short *bottom;
-    short *top;
+    short int *bottom;
+    short int *top;
 #endif
 #endif
 {
 {
   YYFPRINTF (stderr, "Stack now");
   YYFPRINTF (stderr, "Stack now");
@@ -810,13 +893,13 @@ yy_reduce_print (yyrule)
 #endif
 #endif
 {
 {
   int yyi;
   int yyi;
-  unsigned int yylineno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
-             yyrule - 1, yylineno);
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ",
+             yyrule - 1, yylno);
   /* Print the symbols being reduced, and their result.  */
   /* Print the symbols being reduced, and their result.  */
   for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
   for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
-    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
-  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+    YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+  YYFPRINTF (stderr, "-> %s\n", yytname[yyr1[yyrule]]);
 }
 }
 
 
 # define YY_REDUCE_PRINT(Rule)		\
 # define YY_REDUCE_PRINT(Rule)		\
@@ -830,8 +913,7 @@ do {					\
 int yydebug;
 int yydebug;
 #else /* !YYDEBUG */
 #else /* !YYDEBUG */
 # define YYDPRINTF(Args)
 # define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
 # define YY_STACK_PRINT(Bottom, Top)
 # define YY_STACK_PRINT(Bottom, Top)
 # define YY_REDUCE_PRINT(Rule)
 # define YY_REDUCE_PRINT(Rule)
 #endif /* !YYDEBUG */
 #endif /* !YYDEBUG */
@@ -846,13 +928,9 @@ int yydebug;
    if the built-in stack extension method is used).
    if the built-in stack extension method is used).
 
 
    Do not make this value too large; the results are undefined if
    Do not make this value too large; the results are undefined if
-   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
    evaluated with infinite-precision integer arithmetic.  */
    evaluated with infinite-precision integer arithmetic.  */
 
 
-#if YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
 #ifndef YYMAXDEPTH
 #ifndef YYMAXDEPTH
 # define YYMAXDEPTH 10000
 # define YYMAXDEPTH 10000
 #endif
 #endif
@@ -874,7 +952,7 @@ yystrlen (yystr)
      const char *yystr;
      const char *yystr;
 #   endif
 #   endif
 {
 {
-  register const char *yys = yystr;
+  const char *yys = yystr;
 
 
   while (*yys++ != '\0')
   while (*yys++ != '\0')
     continue;
     continue;
@@ -899,8 +977,8 @@ yystpcpy (yydest, yysrc)
      const char *yysrc;
      const char *yysrc;
 #   endif
 #   endif
 {
 {
-  register char *yyd = yydest;
-  register const char *yys = yysrc;
+  char *yyd = yydest;
+  const char *yys = yysrc;
 
 
   while ((*yyd++ = *yys++) != '\0')
   while ((*yyd++ = *yys++) != '\0')
     continue;
     continue;
@@ -910,7 +988,55 @@ yystpcpy (yydest, yysrc)
 #  endif
 #  endif
 # endif
 # endif
 
 
-#endif /* !YYERROR_VERBOSE */
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      size_t yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+#endif /* YYERROR_VERBOSE */
 
 
 
 
 
 
@@ -934,15 +1060,15 @@ yysymprint (yyoutput, yytype, yyvaluep)
   (void) yyvaluep;
   (void) yyvaluep;
 
 
   if (yytype < YYNTOKENS)
   if (yytype < YYNTOKENS)
-    {
-      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
-      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
-    }
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
   else
   else
     YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
     YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
 
 
+
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
   switch (yytype)
   switch (yytype)
     {
     {
       default:
       default:
@@ -958,10 +1084,11 @@ yysymprint (yyoutput, yytype, yyvaluep)
 
 
 #if defined (__STDC__) || defined (__cplusplus)
 #if defined (__STDC__) || defined (__cplusplus)
 static void
 static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
 #else
 #else
 static void
 static void
-yydestruct (yytype, yyvaluep)
+yydestruct (yymsg, yytype, yyvaluep)
+    const char *yymsg;
     int yytype;
     int yytype;
     YYSTYPE *yyvaluep;
     YYSTYPE *yyvaluep;
 #endif
 #endif
@@ -969,8 +1096,42 @@ yydestruct (yytype, yyvaluep)
   /* Pacify ``unused variable'' warnings.  */
   /* Pacify ``unused variable'' warnings.  */
   (void) yyvaluep;
   (void) yyvaluep;
 
 
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
   switch (yytype)
   switch (yytype)
     {
     {
+      case 52: /* "choice_entry" */
+
+        {
+	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+		(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
+	if (current_menu == (yyvaluep->menu))
+		menu_end_menu();
+};
+
+        break;
+      case 58: /* "if_entry" */
+
+        {
+	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+		(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
+	if (current_menu == (yyvaluep->menu))
+		menu_end_menu();
+};
+
+        break;
+      case 63: /* "menu_entry" */
+
+        {
+	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+		(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
+	if (current_menu == (yyvaluep->menu))
+		menu_end_menu();
+};
+
+        break;
 
 
       default:
       default:
         break;
         break;
@@ -996,10 +1157,10 @@ int yyparse ();
 
 
 
 
 
 
-/* The lookahead symbol.  */
+/* The look-ahead symbol.  */
 int yychar;
 int yychar;
 
 
-/* The semantic value of the lookahead symbol.  */
+/* The semantic value of the look-ahead symbol.  */
 YYSTYPE yylval;
 YYSTYPE yylval;
 
 
 /* Number of syntax errors so far.  */
 /* Number of syntax errors so far.  */
@@ -1025,17 +1186,17 @@ yyparse (void)
 #else
 #else
 int
 int
 yyparse ()
 yyparse ()
-
+    ;
 #endif
 #endif
 #endif
 #endif
 {
 {
   
   
-  register int yystate;
-  register int yyn;
+  int yystate;
+  int yyn;
   int yyresult;
   int yyresult;
   /* Number of tokens to shift before error messages enabled.  */
   /* Number of tokens to shift before error messages enabled.  */
   int yyerrstatus;
   int yyerrstatus;
-  /* Lookahead token as an internal (translated) token number.  */
+  /* Look-ahead token as an internal (translated) token number.  */
   int yytoken = 0;
   int yytoken = 0;
 
 
   /* Three stacks and their tools:
   /* Three stacks and their tools:
@@ -1047,14 +1208,14 @@ yyparse ()
      to reallocate them elsewhere.  */
      to reallocate them elsewhere.  */
 
 
   /* The state stack.  */
   /* The state stack.  */
-  short	yyssa[YYINITDEPTH];
-  short *yyss = yyssa;
-  register short *yyssp;
+  short int yyssa[YYINITDEPTH];
+  short int *yyss = yyssa;
+  short int *yyssp;
 
 
   /* The semantic value stack.  */
   /* The semantic value stack.  */
   YYSTYPE yyvsa[YYINITDEPTH];
   YYSTYPE yyvsa[YYINITDEPTH];
   YYSTYPE *yyvs = yyvsa;
   YYSTYPE *yyvs = yyvsa;
-  register YYSTYPE *yyvsp;
+  YYSTYPE *yyvsp;
 
 
 
 
 
 
@@ -1111,14 +1272,14 @@ yyparse ()
 	   these so that the &'s don't force the real ones into
 	   these so that the &'s don't force the real ones into
 	   memory.  */
 	   memory.  */
 	YYSTYPE *yyvs1 = yyvs;
 	YYSTYPE *yyvs1 = yyvs;
-	short *yyss1 = yyss;
+	short int *yyss1 = yyss;
 
 
 
 
 	/* Each stack pointer address is followed by the size of the
 	/* Each stack pointer address is followed by the size of the
 	   data in use in that stack, in bytes.  This used to be a
 	   data in use in that stack, in bytes.  This used to be a
 	   conditional around just the two extra args, but that might
 	   conditional around just the two extra args, but that might
 	   be undefined if yyoverflow is a macro.  */
 	   be undefined if yyoverflow is a macro.  */
-	yyoverflow ("parser stack overflow",
+	yyoverflow (YY_("memory exhausted"),
 		    &yyss1, yysize * sizeof (*yyssp),
 		    &yyss1, yysize * sizeof (*yyssp),
 		    &yyvs1, yysize * sizeof (*yyvsp),
 		    &yyvs1, yysize * sizeof (*yyvsp),
 
 
@@ -1129,21 +1290,21 @@ yyparse ()
       }
       }
 #else /* no yyoverflow */
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
 # ifndef YYSTACK_RELOCATE
-      goto yyoverflowlab;
+      goto yyexhaustedlab;
 # else
 # else
       /* Extend the stack our own way.  */
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
       if (YYMAXDEPTH <= yystacksize)
-	goto yyoverflowlab;
+	goto yyexhaustedlab;
       yystacksize *= 2;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
       if (YYMAXDEPTH < yystacksize)
 	yystacksize = YYMAXDEPTH;
 	yystacksize = YYMAXDEPTH;
 
 
       {
       {
-	short *yyss1 = yyss;
+	short int *yyss1 = yyss;
 	union yyalloc *yyptr =
 	union yyalloc *yyptr =
 	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
 	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
 	if (! yyptr)
 	if (! yyptr)
-	  goto yyoverflowlab;
+	  goto yyexhaustedlab;
 	YYSTACK_RELOCATE (yyss);
 	YYSTACK_RELOCATE (yyss);
 	YYSTACK_RELOCATE (yyvs);
 	YYSTACK_RELOCATE (yyvs);
 
 
@@ -1175,18 +1336,18 @@ yyparse ()
 yybackup:
 yybackup:
 
 
 /* Do appropriate processing given the current state.  */
 /* Do appropriate processing given the current state.  */
-/* Read a lookahead token if we need one and don't already have one.  */
+/* Read a look-ahead token if we need one and don't already have one.  */
 /* yyresume: */
 /* yyresume: */
 
 
-  /* First try to decide what to do without reference to lookahead token.  */
+  /* First try to decide what to do without reference to look-ahead token.  */
 
 
   yyn = yypact[yystate];
   yyn = yypact[yystate];
   if (yyn == YYPACT_NINF)
   if (yyn == YYPACT_NINF)
     goto yydefault;
     goto yydefault;
 
 
-  /* Not known => get a lookahead token if don't already have one.  */
+  /* Not known => get a look-ahead token if don't already have one.  */
 
 
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
   if (yychar == YYEMPTY)
   if (yychar == YYEMPTY)
     {
     {
       YYDPRINTF ((stderr, "Reading a token: "));
       YYDPRINTF ((stderr, "Reading a token: "));
@@ -1201,7 +1362,7 @@ yybackup:
   else
   else
     {
     {
       yytoken = YYTRANSLATE (yychar);
       yytoken = YYTRANSLATE (yychar);
-      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
     }
     }
 
 
   /* If the proper action on seeing token YYTOKEN is to reduce or to
   /* If the proper action on seeing token YYTOKEN is to reduce or to
@@ -1221,8 +1382,8 @@ yybackup:
   if (yyn == YYFINAL)
   if (yyn == YYFINAL)
     YYACCEPT;
     YYACCEPT;
 
 
-  /* Shift the lookahead token.  */
-  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+  /* Shift the look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
 
   /* Discard the token being shifted unless it is eof.  */
   /* Discard the token being shifted unless it is eof.  */
   if (yychar != YYEOF)
   if (yychar != YYEOF)
@@ -1273,35 +1434,47 @@ yyreduce:
     {
     {
         case 8:
         case 8:
 
 
-    { zconfprint("unexpected 'endmenu' statement"); ;}
+    { zconf_error("unexpected end statement"); ;}
     break;
     break;
 
 
   case 9:
   case 9:
 
 
-    { zconfprint("unexpected 'endif' statement"); ;}
+    { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); ;}
     break;
     break;
 
 
   case 10:
   case 10:
 
 
-    { zconfprint("unexpected 'endchoice' statement"); ;}
+    {
+	zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name);
+;}
     break;
     break;
 
 
   case 11:
   case 11:
 
 
-    { zconfprint("syntax error"); yyerrok; ;}
+    { zconf_error("invalid statement"); ;}
     break;
     break;
 
 
-  case 18:
+  case 25:
+
+    { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); ;}
+    break;
+
+  case 26:
+
+    { zconf_error("invalid option"); ;}
+    break;
+
+  case 27:
 
 
     {
     {
-	struct symbol *sym = sym_lookup(yyvsp[-1].string, 0);
+	struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
 	sym->flags |= SYMBOL_OPTIONAL;
 	sym->flags |= SYMBOL_OPTIONAL;
 	menu_add_entry(sym);
 	menu_add_entry(sym);
-	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string);
+	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
 ;}
 ;}
     break;
     break;
 
 
-  case 19:
+  case 28:
 
 
     {
     {
 	menu_end_entry();
 	menu_end_entry();
@@ -1309,17 +1482,17 @@ yyreduce:
 ;}
 ;}
     break;
     break;
 
 
-  case 20:
+  case 29:
 
 
     {
     {
-	struct symbol *sym = sym_lookup(yyvsp[-1].string, 0);
+	struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
 	sym->flags |= SYMBOL_OPTIONAL;
 	sym->flags |= SYMBOL_OPTIONAL;
 	menu_add_entry(sym);
 	menu_add_entry(sym);
-	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string);
+	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
 ;}
 ;}
     break;
     break;
 
 
-  case 21:
+  case 30:
 
 
     {
     {
 	if (current_entry->prompt)
 	if (current_entry->prompt)
@@ -1331,97 +1504,75 @@ yyreduce:
 ;}
 ;}
     break;
     break;
 
 
-  case 27:
-
-    {
-	menu_set_type(S_TRISTATE);
-	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
-;}
-    break;
-
-  case 28:
-
-    {
-	menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr);
-	menu_set_type(S_TRISTATE);
-	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
-;}
-    break;
-
-  case 29:
-
-    {
-	menu_set_type(S_BOOLEAN);
-	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
-;}
-    break;
-
-  case 30:
+  case 38:
 
 
     {
     {
-	menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr);
-	menu_set_type(S_BOOLEAN);
-	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
+	menu_set_type((yyvsp[-2].id)->stype);
+	printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+		zconf_curname(), zconf_lineno(),
+		(yyvsp[-2].id)->stype);
 ;}
 ;}
     break;
     break;
 
 
-  case 31:
+  case 39:
 
 
     {
     {
-	menu_set_type(S_INT);
-	printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
+	menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
+	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 ;}
 ;}
     break;
     break;
 
 
-  case 32:
+  case 40:
 
 
     {
     {
-	menu_set_type(S_HEX);
-	printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
+	menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr));
+	if ((yyvsp[-3].id)->stype != S_UNKNOWN)
+		menu_set_type((yyvsp[-3].id)->stype);
+	printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
+		zconf_curname(), zconf_lineno(),
+		(yyvsp[-3].id)->stype);
 ;}
 ;}
     break;
     break;
 
 
-  case 33:
+  case 41:
 
 
     {
     {
-	menu_set_type(S_STRING);
-	printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
+	menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
+	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
 ;}
 ;}
     break;
     break;
 
 
-  case 34:
+  case 42:
 
 
     {
     {
-	menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr);
-	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr));
+	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
 ;}
 ;}
     break;
     break;
 
 
-  case 35:
+  case 45:
 
 
     {
     {
-	menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr);
-	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+	struct kconf_id *id = kconf_id_lookup((yyvsp[-1].string), strlen((yyvsp[-1].string)));
+	if (id && id->flags & TF_OPTION)
+		menu_add_option(id->token, (yyvsp[0].string));
+	else
+		zconfprint("warning: ignoring unknown option %s", (yyvsp[-1].string));
+	free((yyvsp[-1].string));
 ;}
 ;}
     break;
     break;
 
 
-  case 36:
+  case 46:
 
 
-    {
-	menu_add_symbol(P_SELECT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr);
-	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
-;}
+    { (yyval.string) = NULL; ;}
     break;
     break;
 
 
-  case 37:
+  case 47:
 
 
-    {
-	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,yyvsp[-3].symbol, yyvsp[-2].symbol), yyvsp[-1].expr);
-	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
-;}
+    { (yyval.string) = (yyvsp[0].string); ;}
     break;
     break;
 
 
-  case 38:
+  case 48:
 
 
     {
     {
 	struct symbol *sym = sym_lookup(NULL, 0);
 	struct symbol *sym = sym_lookup(NULL, 0);
@@ -1432,57 +1583,45 @@ yyreduce:
 ;}
 ;}
     break;
     break;
 
 
-  case 39:
+  case 49:
 
 
     {
     {
-	menu_end_entry();
-	menu_add_menu();
+	(yyval.menu) = menu_add_menu();
 ;}
 ;}
     break;
     break;
 
 
-  case 40:
+  case 50:
 
 
     {
     {
-	if (zconf_endtoken(yyvsp[0].token, T_CHOICE, T_ENDCHOICE)) {
+	if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) {
 		menu_end_menu();
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
 		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
 	}
 	}
 ;}
 ;}
     break;
     break;
 
 
-  case 42:
-
-    {
-	printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
-	zconfnerrs++;
-;}
-    break;
-
-  case 48:
+  case 58:
 
 
     {
     {
-	menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr);
+	menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 ;}
 ;}
     break;
     break;
 
 
-  case 49:
+  case 59:
 
 
     {
     {
-	menu_set_type(S_TRISTATE);
-	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
+	if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) {
+		menu_set_type((yyvsp[-2].id)->stype);
+		printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+			zconf_curname(), zconf_lineno(),
+			(yyvsp[-2].id)->stype);
+	} else
+		YYERROR;
 ;}
 ;}
     break;
     break;
 
 
-  case 50:
-
-    {
-	menu_set_type(S_BOOLEAN);
-	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
-;}
-    break;
-
-  case 51:
+  case 60:
 
 
     {
     {
 	current_entry->sym->flags |= SYMBOL_OPTIONAL;
 	current_entry->sym->flags |= SYMBOL_OPTIONAL;
@@ -1490,115 +1629,89 @@ yyreduce:
 ;}
 ;}
     break;
     break;
 
 
-  case 52:
+  case 61:
 
 
     {
     {
-	menu_add_symbol(P_DEFAULT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr);
-	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+	if ((yyvsp[-3].id)->stype == S_UNKNOWN) {
+		menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
+		printd(DEBUG_PARSE, "%s:%d:default\n",
+			zconf_curname(), zconf_lineno());
+	} else
+		YYERROR;
 ;}
 ;}
     break;
     break;
 
 
-  case 55:
+  case 64:
 
 
     {
     {
 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
 	menu_add_entry(NULL);
 	menu_add_entry(NULL);
-	menu_add_dep(yyvsp[-1].expr);
-	menu_end_entry();
-	menu_add_menu();
+	menu_add_dep((yyvsp[-1].expr));
+	(yyval.menu) = menu_add_menu();
 ;}
 ;}
     break;
     break;
 
 
-  case 56:
+  case 65:
 
 
     {
     {
-	if (zconf_endtoken(yyvsp[0].token, T_IF, T_ENDIF)) {
+	if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) {
 		menu_end_menu();
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
 		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
 	}
 	}
 ;}
 ;}
     break;
     break;
 
 
-  case 58:
-
-    {
-	printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
-	zconfnerrs++;
-;}
-    break;
-
-  case 63:
+  case 71:
 
 
     {
     {
 	menu_add_entry(NULL);
 	menu_add_entry(NULL);
-	menu_add_prop(P_MENU, yyvsp[-1].string, NULL, NULL);
+	menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 ;}
 ;}
     break;
     break;
 
 
-  case 64:
+  case 72:
 
 
     {
     {
-	menu_end_entry();
-	menu_add_menu();
+	(yyval.menu) = menu_add_menu();
 ;}
 ;}
     break;
     break;
 
 
-  case 65:
+  case 73:
 
 
     {
     {
-	if (zconf_endtoken(yyvsp[0].token, T_MENU, T_ENDMENU)) {
+	if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) {
 		menu_end_menu();
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
 		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
 	}
 	}
 ;}
 ;}
     break;
     break;
 
 
-  case 67:
-
-    {
-	printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
-	zconfnerrs++;
-;}
-    break;
-
-  case 72:
-
-    { zconfprint("invalid menu option"); yyerrok; ;}
-    break;
-
-  case 73:
-
-    {
-	yyval.string = yyvsp[-1].string;
-	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string);
-;}
-    break;
-
-  case 74:
+  case 79:
 
 
     {
     {
-	zconf_nextfile(yyvsp[0].string);
+	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
+	zconf_nextfile((yyvsp[-1].string));
 ;}
 ;}
     break;
     break;
 
 
-  case 75:
+  case 80:
 
 
     {
     {
 	menu_add_entry(NULL);
 	menu_add_entry(NULL);
-	menu_add_prop(P_COMMENT, yyvsp[-1].string, NULL, NULL);
+	menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL);
 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
 ;}
 ;}
     break;
     break;
 
 
-  case 76:
+  case 81:
 
 
     {
     {
 	menu_end_entry();
 	menu_end_entry();
 ;}
 ;}
     break;
     break;
 
 
-  case 77:
+  case 82:
 
 
     {
     {
 	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
@@ -1606,118 +1719,119 @@ yyreduce:
 ;}
 ;}
     break;
     break;
 
 
-  case 78:
+  case 83:
 
 
     {
     {
-	current_entry->sym->help = yyvsp[0].string;
+	current_entry->sym->help = (yyvsp[0].string);
 ;}
 ;}
     break;
     break;
 
 
-  case 82:
+  case 88:
 
 
     {
     {
-	menu_add_dep(yyvsp[-1].expr);
+	menu_add_dep((yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
 ;}
 ;}
     break;
     break;
 
 
-  case 83:
+  case 89:
 
 
     {
     {
-	menu_add_dep(yyvsp[-1].expr);
+	menu_add_dep((yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
 ;}
 ;}
     break;
     break;
 
 
-  case 84:
+  case 90:
 
 
     {
     {
-	menu_add_dep(yyvsp[-1].expr);
+	menu_add_dep((yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
 ;}
 ;}
     break;
     break;
 
 
-  case 86:
+  case 92:
 
 
     {
     {
-	menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr);
+	menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr));
 ;}
 ;}
     break;
     break;
 
 
-  case 89:
+  case 95:
 
 
-    { yyval.token = T_ENDMENU; ;}
+    { (yyval.id) = (yyvsp[-1].id); ;}
     break;
     break;
 
 
-  case 90:
+  case 96:
 
 
-    { yyval.token = T_ENDCHOICE; ;}
+    { (yyval.id) = (yyvsp[-1].id); ;}
     break;
     break;
 
 
-  case 91:
+  case 97:
 
 
-    { yyval.token = T_ENDIF; ;}
+    { (yyval.id) = (yyvsp[-1].id); ;}
     break;
     break;
 
 
-  case 94:
+  case 100:
 
 
-    { yyval.expr = NULL; ;}
+    { (yyval.expr) = NULL; ;}
     break;
     break;
 
 
-  case 95:
+  case 101:
 
 
-    { yyval.expr = yyvsp[0].expr; ;}
+    { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
     break;
 
 
-  case 96:
+  case 102:
 
 
-    { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); ;}
+    { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;}
     break;
     break;
 
 
-  case 97:
+  case 103:
 
 
-    { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;}
+    { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
     break;
     break;
 
 
-  case 98:
+  case 104:
 
 
-    { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;}
+    { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
     break;
     break;
 
 
-  case 99:
+  case 105:
 
 
-    { yyval.expr = yyvsp[-1].expr; ;}
+    { (yyval.expr) = (yyvsp[-1].expr); ;}
     break;
     break;
 
 
-  case 100:
+  case 106:
 
 
-    { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); ;}
+    { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;}
     break;
     break;
 
 
-  case 101:
+  case 107:
 
 
-    { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); ;}
+    { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
     break;
 
 
-  case 102:
+  case 108:
 
 
-    { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); ;}
+    { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
     break;
 
 
-  case 103:
+  case 109:
 
 
-    { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); ;}
+    { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;}
     break;
     break;
 
 
-  case 104:
+  case 110:
 
 
-    { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); ;}
+    { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;}
     break;
     break;
 
 
 
 
+      default: break;
     }
     }
 
 
-/* Line 999 of yacc.c.  */
+/* Line 1126 of yacc.c.  */
 
 
 
 
   yyvsp -= yylen;
   yyvsp -= yylen;
@@ -1757,87 +1871,152 @@ yyerrlab:
 
 
       if (YYPACT_NINF < yyn && yyn < YYLAST)
       if (YYPACT_NINF < yyn && yyn < YYLAST)
 	{
 	{
-	  YYSIZE_T yysize = 0;
 	  int yytype = YYTRANSLATE (yychar);
 	  int yytype = YYTRANSLATE (yychar);
-	  char *yymsg;
-	  int yyx, yycount;
+	  YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+	  YYSIZE_T yysize = yysize0;
+	  YYSIZE_T yysize1;
+	  int yysize_overflow = 0;
+	  char *yymsg = 0;
+#	  define YYERROR_VERBOSE_ARGS_MAXIMUM 5
+	  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+	  int yyx;
+
+#if 0
+	  /* This is so xgettext sees the translatable formats that are
+	     constructed on the fly.  */
+	  YY_("syntax error, unexpected %s");
+	  YY_("syntax error, unexpected %s, expecting %s");
+	  YY_("syntax error, unexpected %s, expecting %s or %s");
+	  YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+	  YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+#endif
+	  char *yyfmt;
+	  char const *yyf;
+	  static char const yyunexpected[] = "syntax error, unexpected %s";
+	  static char const yyexpecting[] = ", expecting %s";
+	  static char const yyor[] = " or %s";
+	  char yyformat[sizeof yyunexpected
+			+ sizeof yyexpecting - 1
+			+ ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+			   * (sizeof yyor - 1))];
+	  char const *yyprefix = yyexpecting;
 
 
-	  yycount = 0;
 	  /* Start YYX at -YYN if negative to avoid negative indexes in
 	  /* Start YYX at -YYN if negative to avoid negative indexes in
 	     YYCHECK.  */
 	     YYCHECK.  */
-	  for (yyx = yyn < 0 ? -yyn : 0;
-	       yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+	  int yyxbegin = yyn < 0 ? -yyn : 0;
+
+	  /* Stay within bounds of both yycheck and yytname.  */
+	  int yychecklim = YYLAST - yyn;
+	  int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+	  int yycount = 1;
+
+	  yyarg[0] = yytname[yytype];
+	  yyfmt = yystpcpy (yyformat, yyunexpected);
+
+	  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
 	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
 	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-	      yysize += yystrlen (yytname[yyx]) + 15, yycount++;
-	  yysize += yystrlen ("syntax error, unexpected ") + 1;
-	  yysize += yystrlen (yytname[yytype]);
-	  yymsg = (char *) YYSTACK_ALLOC (yysize);
-	  if (yymsg != 0)
+	      {
+		if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+		  {
+		    yycount = 1;
+		    yysize = yysize0;
+		    yyformat[sizeof yyunexpected - 1] = '\0';
+		    break;
+		  }
+		yyarg[yycount++] = yytname[yyx];
+		yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+		yysize_overflow |= yysize1 < yysize;
+		yysize = yysize1;
+		yyfmt = yystpcpy (yyfmt, yyprefix);
+		yyprefix = yyor;
+	      }
+
+	  yyf = YY_(yyformat);
+	  yysize1 = yysize + yystrlen (yyf);
+	  yysize_overflow |= yysize1 < yysize;
+	  yysize = yysize1;
+
+	  if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM)
+	    yymsg = (char *) YYSTACK_ALLOC (yysize);
+	  if (yymsg)
 	    {
 	    {
-	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
-	      yyp = yystpcpy (yyp, yytname[yytype]);
-
-	      if (yycount < 5)
+	      /* Avoid sprintf, as that infringes on the user's name space.
+		 Don't have undefined behavior even if the translation
+		 produced a string with the wrong number of "%s"s.  */
+	      char *yyp = yymsg;
+	      int yyi = 0;
+	      while ((*yyp = *yyf))
 		{
 		{
-		  yycount = 0;
-		  for (yyx = yyn < 0 ? -yyn : 0;
-		       yyx < (int) (sizeof (yytname) / sizeof (char *));
-		       yyx++)
-		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-		      {
-			const char *yyq = ! yycount ? ", expecting " : " or ";
-			yyp = yystpcpy (yyp, yyq);
-			yyp = yystpcpy (yyp, yytname[yyx]);
-			yycount++;
-		      }
+		  if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		    {
+		      yyp += yytnamerr (yyp, yyarg[yyi++]);
+		      yyf += 2;
+		    }
+		  else
+		    {
+		      yyp++;
+		      yyf++;
+		    }
 		}
 		}
 	      yyerror (yymsg);
 	      yyerror (yymsg);
 	      YYSTACK_FREE (yymsg);
 	      YYSTACK_FREE (yymsg);
 	    }
 	    }
 	  else
 	  else
-	    yyerror ("syntax error; also virtual memory exhausted");
+	    {
+	      yyerror (YY_("syntax error"));
+	      goto yyexhaustedlab;
+	    }
 	}
 	}
       else
       else
 #endif /* YYERROR_VERBOSE */
 #endif /* YYERROR_VERBOSE */
-	yyerror ("syntax error");
+	yyerror (YY_("syntax error"));
     }
     }
 
 
 
 
 
 
   if (yyerrstatus == 3)
   if (yyerrstatus == 3)
     {
     {
-      /* If just tried and failed to reuse lookahead token after an
+      /* If just tried and failed to reuse look-ahead token after an
 	 error, discard it.  */
 	 error, discard it.  */
 
 
-      /* Return failure if at end of input.  */
-      if (yychar == YYEOF)
+      if (yychar <= YYEOF)
         {
         {
-	  /* Pop the error token.  */
-          YYPOPSTACK;
-	  /* Pop the rest of the stack.  */
-	  while (yyss < yyssp)
-	    {
-	      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-	      yydestruct (yystos[*yyssp], yyvsp);
-	      YYPOPSTACK;
-	    }
-	  YYABORT;
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
         }
         }
-
-      YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
-      yydestruct (yytoken, &yylval);
-      yychar = YYEMPTY;
-
+      else
+	{
+	  yydestruct ("Error: discarding", yytoken, &yylval);
+	  yychar = YYEMPTY;
+	}
     }
     }
 
 
-  /* Else will try to reuse lookahead token after shifting the error
+  /* Else will try to reuse look-ahead token after shifting the error
      token.  */
      token.  */
   goto yyerrlab1;
   goto yyerrlab1;
 
 
 
 
-/*----------------------------------------------------.
-| yyerrlab1 -- error raised explicitly by an action.  |
-`----------------------------------------------------*/
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (0)
+     goto yyerrorlab;
+
+yyvsp -= yylen;
+  yyssp -= yylen;
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
 yyerrlab1:
 yyerrlab1:
   yyerrstatus = 3;	/* Each real token shifted decrements this.  */
   yyerrstatus = 3;	/* Each real token shifted decrements this.  */
 
 
@@ -1859,22 +2038,22 @@ yyerrlab1:
       if (yyssp == yyss)
       if (yyssp == yyss)
 	YYABORT;
 	YYABORT;
 
 
-      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-      yydestruct (yystos[yystate], yyvsp);
-      yyvsp--;
-      yystate = *--yyssp;
 
 
+      yydestruct ("Error: popping", yystos[yystate], yyvsp);
+      YYPOPSTACK;
+      yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
       YY_STACK_PRINT (yyss, yyssp);
     }
     }
 
 
   if (yyn == YYFINAL)
   if (yyn == YYFINAL)
     YYACCEPT;
     YYACCEPT;
 
 
-  YYDPRINTF ((stderr, "Shifting error token, "));
-
   *++yyvsp = yylval;
   *++yyvsp = yylval;
 
 
 
 
+  /* Shift the error token. */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
   yystate = yyn;
   yystate = yyn;
   goto yynewstate;
   goto yynewstate;
 
 
@@ -1894,16 +2073,25 @@ yyabortlab:
   goto yyreturn;
   goto yyreturn;
 
 
 #ifndef yyoverflow
 #ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here.  |
-`----------------------------------------------*/
-yyoverflowlab:
-  yyerror ("parser stack overflow");
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
   yyresult = 2;
   yyresult = 2;
   /* Fall through.  */
   /* Fall through.  */
 #endif
 #endif
 
 
 yyreturn:
 yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp);
+      YYPOPSTACK;
+    }
 #ifndef yyoverflow
 #ifndef yyoverflow
   if (yyss != yyssa)
   if (yyss != yyssa)
     YYSTACK_FREE (yyss);
     YYSTACK_FREE (yyss);
@@ -1924,22 +2112,30 @@ void conf_parse(const char *name)
 
 
 	sym_init();
 	sym_init();
 	menu_init();
 	menu_init();
-	modules_sym = sym_lookup("MODULES", 0);
-	rootmenu.prompt = menu_add_prop(P_MENU, "Buildroot Configuration", NULL, NULL);
+	modules_sym = sym_lookup(NULL, 0);
+	modules_sym->type = S_BOOLEAN;
+	modules_sym->flags |= SYMBOL_AUTO;
+	rootmenu.prompt = menu_add_prompt(P_MENU, "Buildroot Configuration", NULL);
 
 
-	//zconfdebug = 1;
+#if YYDEBUG
+	if (getenv("ZCONF_DEBUG"))
+		zconfdebug = 1;
+#endif
 	zconfparse();
 	zconfparse();
 	if (zconfnerrs)
 	if (zconfnerrs)
 		exit(1);
 		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));
+	}
 	menu_finalize(&rootmenu);
 	menu_finalize(&rootmenu);
 	for_all_symbols(i, sym) {
 	for_all_symbols(i, sym) {
-                if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym))
-                        printf("\n");
-		else
-			sym->flags |= SYMBOL_CHECK_DONE;
+		sym_check_deps(sym);
         }
         }
 
 
-	sym_change_count = 1;
+	sym_set_change_count(1);
 }
 }
 
 
 const char *zconf_tokenname(int token)
 const char *zconf_tokenname(int token)
@@ -1951,20 +2147,25 @@ const char *zconf_tokenname(int token)
 	case T_ENDCHOICE:	return "endchoice";
 	case T_ENDCHOICE:	return "endchoice";
 	case T_IF:		return "if";
 	case T_IF:		return "if";
 	case T_ENDIF:		return "endif";
 	case T_ENDIF:		return "endif";
+	case T_DEPENDS:		return "depends";
 	}
 	}
 	return "<token>";
 	return "<token>";
 }
 }
 
 
-static bool zconf_endtoken(int token, int starttoken, int endtoken)
+static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
 {
 {
-	if (token != endtoken) {
-		zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken));
+	if (id->token != endtoken) {
+		zconf_error("unexpected '%s' within %s block",
+			kconf_id_strings + id->name, zconf_tokenname(starttoken));
 		zconfnerrs++;
 		zconfnerrs++;
 		return false;
 		return false;
 	}
 	}
 	if (current_menu->file != current_file) {
 	if (current_menu->file != current_file) {
-		zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken));
-		zconfprint("location of the '%s'", zconf_tokenname(starttoken));
+		zconf_error("'%s' in different file than '%s'",
+			kconf_id_strings + id->name, zconf_tokenname(starttoken));
+		fprintf(stderr, "%s:%d: location of the '%s'\n",
+			current_menu->file->name, current_menu->lineno,
+			zconf_tokenname(starttoken));
 		zconfnerrs++;
 		zconfnerrs++;
 		return false;
 		return false;
 	}
 	}
@@ -1975,7 +2176,19 @@ static void zconfprint(const char *err, ...)
 {
 {
 	va_list ap;
 	va_list ap;
 
 
-	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1);
+	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+	va_start(ap, err);
+	vfprintf(stderr, err, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+}
+
+static void zconf_error(const char *err, ...)
+{
+	va_list ap;
+
+	zconfnerrs++;
+	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
 	va_start(ap, err);
 	va_start(ap, err);
 	vfprintf(stderr, err, ap);
 	vfprintf(stderr, err, ap);
 	va_end(ap);
 	va_end(ap);
@@ -1984,7 +2197,9 @@ static void zconfprint(const char *err, ...)
 
 
 static void zconferror(const char *err)
 static void zconferror(const char *err)
 {
 {
+#if YYDEBUG
 	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
 	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+#endif
 }
 }
 
 
 void print_quoted_string(FILE *out, const char *str)
 void print_quoted_string(FILE *out, const char *str)

+ 191 - 169
package/config/zconf.y

@@ -11,6 +11,11 @@
 #include <string.h>
 #include <string.h>
 #include <stdbool.h>
 #include <stdbool.h>
 
 
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#include "zconf.hash.c"
+
 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
 
 
 #define PRINTD		0x0001
 #define PRINTD		0x0001
@@ -20,61 +25,60 @@ int cdebug = PRINTD;
 
 
 extern int zconflex(void);
 extern int zconflex(void);
 static void zconfprint(const char *err, ...);
 static void zconfprint(const char *err, ...);
+static void zconf_error(const char *err, ...);
 static void zconferror(const char *err);
 static void zconferror(const char *err);
-static bool zconf_endtoken(int token, int starttoken, int endtoken);
+static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
 
 
 struct symbol *symbol_hash[257];
 struct symbol *symbol_hash[257];
 
 
 static struct menu *current_menu, *current_entry;
 static struct menu *current_menu, *current_entry;
 
 
+#define YYDEBUG 0
+#if YYDEBUG
 #define YYERROR_VERBOSE
 #define YYERROR_VERBOSE
+#endif
 %}
 %}
-%expect 40
+%expect 26
 
 
 %union
 %union
 {
 {
-	int token;
 	char *string;
 	char *string;
+	struct file *file;
 	struct symbol *symbol;
 	struct symbol *symbol;
 	struct expr *expr;
 	struct expr *expr;
 	struct menu *menu;
 	struct menu *menu;
+	struct kconf_id *id;
 }
 }
 
 
-%token T_MAINMENU
-%token T_MENU
-%token T_ENDMENU
-%token T_SOURCE
-%token T_CHOICE
-%token T_ENDCHOICE
-%token T_COMMENT
-%token T_CONFIG
-%token T_MENUCONFIG
-%token T_HELP
+%token <id>T_MAINMENU
+%token <id>T_MENU
+%token <id>T_ENDMENU
+%token <id>T_SOURCE
+%token <id>T_CHOICE
+%token <id>T_ENDCHOICE
+%token <id>T_COMMENT
+%token <id>T_CONFIG
+%token <id>T_MENUCONFIG
+%token <id>T_HELP
 %token <string> T_HELPTEXT
 %token <string> T_HELPTEXT
-%token T_IF
-%token T_ENDIF
-%token T_DEPENDS
-%token T_REQUIRES
-%token T_OPTIONAL
-%token T_PROMPT
-%token T_DEFAULT
-%token T_TRISTATE
-%token T_DEF_TRISTATE
-%token T_BOOLEAN
-%token T_DEF_BOOLEAN
-%token T_STRING
-%token T_INT
-%token T_HEX
+%token <id>T_IF
+%token <id>T_ENDIF
+%token <id>T_DEPENDS
+%token <id>T_REQUIRES
+%token <id>T_OPTIONAL
+%token <id>T_PROMPT
+%token <id>T_TYPE
+%token <id>T_DEFAULT
+%token <id>T_SELECT
+%token <id>T_RANGE
+%token <id>T_OPTION
+%token <id>T_ON
 %token <string> T_WORD
 %token <string> T_WORD
 %token <string> T_WORD_QUOTE
 %token <string> T_WORD_QUOTE
 %token T_UNEQUAL
 %token T_UNEQUAL
-%token T_EOF
-%token T_EOL
 %token T_CLOSE_PAREN
 %token T_CLOSE_PAREN
 %token T_OPEN_PAREN
 %token T_OPEN_PAREN
-%token T_ON
-%token T_SELECT
-%token T_RANGE
+%token T_EOL
 
 
 %left T_OR
 %left T_OR
 %left T_AND
 %left T_AND
@@ -82,38 +86,55 @@ static struct menu *current_menu, *current_entry;
 %nonassoc T_NOT
 %nonassoc T_NOT
 
 
 %type <string> prompt
 %type <string> prompt
-%type <string> source
 %type <symbol> symbol
 %type <symbol> symbol
 %type <expr> expr
 %type <expr> expr
 %type <expr> if_expr
 %type <expr> if_expr
-%type <token> end
+%type <id> end
+%type <id> option_name
+%type <menu> if_entry menu_entry choice_entry
+%type <string> symbol_option_arg
+
+%destructor {
+	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+		$$->file->name, $$->lineno);
+	if (current_menu == $$)
+		menu_end_menu();
+} if_entry menu_entry choice_entry
 
 
-%{
-#define LKC_DIRECT_LINK
-#include "lkc.h"
-%}
 %%
 %%
-input:	  /* empty */
-	| input block
+input: stmt_list;
+
+stmt_list:
+	  /* empty */
+	| stmt_list common_stmt
+	| stmt_list choice_stmt
+	| stmt_list menu_stmt
+	| stmt_list T_MAINMENU prompt nl
+	| stmt_list end			{ zconf_error("unexpected end statement"); }
+	| stmt_list T_WORD error T_EOL	{ zconf_error("unknown statement \"%s\"", $2); }
+	| stmt_list option_name error T_EOL
+{
+	zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
+}
+	| stmt_list error T_EOL		{ zconf_error("invalid statement"); }
 ;
 ;
 
 
-block:	  common_block
-	| choice_stmt
-	| menu_stmt
-	| T_MAINMENU prompt nl_or_eof
-	| T_ENDMENU		{ zconfprint("unexpected 'endmenu' statement"); }
-	| T_ENDIF		{ zconfprint("unexpected 'endif' statement"); }
-	| T_ENDCHOICE		{ zconfprint("unexpected 'endchoice' statement"); }
-	| error nl_or_eof	{ zconfprint("syntax error"); yyerrok; }
+option_name:
+	T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
 ;
 ;
 
 
-common_block:
-	  if_stmt
+common_stmt:
+	  T_EOL
+	| if_stmt
 	| comment_stmt
 	| comment_stmt
 	| config_stmt
 	| config_stmt
 	| menuconfig_stmt
 	| menuconfig_stmt
 	| source_stmt
 	| source_stmt
-	| nl_or_eof
+;
+
+option_error:
+	  T_WORD error T_EOL		{ zconf_error("unknown option \"%s\"", $1); }
+	| error T_EOL			{ zconf_error("invalid option"); }
 ;
 ;
 
 
 
 
@@ -154,53 +175,19 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
 config_option_list:
 config_option_list:
 	  /* empty */
 	  /* empty */
 	| config_option_list config_option
 	| config_option_list config_option
+	| config_option_list symbol_option
 	| config_option_list depends
 	| config_option_list depends
 	| config_option_list help
 	| config_option_list help
+	| config_option_list option_error
 	| config_option_list T_EOL
 	| config_option_list T_EOL
 ;
 ;
 
 
-config_option: T_TRISTATE prompt_stmt_opt T_EOL
+config_option: T_TYPE prompt_stmt_opt T_EOL
 {
 {
-	menu_set_type(S_TRISTATE);
-	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: T_DEF_TRISTATE expr if_expr T_EOL
-{
-	menu_add_expr(P_DEFAULT, $2, $3);
-	menu_set_type(S_TRISTATE);
-	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: T_BOOLEAN prompt_stmt_opt T_EOL
-{
-	menu_set_type(S_BOOLEAN);
-	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: T_DEF_BOOLEAN expr if_expr T_EOL
-{
-	menu_add_expr(P_DEFAULT, $2, $3);
-	menu_set_type(S_BOOLEAN);
-	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: T_INT prompt_stmt_opt T_EOL
-{
-	menu_set_type(S_INT);
-	printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: T_HEX prompt_stmt_opt T_EOL
-{
-	menu_set_type(S_HEX);
-	printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: T_STRING prompt_stmt_opt T_EOL
-{
-	menu_set_type(S_STRING);
-	printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
+	menu_set_type($1->stype);
+	printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+		zconf_curname(), zconf_lineno(),
+		$1->stype);
 };
 };
 
 
 config_option: T_PROMPT prompt if_expr T_EOL
 config_option: T_PROMPT prompt if_expr T_EOL
@@ -212,7 +199,11 @@ config_option: T_PROMPT prompt if_expr T_EOL
 config_option: T_DEFAULT expr if_expr T_EOL
 config_option: T_DEFAULT expr if_expr T_EOL
 {
 {
 	menu_add_expr(P_DEFAULT, $2, $3);
 	menu_add_expr(P_DEFAULT, $2, $3);
-	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+	if ($1->stype != S_UNKNOWN)
+		menu_set_type($1->stype);
+	printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
+		zconf_curname(), zconf_lineno(),
+		$1->stype);
 };
 };
 
 
 config_option: T_SELECT T_WORD if_expr T_EOL
 config_option: T_SELECT T_WORD if_expr T_EOL
@@ -227,6 +218,26 @@ config_option: T_RANGE symbol symbol if_expr T_EOL
 	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
 };
 };
 
 
+symbol_option: T_OPTION symbol_option_list T_EOL
+;
+
+symbol_option_list:
+	  /* empty */
+	| symbol_option_list T_WORD symbol_option_arg
+{
+	struct kconf_id *id = kconf_id_lookup($2, strlen($2));
+	if (id && id->flags & TF_OPTION)
+		menu_add_option(id->token, $3);
+	else
+		zconfprint("warning: ignoring unknown option %s", $2);
+	free($2);
+};
+
+symbol_option_arg:
+	  /* empty */		{ $$ = NULL; }
+	| T_EQUAL prompt	{ $$ = $2; }
+;
+
 /* choice entry */
 /* choice entry */
 
 
 choice: T_CHOICE T_EOL
 choice: T_CHOICE T_EOL
@@ -240,8 +251,7 @@ choice: T_CHOICE T_EOL
 
 
 choice_entry: choice choice_option_list
 choice_entry: choice choice_option_list
 {
 {
-	menu_end_entry();
-	menu_add_menu();
+	$$ = menu_add_menu();
 };
 };
 
 
 choice_end: end
 choice_end: end
@@ -252,13 +262,8 @@ choice_end: end
 	}
 	}
 };
 };
 
 
-choice_stmt:
-	  choice_entry choice_block choice_end
-	| choice_entry choice_block
-{
-	printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
-	zconfnerrs++;
-};
+choice_stmt: choice_entry choice_block choice_end
+;
 
 
 choice_option_list:
 choice_option_list:
 	  /* empty */
 	  /* empty */
@@ -266,6 +271,7 @@ choice_option_list:
 	| choice_option_list depends
 	| choice_option_list depends
 	| choice_option_list help
 	| choice_option_list help
 	| choice_option_list T_EOL
 	| choice_option_list T_EOL
+	| choice_option_list option_error
 ;
 ;
 
 
 choice_option: T_PROMPT prompt if_expr T_EOL
 choice_option: T_PROMPT prompt if_expr T_EOL
@@ -274,16 +280,15 @@ choice_option: T_PROMPT prompt if_expr T_EOL
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 };
 };
 
 
-choice_option: T_TRISTATE prompt_stmt_opt T_EOL
-{
-	menu_set_type(S_TRISTATE);
-	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
-};
-
-choice_option: T_BOOLEAN prompt_stmt_opt T_EOL
+choice_option: T_TYPE prompt_stmt_opt T_EOL
 {
 {
-	menu_set_type(S_BOOLEAN);
-	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
+	if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
+		menu_set_type($1->stype);
+		printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+			zconf_curname(), zconf_lineno(),
+			$1->stype);
+	} else
+		YYERROR;
 };
 };
 
 
 choice_option: T_OPTIONAL T_EOL
 choice_option: T_OPTIONAL T_EOL
@@ -294,24 +299,27 @@ choice_option: T_OPTIONAL T_EOL
 
 
 choice_option: T_DEFAULT T_WORD if_expr T_EOL
 choice_option: T_DEFAULT T_WORD if_expr T_EOL
 {
 {
-	menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
-	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+	if ($1->stype == S_UNKNOWN) {
+		menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
+		printd(DEBUG_PARSE, "%s:%d:default\n",
+			zconf_curname(), zconf_lineno());
+	} else
+		YYERROR;
 };
 };
 
 
 choice_block:
 choice_block:
 	  /* empty */
 	  /* empty */
-	| choice_block common_block
+	| choice_block common_stmt
 ;
 ;
 
 
 /* if entry */
 /* if entry */
 
 
-if: T_IF expr T_EOL
+if_entry: T_IF expr nl
 {
 {
 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
 	menu_add_entry(NULL);
 	menu_add_entry(NULL);
 	menu_add_dep($2);
 	menu_add_dep($2);
-	menu_end_entry();
-	menu_add_menu();
+	$$ = menu_add_menu();
 };
 };
 
 
 if_end: end
 if_end: end
@@ -322,17 +330,12 @@ if_end: end
 	}
 	}
 };
 };
 
 
-if_stmt:
-	  if if_block if_end
-	| if if_block
-{
-	printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
-	zconfnerrs++;
-};
+if_stmt: if_entry if_block if_end
+;
 
 
 if_block:
 if_block:
 	  /* empty */
 	  /* empty */
-	| if_block common_block
+	| if_block common_stmt
 	| if_block menu_stmt
 	| if_block menu_stmt
 	| if_block choice_stmt
 	| if_block choice_stmt
 ;
 ;
@@ -342,14 +345,13 @@ if_block:
 menu: T_MENU prompt T_EOL
 menu: T_MENU prompt T_EOL
 {
 {
 	menu_add_entry(NULL);
 	menu_add_entry(NULL);
-	menu_add_prop(P_MENU, $2, NULL, NULL);
+	menu_add_prompt(P_MENU, $2, NULL);
 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 };
 };
 
 
 menu_entry: menu depends_list
 menu_entry: menu depends_list
 {
 {
-	menu_end_entry();
-	menu_add_menu();
+	$$ = menu_add_menu();
 };
 };
 
 
 menu_end: end
 menu_end: end
@@ -360,31 +362,20 @@ menu_end: end
 	}
 	}
 };
 };
 
 
-menu_stmt:
-	  menu_entry menu_block menu_end
-	| menu_entry menu_block
-{
-	printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
-	zconfnerrs++;
-};
+menu_stmt: menu_entry menu_block menu_end
+;
 
 
 menu_block:
 menu_block:
 	  /* empty */
 	  /* empty */
-	| menu_block common_block
+	| menu_block common_stmt
 	| menu_block menu_stmt
 	| menu_block menu_stmt
 	| menu_block choice_stmt
 	| menu_block choice_stmt
-	| menu_block error T_EOL		{ zconfprint("invalid menu option"); yyerrok; }
 ;
 ;
 
 
-source: T_SOURCE prompt T_EOL
+source_stmt: T_SOURCE prompt T_EOL
 {
 {
-	$$ = $2;
 	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
 	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
-};
-
-source_stmt: source
-{
-	zconf_nextfile($1);
+	zconf_nextfile($2);
 };
 };
 
 
 /* comment entry */
 /* comment entry */
@@ -392,7 +383,7 @@ source_stmt: source
 comment: T_COMMENT prompt T_EOL
 comment: T_COMMENT prompt T_EOL
 {
 {
 	menu_add_entry(NULL);
 	menu_add_entry(NULL);
-	menu_add_prop(P_COMMENT, $2, NULL, NULL);
+	menu_add_prompt(P_COMMENT, $2, NULL);
 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
 };
 };
 
 
@@ -416,9 +407,11 @@ help: help_start T_HELPTEXT
 
 
 /* depends option */
 /* depends option */
 
 
-depends_list:	  /* empty */
-		| depends_list depends
-		| depends_list T_EOL
+depends_list:
+	  /* empty */
+	| depends_list depends
+	| depends_list T_EOL
+	| depends_list option_error
 ;
 ;
 
 
 depends: T_DEPENDS T_ON expr T_EOL
 depends: T_DEPENDS T_ON expr T_EOL
@@ -443,20 +436,22 @@ prompt_stmt_opt:
 	  /* empty */
 	  /* empty */
 	| prompt if_expr
 	| prompt if_expr
 {
 {
-	menu_add_prop(P_PROMPT, $1, NULL, $2);
+	menu_add_prompt(P_PROMPT, $1, $2);
 };
 };
 
 
 prompt:	  T_WORD
 prompt:	  T_WORD
 	| T_WORD_QUOTE
 	| T_WORD_QUOTE
 ;
 ;
 
 
-end:	  T_ENDMENU nl_or_eof	{ $$ = T_ENDMENU; }
-	| T_ENDCHOICE nl_or_eof	{ $$ = T_ENDCHOICE; }
-	| T_ENDIF nl_or_eof	{ $$ = T_ENDIF; }
+end:	  T_ENDMENU T_EOL	{ $$ = $1; }
+	| T_ENDCHOICE T_EOL	{ $$ = $1; }
+	| T_ENDIF T_EOL		{ $$ = $1; }
 ;
 ;
 
 
-nl_or_eof:
-	T_EOL | T_EOF;
+nl:
+	  T_EOL
+	| nl T_EOL
+;
 
 
 if_expr:  /* empty */			{ $$ = NULL; }
 if_expr:  /* empty */			{ $$ = NULL; }
 	| T_IF expr			{ $$ = $2; }
 	| T_IF expr			{ $$ = $2; }
@@ -486,22 +481,30 @@ void conf_parse(const char *name)
 
 
 	sym_init();
 	sym_init();
 	menu_init();
 	menu_init();
-	modules_sym = sym_lookup("MODULES", 0);
-	rootmenu.prompt = menu_add_prop(P_MENU, "Buildroot Configuration", NULL, NULL);
-
-	//zconfdebug = 1;
+	modules_sym = sym_lookup(NULL, 0);
+	modules_sym->type = S_BOOLEAN;
+	modules_sym->flags |= SYMBOL_AUTO;
+	rootmenu.prompt = menu_add_prompt(P_MENU, "Buildroot Configuration", NULL);
+
+#if YYDEBUG
+	if (getenv("ZCONF_DEBUG"))
+		zconfdebug = 1;
+#endif
 	zconfparse();
 	zconfparse();
 	if (zconfnerrs)
 	if (zconfnerrs)
 		exit(1);
 		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));
+	}
 	menu_finalize(&rootmenu);
 	menu_finalize(&rootmenu);
 	for_all_symbols(i, sym) {
 	for_all_symbols(i, sym) {
-                if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym))
-                        printf("\n");
-		else
-			sym->flags |= SYMBOL_CHECK_DONE;
+		sym_check_deps(sym);
         }
         }
 
 
-	sym_change_count = 1;
+	sym_set_change_count(1);
 }
 }
 
 
 const char *zconf_tokenname(int token)
 const char *zconf_tokenname(int token)
@@ -513,20 +516,25 @@ const char *zconf_tokenname(int token)
 	case T_ENDCHOICE:	return "endchoice";
 	case T_ENDCHOICE:	return "endchoice";
 	case T_IF:		return "if";
 	case T_IF:		return "if";
 	case T_ENDIF:		return "endif";
 	case T_ENDIF:		return "endif";
+	case T_DEPENDS:		return "depends";
 	}
 	}
 	return "<token>";
 	return "<token>";
 }
 }
 
 
-static bool zconf_endtoken(int token, int starttoken, int endtoken)
+static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
 {
 {
-	if (token != endtoken) {
-		zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken));
+	if (id->token != endtoken) {
+		zconf_error("unexpected '%s' within %s block",
+			kconf_id_strings + id->name, zconf_tokenname(starttoken));
 		zconfnerrs++;
 		zconfnerrs++;
 		return false;
 		return false;
 	}
 	}
 	if (current_menu->file != current_file) {
 	if (current_menu->file != current_file) {
-		zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken));
-		zconfprint("location of the '%s'", zconf_tokenname(starttoken));
+		zconf_error("'%s' in different file than '%s'",
+			kconf_id_strings + id->name, zconf_tokenname(starttoken));
+		fprintf(stderr, "%s:%d: location of the '%s'\n",
+			current_menu->file->name, current_menu->lineno,
+			zconf_tokenname(starttoken));
 		zconfnerrs++;
 		zconfnerrs++;
 		return false;
 		return false;
 	}
 	}
@@ -537,7 +545,19 @@ static void zconfprint(const char *err, ...)
 {
 {
 	va_list ap;
 	va_list ap;
 
 
-	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1);
+	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+	va_start(ap, err);
+	vfprintf(stderr, err, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+}
+
+static void zconf_error(const char *err, ...)
+{
+	va_list ap;
+
+	zconfnerrs++;
+	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
 	va_start(ap, err);
 	va_start(ap, err);
 	vfprintf(stderr, err, ap);
 	vfprintf(stderr, err, ap);
 	va_end(ap);
 	va_end(ap);
@@ -546,7 +566,9 @@ static void zconfprint(const char *err, ...)
 
 
 static void zconferror(const char *err)
 static void zconferror(const char *err)
 {
 {
+#if YYDEBUG
 	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
 	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+#endif
 }
 }
 
 
 void print_quoted_string(FILE *out, const char *str)
 void print_quoted_string(FILE *out, const char *str)