- pull kconfig from linux-2.6.21.5
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Thu, 28 Jun 2007 10:46:19 +0000 (10:46 -0000)
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Thu, 28 Jun 2007 10:46:19 +0000 (10:46 -0000)
36 files changed:
package/config/Makefile
package/config/Makefile.kconfig [new file with mode: 0644]
package/config/POTFILES.in [new file with mode: 0644]
package/config/README.buildroot2 [new file with mode: 0644]
package/config/conf.c
package/config/confdata.c
package/config/expr.c
package/config/expr.h
package/config/gconf.c [new file with mode: 0644]
package/config/gconf.glade [new file with mode: 0644]
package/config/images.c [new file with mode: 0644]
package/config/kconfig-to-buildroot2.patch [new file with mode: 0644]
package/config/kconfig_load.c [new file with mode: 0644]
package/config/kxgettext.c [new file with mode: 0644]
package/config/lex.zconf.c_shipped
package/config/lkc.h
package/config/lkc_proto.h
package/config/lxdialog/check-lxdialog.sh [new file with mode: 0644]
package/config/lxdialog/checklist.c
package/config/lxdialog/dialog.h
package/config/lxdialog/inputbox.c
package/config/lxdialog/menubox.c
package/config/lxdialog/textbox.c
package/config/lxdialog/util.c
package/config/lxdialog/yesno.c
package/config/mconf.c
package/config/menu.c
package/config/qconf.cc [new file with mode: 0644]
package/config/qconf.h [new file with mode: 0644]
package/config/symbol.c
package/config/util.c
package/config/zconf.gperf [new file with mode: 0644]
package/config/zconf.hash.c_shipped [new file with mode: 0644]
package/config/zconf.l
package/config/zconf.tab.c_shipped
package/config/zconf.y

index 430138f77f8af6fdcce0b5d27a899ef31a3de7aa..f247082cf5d51b921156f8fd75225f7f988c4eb9 100644 (file)
-# 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:
-       $(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
diff --git a/package/config/Makefile.kconfig b/package/config/Makefile.kconfig
new file mode 100644 (file)
index 0000000..7e7e147
--- /dev/null
@@ -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
diff --git a/package/config/POTFILES.in b/package/config/POTFILES.in
new file mode 100644 (file)
index 0000000..cc94e46
--- /dev/null
@@ -0,0 +1,5 @@
+scripts/kconfig/mconf.c
+scripts/kconfig/conf.c
+scripts/kconfig/confdata.c
+scripts/kconfig/gconf.c
+scripts/kconfig/qconf.cc
diff --git a/package/config/README.buildroot2 b/package/config/README.buildroot2
new file mode 100644 (file)
index 0000000..1437cb9
--- /dev/null
@@ -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
index 8ca430b0bdb0c481327e3532d013741af451c3c4..f475f139e844e43434834cc25dde1f86ec7c685f 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <ctype.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
@@ -31,14 +32,14 @@ char *defconfig_file;
 static int indent = 1;
 static int valid_stdin = 1;
 static int conf_cnt;
-static signed char line[128];
+static char line[128];
 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;
 
        while ((isspace(*p)))
@@ -56,9 +57,9 @@ static void strip(signed char *str)
 static void check_stdin(void)
 {
        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);
        }
 }
@@ -82,6 +83,15 @@ static void conf_askvalue(struct symbol *sym, const char *def)
        }
 
        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_silent:
                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));
                def_sym = sym_get_choice_value(sym);
                cnt = def = 0;
-               line[0] = '0';
-               line[1] = 0;
+               line[0] = 0;
                for (child = menu->list; child; child = child->next) {
                        if (!menu_is_visible(child))
                                continue;
@@ -467,15 +476,14 @@ static void check_conf(struct menu *menu)
                return;
 
        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++)
-                               printf("*\n* Restart config...\n*\n");
+                               printf(_("*\n* Restart config...\n*\n"));
                        rootEntry = menu_get_parent_menu(menu);
                        conf(rootEntry);
                }
-               if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)
-                       return;
        }
 
        for (child = menu->list; child; child = child->next)
@@ -504,7 +512,7 @@ int main(int ac, char **av)
                        input_mode = set_default;
                        defconfig_file = av[i++];
                        if (!defconfig_file) {
-                               printf("%s: No default config file specified\n",
+                               printf(_("%s: No default config file specified\n"),
                                        av[0]);
                                exit(1);
                        }
@@ -524,13 +532,14 @@ int main(int ac, char **av)
                        break;
                case 'h':
                case '?':
-                       printf("%s [-o|-s] config\n", av[0]);
+                       fprintf(stderr, "See README for usage info\n");
                        exit(0);
                }
        }
        name = av[i];
        if (!name) {
-               printf("%s: configuration file missing\n", av[0]);
+               printf(_("%s: Kconfig file missing\n"), av[0]);
+               exit(1);
        }
        conf_parse(name);
        //zconfdump(stdout);
@@ -547,18 +556,39 @@ int main(int ac, char **av)
                break;
        case ask_silent:
                if (stat(".config", &tmpstat)) {
-                       printf("***\n"
+                       printf(_("***\n"
                                "*** You have not yet configured Buildroot!\n"
                                "***\n"
                                "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
                                "*** \"make menuconfig\" or \"make config\").\n"
-                               "***\n");
+                               "***\n"));
                        exit(1);
                }
        case ask_all:
        case ask_new:
                conf_read(NULL);
                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:
                break;
        }
@@ -570,14 +600,28 @@ int main(int ac, char **av)
                        input_mode = ask_silent;
                        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 {
                conf_cnt = 0;
                check_conf(&rootmenu);
        } while (conf_cnt);
        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;
        }
+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;
 }
index 144b15c04372b6b908b1fa1e2e7b2913a72c63c5..64af1ac828ebe5714e66f4dfa582cb9b9993c5ec 100644 (file)
@@ -5,28 +5,46 @@
 
 #include <sys/stat.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 
 #define LKC_DIRECT_LINK
 #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;
-       const signed char *src;
+       const char *src;
        static char res_value[SYMBOL_MAXLENGTH];
        char *dst, name[SYMBOL_MAXLENGTH];
 
@@ -65,53 +83,70 @@ char *conf_get_default_confname(void)
        return name;
 }
 
-int conf_read(const char *name)
+int conf_read_simple(const char *name, int def)
 {
        FILE *in = NULL;
        char line[1024];
        char *p, *p2;
-       int lineno = 0;
        struct symbol *sym;
-       struct property *prop;
-       struct expr *e;
-       int i;
+       int i, def_flags;
 
        if (name) {
                in = zconf_fopen(name);
        } 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);
                        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)
                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) {
-               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) {
                case S_INT:
                case S_HEX:
                case S_STRING:
-                       if (sym->user.val)
-                               free(sym->user.val);
+                       if (sym->def[def].val)
+                               free(sym->def[def].val);
                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)) {
-               lineno++;
+               conf_lineno++;
                sym = NULL;
                switch (line[0]) {
                case '#':
@@ -123,54 +158,84 @@ int conf_read(const char *name)
                        *p++ = 0;
                        if (strncmp(p, "is not set", 10))
                                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;
                        }
                        switch (sym->type) {
                        case S_BOOLEAN:
                        case S_TRISTATE:
-                               sym->user.tri = no;
-                               sym->flags &= ~SYMBOL_NEW;
+                               sym->def[def].tri = no;
+                               sym->flags |= def_flags;
                                break;
                        default:
                                ;
                        }
                        break;
-
                case 'A' ... 'Z':
                        p = strchr(line, '=');
                        if (!p)
                                continue;
                        *p++ = 0;
                        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;
                        }
                        switch (sym->type) {
                        case S_TRISTATE:
                                if (p[0] == 'm') {
-                                       sym->user.tri = mod;
-                                       sym->flags &= ~SYMBOL_NEW;
+                                       sym->def[def].tri = mod;
+                                       sym->flags |= def_flags;
                                        break;
                                }
                        case S_BOOLEAN:
                                if (p[0] == 'y') {
-                                       sym->user.tri = yes;
-                                       sym->flags &= ~SYMBOL_NEW;
+                                       sym->def[def].tri = yes;
+                                       sym->flags |= def_flags;
                                        break;
                                }
                                if (p[0] == 'n') {
-                                       sym->user.tri = no;
-                                       sym->flags &= ~SYMBOL_NEW;
+                                       sym->def[def].tri = no;
+                                       sym->flags |= def_flags;
                                        break;
                                }
+                               conf_warning("symbol value '%s' invalid for %s", p, sym->name);
                                break;
+                       case S_OTHER:
+                               if (*p != '"') {
+                                       for (p2 = p; *p2 && !isspace(*p2); p2++)
+                                               ;
+                                       sym->type = S_STRING;
+                                       goto done;
+                               }
                        case S_STRING:
                                if (*p++ != '"')
                                        break;
@@ -182,62 +247,105 @@ int conf_read(const char *name)
                                        memmove(p2, p2 + 1, strlen(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_HEX:
+                       done:
                                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 {
-                                       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;
                        default:
                                ;
                        }
                        break;
+               case '\r':
                case '\n':
                        break;
                default:
+                       conf_warning("unexpected data");
                        continue;
                }
                if (sym && sym_is_choice_value(sym)) {
                        struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
-                       switch (sym->user.tri) {
+                       switch (sym->def[def].tri) {
                        case no:
                                break;
                        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;
                        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;
                        }
-                       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);
 
        if (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) {
                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->visible == no)
-                               sym->flags |= SYMBOL_NEW;
+                               sym->flags &= ~SYMBOL_DEF_USER;
                        switch (sym->type) {
                        case S_STRING:
                        case S_INT:
                        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:
                                break;
                        }
@@ -245,12 +353,14 @@ int conf_read(const char *name)
                if (!sym_is_choice(sym))
                        continue;
                prop = sym_get_choice_prop(sym);
+               flags = sym->flags;
                for (e = prop->expr; e; e = e->left.expr)
                        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;
 }
@@ -264,6 +374,9 @@ int conf_write(const char *name)
        char dirname[128], tmpname[128], newname[128];
        int type, l;
        const char *str;
+       time_t now;
+       int use_timestamp = 1;
+       char *env;
 
        dirname[0] = 0;
        if (name && name[0]) {
@@ -273,7 +386,7 @@ int conf_write(const char *name)
                if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
                        strcpy(dirname, name);
                        strcat(dirname, "/");
-                       basename = conf_def_filename;
+                       basename = conf_get_configname();
                } else if ((slash = strrchr(name, '/'))) {
                        int size = slash - name + 1;
                        memcpy(dirname, name, size);
@@ -281,21 +394,39 @@ int conf_write(const char *name)
                        if (slash[1])
                                basename = slash + 1;
                        else
-                               basename = conf_def_filename;
+                               basename = conf_get_configname();
                } else
                        basename = name;
        } 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)
                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();
 
        menu = rootmenu.list;
@@ -336,20 +467,18 @@ int conf_write(const char *name)
                                }
                                break;
                        case S_STRING:
-                               // fix me
                                str = sym_get_string_value(sym);
                                fprintf(out, "%s=\"", sym->name);
-                               do {
+                               while (1) {
                                        l = strcspn(str, "\"\\");
                                        if (l) {
                                                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);
                                break;
                        case S_HEX:
@@ -380,18 +509,279 @@ int conf_write(const char *name)
                }
        }
        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;
 
-       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;
+
+       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;
 }
index 30e4f9d69c2fbc2e080022f6fe5db49985207d9d..6f98dbfe70cf4df2e57432e838465c33e4f4888e 100644 (file)
@@ -145,7 +145,8 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
                return;
        }
        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;
        if (!expr_eq(e1, e2))
                return;
@@ -1012,73 +1013,73 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2)
 #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) {
-               fn(data, "y");
+               fn(data, NULL, "y");
                return;
        }
 
        if (expr_compare_type(prevtoken, e->type) > 0)
-               fn(data, "(");
+               fn(data, NULL, "(");
        switch (e->type) {
        case E_SYMBOL:
                if (e->left.sym->name)
-                       fn(data, e->left.sym->name);
+                       fn(data, e->left.sym, e->left.sym->name);
                else
-                       fn(data, "<choice>");
+                       fn(data, NULL, "<choice>");
                break;
        case E_NOT:
-               fn(data, "!");
+               fn(data, NULL, "!");
                expr_print(e->left.expr, fn, data, E_NOT);
                break;
        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;
        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;
        case 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);
                break;
        case 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);
                break;
        case E_CHOICE:
-               fn(data, e->right.sym->name);
+               fn(data, e->right.sym, e->right.sym->name);
                if (e->left.expr) {
-                       fn(data, " ^ ");
+                       fn(data, NULL, " ^ ");
                        expr_print(e->left.expr, fn, data, E_CHOICE);
                }
                break;
        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;
        default:
          {
                char buf[32];
                sprintf(buf, "<unknown type %d>", e->type);
-               fn(data, buf);
+               fn(data, NULL, buf);
                break;
          }
        }
        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);
 }
@@ -1088,7 +1089,7 @@ void expr_fprint(struct expr *e, FILE *out)
        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);
 }
index 7d39ff43e6e1facd64d6267cd443919b3d1c7381..6084525f604b10e9871ada2aa6ca096d5be481ff 100644 (file)
@@ -63,12 +63,18 @@ enum symbol_type {
        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 *next;
        char *name;
        char *help;
        enum symbol_type type;
-       struct symbol_value curr, user;
+       struct symbol_value curr;
+       struct symbol_value def[4];
        tristate visible;
        int flags;
        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 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_CHOICE          0x0010
 #define SYMBOL_CHOICEVAL       0x0020
@@ -90,11 +93,14 @@ struct symbol {
 #define SYMBOL_OPTIONAL                0x0100
 #define SYMBOL_WRITE           0x0200
 #define SYMBOL_CHANGED         0x0400
-#define SYMBOL_NEW             0x0800
 #define SYMBOL_AUTO            0x1000
 #define SYMBOL_CHECKED         0x2000
-#define SYMBOL_CHECK_DONE      0x4000
 #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_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 *modules_sym;
+extern struct symbol *sym_defconfig_list;
 extern int cdebug;
 struct expr *expr_alloc_symbol(struct symbol *sym);
 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
diff --git a/package/config/gconf.c b/package/config/gconf.c
new file mode 100644 (file)
index 0000000..99b82ca
--- /dev/null
@@ -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);
+}
diff --git a/package/config/gconf.glade b/package/config/gconf.glade
new file mode 100644 (file)
index 0000000..5656bf7
--- /dev/null
@@ -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>
diff --git a/package/config/images.c b/package/config/images.c
new file mode 100644 (file)
index 0000000..d4f84bd
--- /dev/null
@@ -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",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            ",
+"            "};
diff --git a/package/config/kconfig-to-buildroot2.patch b/package/config/kconfig-to-buildroot2.patch
new file mode 100644 (file)
index 0000000..38a570d
--- /dev/null
@@ -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>
diff --git a/package/config/kconfig_load.c b/package/config/kconfig_load.c
new file mode 100644 (file)
index 0000000..dbdcaad
--- /dev/null
@@ -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
+}
diff --git a/package/config/kxgettext.c b/package/config/kxgettext.c
new file mode 100644 (file)
index 0000000..abee55c
--- /dev/null
@@ -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;
+}
index 22dda11f758b4fa052def4f76a4f5921a7314baa..800f8c71c407f32893020c72c14d043147e8eeb1 100644 (file)
@@ -1,5 +1,5 @@
 
-#line 3 "lex.zconf.c"
+#line 3 "scripts/kconfig/lex.zconf.c"
 
 #define  YY_INT_ALIGNED short int
 
@@ -8,7 +8,7 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 31
+#define YY_FLEX_SUBMINOR_VERSION 33
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
 
 /* 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>
 typedef int8_t flex_int8_t;
 typedef uint8_t flex_uint8_t;
@@ -134,6 +142,10 @@ typedef unsigned int flex_uint32_t;
 #define YY_BUF_SIZE 16384
 #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
 #define YY_TYPEDEF_YY_BUFFER_STATE
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
@@ -267,7 +279,7 @@ int zconfleng;
 
 /* Points to current character in buffer. */
 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 */
 
 /* 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_flush_buffer (YY_BUFFER_STATE b  );
 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_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,
    but its presence is necessary. */
 struct yy_trans_info
@@ -1927,31 +695,14 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        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,
-       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] =
@@ -1965,11 +716,11 @@ static yyconst flex_int32_t yy_ec[256] =
        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,
-        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,
@@ -2014,8 +765,12 @@ char *zconftext;
 
 #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;
 
 struct buffer {
@@ -2028,29 +783,28 @@ struct buffer *current_buf;
 static int last_ts, first_ts;
 
 static void zconf_endhelp(void);
-static struct buffer *zconf_endfile(void);
+static void zconf_endfile(void);
 
 void new_string(void)
 {
        text = malloc(START_STRSIZE);
        text_asize = START_STRSIZE;
-       text_ptr = text;
        text_size = 0;
-       *text_ptr = 0;
+       *text = 0;
 }
 
 void append_string(const char *str, int size)
 {
        int new_size = text_size + size + 1;
        if (new_size > text_asize) {
+               new_size += START_STRSIZE - 1;
+               new_size &= -START_STRSIZE;
                text = realloc(text, 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_ptr = 0;
+       text[text_size] = 0;
 }
 
 void alloc_string(const char *str, int size)
@@ -2066,16 +820,20 @@ void alloc_string(const char *str, int size)
 #define STRING 3
 #define PARAM 4
 
+#ifndef YY_NO_UNISTD_H
 /* 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.
  * The user has a chance to override it with an option.
  */
 #include <unistd.h>
+#endif
 
 #ifndef YY_EXTRA_TYPE
 #define YY_EXTRA_TYPE void *
 #endif
 
+static int yy_init_globals (void );
+
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
  */
@@ -2198,9 +956,9 @@ YY_DECL
        int str = 0;
        int ts, i;
 
-       if ( (yy_init) )
+       if ( !(yy_init) )
                {
-               (yy_init) = 0;
+               (yy_init) = 1;
 
 #ifdef 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 */
 case 1:
 /* rule 1 can match eol */
-YY_RULE_SETUP
-current_file->lineno++;
-       YY_BREAK
 case 2:
+/* rule 2 can match eol */
 YY_RULE_SETUP
-
+{
+       current_file->lineno++;
+       return T_EOL;
+}
        YY_BREAK
 case 3:
-/* rule 3 can match eol */
 YY_RULE_SETUP
-current_file->lineno++; return T_EOL;
+
        YY_BREAK
 case 4:
 YY_RULE_SETUP
@@ -2282,175 +1040,63 @@ YY_RULE_SETUP
 
 case 6:
 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);
                zconflval.string = text;
                return T_WORD;
        }
        YY_BREAK
-case 36:
+case 7:
 YY_RULE_SETUP
 
        YY_BREAK
-case 37:
-/* rule 37 can match eol */
+case 8:
+/* rule 8 can match eol */
 YY_RULE_SETUP
-current_file->lineno++; BEGIN(INITIAL);
+{
+               BEGIN(INITIAL);
+               current_file->lineno++;
+               return T_EOL;
+       }
        YY_BREAK
 
-case 38:
+case 9:
 YY_RULE_SETUP
 return T_AND;
        YY_BREAK
-case 39:
+case 10:
 YY_RULE_SETUP
 return T_OR;
        YY_BREAK
-case 40:
+case 11:
 YY_RULE_SETUP
 return T_OPEN_PAREN;
        YY_BREAK
-case 41:
+case 12:
 YY_RULE_SETUP
 return T_CLOSE_PAREN;
        YY_BREAK
-case 42:
+case 13:
 YY_RULE_SETUP
 return T_NOT;
        YY_BREAK
-case 43:
+case 14:
 YY_RULE_SETUP
 return T_EQUAL;
        YY_BREAK
-case 44:
+case 15:
 YY_RULE_SETUP
 return T_UNEQUAL;
        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
 {
                str = zconftext[0];
@@ -2458,33 +1104,38 @@ YY_RULE_SETUP
                BEGIN(STRING);
        }
        YY_BREAK
-case 48:
-/* rule 48 can match eol */
+case 17:
+/* rule 17 can match eol */
 YY_RULE_SETUP
 BEGIN(INITIAL); current_file->lineno++; return T_EOL;
        YY_BREAK
-case 49:
+case 18:
 YY_RULE_SETUP
 /* ignore */
        YY_BREAK
-case 50:
+case 19:
 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);
                zconflval.string = text;
                return T_WORD;
        }
        YY_BREAK
-case 51:
+case 20:
 YY_RULE_SETUP
 /* comment */
        YY_BREAK
-case 52:
-/* rule 52 can match eol */
+case 21:
+/* rule 21 can match eol */
 YY_RULE_SETUP
 current_file->lineno++;
        YY_BREAK
-case 53:
+case 22:
 YY_RULE_SETUP
 
        YY_BREAK
@@ -2494,8 +1145,8 @@ case YY_STATE_EOF(PARAM):
        }
        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_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
@@ -2506,14 +1157,14 @@ YY_RULE_SETUP
                return T_WORD_QUOTE;
        }
        YY_BREAK
-case 55:
+case 24:
 YY_RULE_SETUP
 {
                append_string(zconftext, zconfleng);
        }
        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_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
@@ -2524,13 +1175,13 @@ YY_RULE_SETUP
                return T_WORD_QUOTE;
        }
        YY_BREAK
-case 57:
+case 26:
 YY_RULE_SETUP
 {
                append_string(zconftext + 1, zconfleng - 1);
        }
        YY_BREAK
-case 58:
+case 27:
 YY_RULE_SETUP
 {
                if (str == zconftext[0]) {
@@ -2541,8 +1192,8 @@ YY_RULE_SETUP
                        append_string(zconftext, 1);
        }
        YY_BREAK
-case 59:
-/* rule 59 can match eol */
+case 28:
+/* rule 28 can match eol */
 YY_RULE_SETUP
 {
                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
 
-case 60:
+case 29:
 YY_RULE_SETUP
 {
                ts = 0;
@@ -2582,8 +1233,8 @@ YY_RULE_SETUP
                }
        }
        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_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
@@ -2594,15 +1245,15 @@ YY_RULE_SETUP
                return T_HELPTEXT;
        }
        YY_BREAK
-case 62:
-/* rule 62 can match eol */
+case 31:
+/* rule 31 can match eol */
 YY_RULE_SETUP
 {
                current_file->lineno++;
                append_string("\n", 1);
        }
        YY_BREAK
-case 63:
+case 32:
 YY_RULE_SETUP
 {
                append_string(zconftext, zconfleng);
@@ -2620,15 +1271,15 @@ case YY_STATE_EOF(HELP):
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(COMMAND):
 {
-       if (current_buf) {
+       if (current_file) {
                zconf_endfile();
-               return T_EOF;
+               return T_EOL;
        }
        fclose(zconfin);
        yyterminate();
 }
        YY_BREAK
-case 64:
+case 33:
 YY_RULE_SETUP
 YY_FATAL_ERROR( "flex scanner jammed" );
        YY_BREAK
@@ -2815,7 +1466,7 @@ static int yy_get_next_buffer (void)
 
        else
                {
-                       size_t num_to_read =
+                       int num_to_read =
                        YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
                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
  * 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.
  * @note If you want to scan bytes that may contain NUL values, then use
  *       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
@@ -3351,7 +2002,7 @@ YY_BUFFER_STATE zconf_scan_string (yyconst char * str )
  * 
  * @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;
        char *buf;
@@ -3359,15 +2010,15 @@ YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * bytes, int  len )
        int i;
     
        /* Get memory for full buffer, including space for trailing EOB's. */
-       n = len + 2;
+       n = _yybytes_len + 2;
        buf = (char *) zconfalloc(n  );
        if ( ! buf )
                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 );
        if ( ! b )
@@ -3488,6 +2139,34 @@ void zconfset_debug (int  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. */
 int zconflex_destroy  (void)
 {
@@ -3503,6 +2182,10 @@ int zconflex_destroy  (void)
        zconffree((yy_buffer_stack) );
        (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;
 }
 
@@ -3514,7 +2197,7 @@ int zconflex_destroy  (void)
 static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 {
        register int i;
-       for ( i = 0; i < n; ++i )
+       for ( i = 0; i < n; ++i )
                s1[i] = s2[i];
 }
 #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 )
 {
        register int n;
-       for ( n = 0; s[n]; ++n )
+       for ( n = 0; s[n]; ++n )
                ;
 
        return n;
@@ -3554,19 +2237,6 @@ void zconffree (void * ptr )
 
 #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)
 {
        new_string();
@@ -3650,7 +2320,7 @@ void zconf_nextfile(const char *name)
        current_file = file;
 }
 
-static struct buffer *zconf_endfile(void)
+static void zconf_endfile(void)
 {
        struct buffer *parent;
 
@@ -3666,23 +2336,15 @@ static struct buffer *zconf_endfile(void)
        }
        free(current_buf);
        current_buf = parent;
-
-       return parent;
 }
 
 int zconf_lineno(void)
 {
-       if (current_buf)
-               return current_file->lineno - 1;
-       else
-               return 0;
+       return current_pos.lineno;
 }
 
 char *zconf_curname(void)
 {
-       if (current_buf)
-               return current_file->name;
-       else
-               return "<none>";
+       return current_pos.file ? current_pos.file->name : "<none>";
 }
 
index b8a67fc9d6476d4b4b812f4226f7376f4c08584d..9b2706a41548d3b5224caed652b2a4f74f68eed4 100644 (file)
@@ -8,6 +8,14 @@
 
 #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
 extern "C" {
 #endif
@@ -23,6 +31,27 @@ extern "C" {
 
 #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);
 void zconfdump(FILE *out);
 
@@ -35,25 +64,25 @@ int zconf_lineno(void);
 char *zconf_curname(void);
 
 /* confdata.c */
-extern const char conf_def_filename[];
-extern char conf_filename[];
-
 char *conf_get_default_confname(void);
+void sym_set_change_count(int count);
+void sym_add_change_count(int count);
 
 /* kconfig_load.c */
 void kconfig_load(void);
 
 /* menu.c */
 void menu_init(void);
-void menu_add_menu(void);
+struct menu *menu_add_menu(void);
 void menu_end_menu(void);
 void menu_add_entry(struct symbol *sym);
 void menu_end_entry(void);
 void menu_add_dep(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_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_set_type(int type);
 
@@ -75,6 +104,7 @@ const char *str_get(struct gstr *gs);
 /* symbol.c */
 void sym_init(void);
 void sym_clear_all_valid(void);
+void sym_set_all_changed(void);
 void sym_set_changed(struct symbol *sym);
 struct symbol *sym_check_deps(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)
 {
-       return sym->flags & SYMBOL_NEW ? false : true;
+       return sym->flags & SYMBOL_DEF_USER ? true : false;
 }
 
 #ifdef __cplusplus
index 6dc6d0c48e7ac8e617e1010ac97e572db9328423..15030770d1ad4e937272a6f03d7d704ebad70dff 100644 (file)
@@ -2,7 +2,11 @@
 /* confdata.c */
 P(conf_parse,void,(const char *name));
 P(conf_read,int,(const char *name));
+P(conf_read_simple,int,(const char *name, int));
 P(conf_write,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 */
 P(rootmenu,struct menu,);
@@ -14,7 +18,6 @@ P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 
 /* symbol.c */
 P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
-P(sym_change_count,int,);
 
 P(sym_lookup,struct symbol *,(const char *name, int isconst));
 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 */
 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));
diff --git a/package/config/lxdialog/check-lxdialog.sh b/package/config/lxdialog/check-lxdialog.sh
new file mode 100644 (file)
index 0000000..120d624
--- /dev/null
@@ -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
index 71de4a191dab864af00e868f9c91d943860c1311..cf697080ddddd4bf47df0057f860ef681255ea29 100644 (file)
 
 #include "dialog.h"
 
-static int list_width, check_x, item_x, checkflag;
+static int list_width, check_x, item_x;
 
 /*
  * 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.
  */
-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
  */
-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
- * 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 */
 }
index 7bab3ad0e1c137839578c69ce17e8f645bc318ef..fd695e1070f76de6d64f2b6d95b2b2a5fbf84a9f 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  *  dialog.h -- common declarations for all dialog modules
  *
@@ -25,8 +24,8 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 
-#ifdef CURSES_LOC
 #ifdef __sun__
 #define CURS_MACROS
 #endif
 #if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
 #define OLD_NCURSES 1
 #undef  wbkgdset
-#define wbkgdset(w,p) /*nothing*/
+#define wbkgdset(w,p)          /*nothing */
 #else
 #define OLD_NCURSES 0
 #endif
 
 #define TR(params) _tracef params
 
-#define ESC 27
+#define KEY_ESC 27
 #define TAB 9
 #define MAX_LEN 2048
 #define BUF_SIZE (10*1024)
 #define MIN(x,y) (x < y ? x : y)
 #define MAX(x,y) (x > y ? x : y)
 
-
 #ifndef ACS_ULCORNER
 #define ACS_ULCORNER '+'
 #endif
 #define ACS_DARROW 'v'
 #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
  */
 
-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
@@ -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')
  *   -- uppercase chars are used to invoke the button (M_EVENT + 'O')
  */
-#ifdef CURSES_LOC
 #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
index fa7bebc693b932d36c86cb8c6d19d3fd8a5bd999..05e72066b35987dfe7037f6abd2fe29a03cb016a 100644 (file)
 
 #include "dialog.h"
 
-unsigned char dialog_input_result[MAX_LEN + 1];
+char dialog_input_result[MAX_LEN + 1];
 
 /*
  *  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
  */
-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 */
 }
index 873dc587b8991bc2526398e877d338fbcca879c6..0d83159d90127a1dad38be99edff1a0973353a33 100644 (file)
@@ -63,376 +63,372 @@ static int menu_width, item_x;
 /*
  * 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
-    {
-        int i;
-        for (i = 0; i < menu_width; i++)
-           waddch (win, ' ');
-    }
+       {
+               int i;
+               for (i = 0; i < menu_width; i++)
+                       waddch(win, ' ');
+       }
 #else
-    wclrtoeol(win);
+       wclrtoeol(win);
 #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.
  */
-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.
  */
-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
  */
-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 {
-           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 */
 }
index a5a460b5cc64f8be035f52882f3e38ae15f17c25..fabfc1ad789d674f5f91637cba70cbfc335431d0 100644 (file)
 
 #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.
  */
-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'.
  */
-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().
  */
-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().
  */
-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
-    {
-        int i;
-        for (i = 0; i < width - x; i++)
-           waddch (win, ' ');
-    }
+       {
+               int i;
+               for (i = 0; i < width - x; i++)
+                       waddch(win, ' ');
+       }
 #else
-    wclrtoeol(win);
+       wclrtoeol(win);
 #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
  * 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
  */
-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);
 }
index 6f83951b905b354b66941d64a15cb56f2851a9a4..d54440fc166cbd03bc8c16c9c91667fd9631761e 100644 (file)
 
 #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
  */
-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.
  */
-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
@@ -194,164 +309,166 @@ end_dialog (void)
  * characters '\n' are replaced by spaces.  We start on a new line
  * if there is no room for at least 4 nonblanks following a double-space.
  */
-void
-print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
-{
-    int newl, cur_x, cur_y;
-    int i, prompt_len, room, wlen;
-    char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
-
-    strcpy (tempstr, prompt);
-
-    prompt_len = strlen(tempstr);
-       
-    /*
-     * Remove newlines
-     */
-    for(i=0; i<prompt_len; i++) {
-       if(tempstr[i] == '\n') tempstr[i] = ' ';
-    }
-
-    if (prompt_len <= width - x * 2) { /* If prompt is short */
-       wmove (win, y, (width - prompt_len) / 2);
-       waddstr (win, tempstr);
-    } else {
-       cur_x = x;
-       cur_y = y;
-       newl = 1;
-       word = tempstr;
-       while (word && *word) {
-           sp = index(word, ' ');
-           if (sp)
-               *sp++ = 0;
-
-           /* Wrap to next line if either the word does not fit,
-              or it is the first word of a new sentence, and it is
-              short, and the next word does not fit. */
-           room = width - cur_x;
-           wlen = strlen(word);
-           if (wlen > room ||
-              (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
-                    && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
-               cur_y++;
+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;
-           }
-           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;
-           } 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
  */
-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
  */
 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
  * 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.
  */
-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++) {
                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;
        }
 
@@ -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);
 }
index 11fcc25f5159c1e69aa4631f2c62cbe9df52510c..ee0a04e3e012ecd4ba119cd153d96a08ded7b2a2 100644 (file)
 /*
  * 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
  */
-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 */
 }
index 3f645d44a2d44c4c89d9152326468c2d06ce0131..3288822f12db2484e8dfdd89a95e1a6cf2a42c42 100644 (file)
@@ -5,13 +5,11 @@
  * Introduced single menu mode (show all sub-menus in one large tree).
  * 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/wait.h>
-#include <sys/termios.h>
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <string.h>
 #include <termios.h>
 #include <unistd.h>
-
-#include "lxdialog/dialog.h"
+#include <locale.h>
 
 #define LKC_DIRECT_LINK
 #include "lkc.h"
+#include "lxdialog/dialog.h"
 
 static char menu_backtitle[128];
-static const char mconf_readme[] =
+static const char mconf_readme[] = N_(
 "Overview\n"
 "--------\n"
 "Some features may be built directly into Buildroot.  Some features\n"
@@ -160,39 +158,53 @@ static const char mconf_readme[] =
 "\n"
 "Note that this mode can eventually be a little more CPU expensive\n"
 "(especially with a larger number of unrolled categories) than the\n"
-"default mode.\n",
-menu_instructions[] =
+"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.  "
        "<Enter> selects submenus --->.  "
        "Highlighted letters are hotkeys.  "
        "Pressing <Y> selectes a feature, while <N> will exclude a feature.  "
        "Press <Esc><Esc> to exit, <?> for Help, </> 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 "
        "press the hotkey of the item you wish to select "
        "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. "
        "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. "
-       "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. "
-       "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"
-       "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.  "
        "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"
        "For various reasons, one may wish to keep several different Buildroot\n"
        "configurations available on a single machine.\n"
@@ -202,11 +214,11 @@ load_config_help[] =
        "to modify that configuration.\n"
        "\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 "
-       "as an alternate.  Leave blank to abort.",
-save_config_help[] =
+       "as an alternate.  Leave blank to abort."),
+save_config_help[] = N_(
        "\n"
        "For various reasons, one may wish to keep different Buildroot\n"
        "configurations available on a single machine.\n"
@@ -216,10 +228,11 @@ save_config_help[] =
        "configuration options you have selected at that time.\n"
        "\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"
        "Search for CONFIG_ symbols and display their relations.\n"
+       "Regular expressions are allowed.\n"
        "Example: search for \"^FOO\"\n"
        "Result:\n"
        "-----------------------------------------------------------------\n"
@@ -254,7 +267,7 @@ search_help[] =
        "Examples: USB  => find all CONFIG_ symbols containing USB\n"
        "          ^USB => find all CONFIG_ symbols starting with USB\n"
        "          USB$ => find all CONFIG_ symbols ending with USB\n"
-       "\n";
+       "\n");
 
 static char filename[PATH_MAX+1] = ".config";
 static int indent;
@@ -264,9 +277,6 @@ static struct menu *current_menu;
 static int child_count;
 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_choice(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_helptext(const char *title, const char *text);
 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)
 {
@@ -303,8 +312,8 @@ static void init_wsize(void)
        }
 
        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);
        }
 
@@ -312,65 +321,6 @@ static void init_wsize(void)
        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)
 {
        int i, j;
@@ -447,15 +397,17 @@ static void search_conf(void)
 {
        struct symbol **sym_arr;
        struct gstr res;
-
+       int dres;
 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:
                break;
        case 1:
-               show_helptext("Search Configuration", search_help);
+               show_helptext(_("Search Configuration"), search_help);
                goto again;
        default:
                return;
@@ -464,7 +416,7 @@ again:
        sym_arr = sym_re_search(dialog_input_result);
        res = get_relations_str(sym_arr);
        free(sym_arr);
-       show_textbox("Search Results", str_get(&res), 0, 0);
+       show_textbox(_("Search Results"), str_get(&res), 0, 0);
        str_free(&res);
 }
 
@@ -488,26 +440,24 @@ static void build_conf(struct menu *menu)
                        switch (prop->type) {
                        case P_MENU:
                                child_count++;
-                               cmake();
-                               cprint_tag("m%p", menu);
-
                                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)
                                        goto conf_childs;
                                return;
                        default:
                                if (prompt) {
                                        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
@@ -515,7 +465,6 @@ static void build_conf(struct menu *menu)
                goto conf_childs;
        }
 
-       cmake();
        type = sym_get_type(sym);
        if (sym_is_choice(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);
                if (sym_is_changable(sym)) {
-                       cprint_tag("t%p", menu);
                        switch (type) {
                        case S_BOOLEAN:
-                               cprint_name("[%c]", val == no ? ' ' : '*');
+                               item_make("[%c]", val == no ? ' ' : '*');
                                break;
                        case S_TRISTATE:
                                switch (val) {
@@ -540,19 +488,22 @@ static void build_conf(struct menu *menu)
                                case mod: ch = 'M'; break;
                                default:  ch = ' '; break;
                                }
-                               cprint_name("<%c>", ch);
+                               item_make("<%c>", ch);
                                break;
                        }
+                       item_set_tag('t');
+                       item_set_data(menu);
                } 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 (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) {
                                        indent += 2;
                                        build_conf(def_menu);
@@ -563,53 +514,59 @@ static void build_conf(struct menu *menu)
                }
        } else {
                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;
                }
                child_count++;
                val = sym_get_tristate_value(sym);
                if (sym_is_choice_value(sym) && val == yes) {
-                       cprint_tag(":%p", menu);
-                       cprint_name("   ");
+                       item_make("   ");
+                       item_set_tag(':');
+                       item_set_data(menu);
                } else {
                        switch (type) {
                        case S_BOOLEAN:
-                               cprint_tag("t%p", menu);
                                if (sym_is_changable(sym))
-                                       cprint_name("[%c]", val == no ? ' ' : '*');
+                                       item_make("[%c]", val == no ? ' ' : '*');
                                else
-                                       cprint_name("---");
+                                       item_make("---");
+                               item_set_tag('t');
+                               item_set_data(menu);
                                break;
                        case S_TRISTATE:
-                               cprint_tag("t%p", menu);
                                switch (val) {
                                case yes: ch = '*'; break;
                                case mod: ch = 'M'; break;
                                default:  ch = ' '; break;
                                }
                                if (sym_is_changable(sym))
-                                       cprint_name("<%c>", ch);
+                                       item_make("<%c>", ch);
                                else
-                                       cprint_name("---");
+                                       item_make("---");
+                               item_set_tag('t');
+                               item_set_data(menu);
                                break;
                        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;
                                if (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;
                        }
                }
-               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) {
-                       cprint_name("  --->");
+                       item_add_str("  --->");
                        return;
                }
        }
@@ -623,56 +580,48 @@ conf_childs:
 
 static void conf(struct menu *menu)
 {
-       struct dialog_list_item *active_item = NULL;
        struct menu *submenu;
        const char *prompt = menu_get_prompt(menu);
        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) {
-               indent = 0;
-               child_count = 0;
+               item_reset();
                current_menu = menu;
-               cdone(); cinit();
                build_conf(menu);
                if (!child_count)
                        break;
                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();
-               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;
-
-               active_item = first_sel_item(item_no, items);
-               if (!active_item)
+               if (!item_activate_selected())
                        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;
 
-               sym = NULL;
-               submenu = NULL;
-               if (sscanf(active_entry + 1, "%p", &submenu) == 1)
+               submenu = item_data();
+               active_menu = item_data();
+               if (submenu)
                        sym = submenu->sym;
+               else
+                       sym = NULL;
 
-               switch (stat) {
+               switch (res) {
                case 0:
-                       switch (type) {
+                       switch (item_tag()) {
                        case 'm':
                                if (single_menu_mode)
                                        submenu->data = (void *) (long) !submenu->data;
@@ -700,10 +649,10 @@ static void conf(struct menu *menu)
                        if (sym)
                                show_help(submenu);
                        else
-                               show_helptext("README", mconf_readme);
+                               show_helptext("README", _(mconf_readme));
                        break;
                case 3:
-                       if (type == 't') {
+                       if (item_is_tag('t')) {
                                if (sym_set_tristate_value(sym, yes))
                                        break;
                                if (sym_set_tristate_value(sym, mod))
@@ -711,17 +660,17 @@ static void conf(struct menu *menu)
                        }
                        break;
                case 4:
-                       if (type == 't')
+                       if (item_is_tag('t'))
                                sym_set_tristate_value(sym, no);
                        break;
                case 5:
-                       if (type == 't')
+                       if (item_is_tag('t'))
                                sym_set_tristate_value(sym, mod);
                        break;
                case 6:
-                       if (type == 't')
+                       if (item_is_tag('t'))
                                sym_toggle_tristate_value(sym);
-                       else if (type == 'm')
+                       else if (item_is_tag('m'))
                                conf(submenu);
                        break;
                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)
 {
-       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)
@@ -755,8 +699,8 @@ static void show_help(struct menu *menu)
        if (sym->help)
        {
                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");
                }
        } else {
@@ -767,12 +711,6 @@ static void show_help(struct menu *menu)
        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)
 {
        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);
        while (1) {
+               int res;
+               int selected;
+               item_reset();
+
                current_menu = menu;
-               cdone(); cinit();
                for (child = menu->list; child; child = child->next) {
                        if (!menu_is_visible(child))
                                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))
-                               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:
-                       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;
                case 1:
-                       if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) == 1) {
+                       if (selected) {
+                               child = item_data();
                                show_help(child);
                                active = child->sym;
                        } else
                                show_help(menu);
                        break;
-               case 255:
+               case KEY_ESC:
+                       return;
+               case -ERRDISPLAYTOOSMALL:
                        return;
                }
        }
@@ -823,35 +767,36 @@ static void conf_string(struct menu *menu)
        const char *prompt = menu_get_prompt(menu);
 
        while (1) {
+               int res;
                char *heading;
 
                switch (sym_get_type(menu->sym)) {
                case S_INT:
-                       heading = (char *) inputbox_instructions_int;
+                       heading = _(inputbox_instructions_int);
                        break;
                case S_HEX:
-                       heading = (char *) inputbox_instructions_hex;
+                       heading = _(inputbox_instructions_hex);
                        break;
                case S_STRING:
-                       heading = (char *) inputbox_instructions_string;
+                       heading = _(inputbox_instructions_string);
                        break;
                default:
                        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:
                        if (sym_set_string_value(menu->sym, dialog_input_result))
                                return;
-                       show_textbox(NULL, "You have made an invalid entry.", 5, 43);
+                       show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
                        break;
                case 1:
                        show_help(menu);
                        break;
-               case 255:
+               case KEY_ESC:
                        return;
                }
        }
@@ -859,20 +804,24 @@ static void conf_string(struct menu *menu)
 
 static void conf_load(void)
 {
+
        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:
                        if (!dialog_input_result[0])
                                return;
                        if (!conf_read(dialog_input_result))
                                return;
-                       show_textbox(NULL, "File does not exist!", 5, 38);
+                       show_textbox(NULL, _("File does not exist!"), 5, 38);
                        break;
                case 1:
-                       show_helptext("Load Alternate Configuration", load_config_help);
+                       show_helptext(_("Load Alternate Configuration"), load_config_help);
                        break;
-               case 255:
+               case KEY_ESC:
                        return;
                }
        }
@@ -881,19 +830,22 @@ static void conf_load(void)
 static void conf_save(void)
 {
        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:
                        if (!dialog_input_result[0])
                                return;
                        if (!conf_write(dialog_input_result))
                                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;
                case 1:
-                       show_helptext("Save Alternate Configuration", save_config_help);
+                       show_helptext(_("Save Alternate Configuration"), save_config_help);
                        break;
-               case 255:
+               case KEY_ESC:
                        return;
                }
        }
@@ -902,42 +854,25 @@ static void conf_save(void)
 static void conf_cleanup(void)
 {
        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)
 {
+       struct symbol *sym;
        char *mode;
-       int stat;
+       int res;
+
+       setlocale(LC_ALL, "");
+       bindtextdomain(PACKAGE, LOCALEDIR);
+       textdomain(PACKAGE);
 
        conf_parse(av[1]);
        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");
        if (mode) {
@@ -948,26 +883,42 @@ int main(int ac, char **av)
        tcgetattr(1, &ios_org);
        atexit(conf_cleanup);
        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 {
-               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();
 
-       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"
-                       "*** 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();
 }
index 0c13156f33441fc8fc787b92ab038b752c87a563..c86c27f2c76135f4b69d4f24149f6559e72370fb 100644 (file)
@@ -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;
+       return current_menu = current_entry;
 }
 
 void menu_end_menu(void)
@@ -113,7 +114,7 @@ void menu_set_type(int type)
                sym->type = type;
                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_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);
 
        prop->menu = current_entry;
-       prop->text = prompt;
        prop->expr = expr;
        prop->visible.expr = menu_check_dep(dep);
 
        if (prompt) {
+               if (isspace(*prompt)) {
+                       prop_warn(prop, "leading whitespace ignored");
+                       while (isspace(*prompt))
+                               prompt++;
+               }
                if (current_entry->prompt)
-                       menu_warn(current_entry, "prompt redefined\n");
+                       prop_warn(prop, "prompt redefined");
                current_entry->prompt = prop;
        }
+       prop->text = prompt;
 
        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)
@@ -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);
 }
 
+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)
 {
        struct property *prop;
@@ -185,8 +215,8 @@ void sym_check_prop(struct symbol *sym)
                        if (sym->type != S_INT && sym->type != S_HEX)
                                prop_warn(prop, "range is only allowed "
                                                "for int or hex symbols");
-                       if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
-                           !sym_string_valid(sym, prop->expr->right.sym->name))
+                       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");
                        break;
                default:
@@ -318,11 +348,10 @@ void menu_finalize(struct menu *parent)
 
        if (sym && !(sym->flags & SYMBOL_WARNED)) {
                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)
-                       menu_warn(parent, "choice must have a prompt\n");
+                       menu_warn(parent, "choice must have a prompt");
 
                /* Check properties connected to this symbol */
                sym_check_prop(sym);
@@ -365,9 +394,9 @@ bool menu_is_visible(struct menu *menu)
 const char *menu_get_prompt(struct menu *menu)
 {
        if (menu->prompt)
-               return menu->prompt->text;
+               return _(menu->prompt->text);
        else if (menu->sym)
-               return menu->sym->name;
+               return _(menu->sym->name);
        return NULL;
 }
 
diff --git a/package/config/qconf.cc b/package/config/qconf.cc
new file mode 100644 (file)
index 0000000..512c2f5
--- /dev/null
@@ -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;
+}
diff --git a/package/config/qconf.h b/package/config/qconf.h
new file mode 100644 (file)
index 0000000..6fc1c5f
--- /dev/null
@@ -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;
+};
index ea629728ac1713ee4f59744a66bbee9c8dc84444..9fbe737febda4dd69fc0247cbe7067d6610749c5 100644 (file)
 struct symbol symbol_yes = {
        .name = "y",
        .curr = { "y", yes },
-       .flags = SYMBOL_YES|SYMBOL_VALID,
+       .flags = SYMBOL_CONST|SYMBOL_VALID,
 }, symbol_mod = {
        .name = "m",
        .curr = { "m", mod },
-       .flags = SYMBOL_MOD|SYMBOL_VALID,
+       .flags = SYMBOL_CONST|SYMBOL_VALID,
 }, symbol_no = {
        .name = "n",
        .curr = { "n", no },
-       .flags = SYMBOL_NO|SYMBOL_VALID,
+       .flags = SYMBOL_CONST|SYMBOL_VALID,
 }, symbol_empty = {
        .name = "",
        .curr = { "", no },
        .flags = SYMBOL_VALID,
 };
 
-int sym_change_count;
+struct symbol *sym_defconfig_list;
 struct symbol *modules_sym;
 tristate modules_val;
 
@@ -44,6 +44,7 @@ void sym_add_default(struct symbol *sym, const char *def)
 void sym_init(void)
 {
        struct symbol *sym;
+       struct utsname uts;
        char *p;
        static bool inited = false;
 
@@ -51,20 +52,26 @@ void sym_init(void)
                return;
        inited = true;
 
-       sym = sym_lookup("VERSION", 0);
+       uname(&uts);
+
+       sym = sym_lookup("ARCH", 0);
        sym->type = S_STRING;
        sym->flags |= SYMBOL_AUTO;
-       p = getenv("VERSION");
+       p = getenv("ARCH");
        if (p)
                sym_add_default(sym, p);
 
-       sym = sym_lookup("TARGET_ARCH", 0);
+       sym = sym_lookup("VERSION", 0);
        sym->type = S_STRING;
        sym->flags |= SYMBOL_AUTO;
-       p = getenv("TARGET_ARCH");
+       p = getenv("VERSION");
        if (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)
@@ -134,6 +141,55 @@ struct property *sym_get_range_prop(struct symbol *sym)
        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)
 {
        struct property *prop;
@@ -171,7 +227,7 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
        struct expr *e;
 
        /* is the user choice visible? */
-       def_sym = sym->user.val;
+       def_sym = sym->def[S_DEF_USER].val;
        if (def_sym) {
                sym_calc_visibility(def_sym);
                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) {
                        sym->flags |= SYMBOL_WRITE;
                        if (sym_has_value(sym))
-                               newval.tri = sym->user.tri;
+                               newval.tri = sym->def[S_DEF_USER].tri;
                        else if (!sym_is_choice(sym)) {
                                prop = sym_get_default_prop(sym);
                                if (prop)
@@ -273,7 +329,7 @@ void sym_calc_value(struct symbol *sym)
                if (sym->visible != no) {
                        sym->flags |= SYMBOL_WRITE;
                        if (sym_has_value(sym)) {
-                               newval.val = sym->user.val;
+                               newval.val = sym->def[S_DEF_USER].val;
                                break;
                        }
                }
@@ -294,11 +350,15 @@ void sym_calc_value(struct symbol *sym)
        sym->curr = newval;
        if (sym_is_choice(sym) && newval.tri == yes)
                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);
-       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)) {
                int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
@@ -318,7 +378,7 @@ void sym_clear_all_valid(void)
 
        for_all_symbols(i, sym)
                sym->flags &= ~SYMBOL_VALID;
-       sym_change_count++;
+       sym_add_change_count(1);
        if (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))
                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);
        }
+       /*
+        * 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) {
                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();
-               if (sym == modules_sym)
-                       sym_set_all_changed();
-       }
 
        return true;
 }
@@ -471,8 +539,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
                if (!prop)
                        return true;
                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:
                if (!sym_string_valid(sym, str))
                        return false;
@@ -480,8 +548,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
                if (!prop)
                        return true;
                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_TRISTATE:
                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))
                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);
        }
 
-       oldval = sym->user.val;
+       oldval = sym->def[S_DEF_USER].val;
        size = strlen(newval) + 1;
        if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
                size += 2;
-               sym->user.val = val = malloc(size);
+               sym->def[S_DEF_USER].val = val = malloc(size);
                *val++ = '0';
                *val++ = 'x';
        } else if (!oldval || strcmp(oldval, newval))
-               sym->user.val = val = malloc(size);
+               sym->def[S_DEF_USER].val = val = malloc(size);
        else
                return true;
 
@@ -611,7 +679,6 @@ struct symbol *sym_lookup(const char *name, int isconst)
        memset(symbol, 0, sizeof(*symbol));
        symbol->name = new_name;
        symbol->type = S_UNKNOWN;
-       symbol->flags = SYMBOL_NEW;
        if (isconst)
                symbol->flags |= SYMBOL_CONST;
 
@@ -724,12 +791,12 @@ struct symbol *sym_check_deps(struct symbol *sym)
        struct symbol *sym2;
        struct property *prop;
 
-       if (sym->flags & SYMBOL_CHECK_DONE)
-               return NULL;
        if (sym->flags & SYMBOL_CHECK) {
                printf("Warning! Found recursive dependency: %s", sym->name);
                return sym;
        }
+       if (sym->flags & SYMBOL_CHECKED)
+               return NULL;
 
        sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
        sym2 = sym_check_expr_deps(sym->rev_dep.expr);
@@ -749,8 +816,13 @@ struct symbol *sym_check_deps(struct symbol *sym)
                        goto out;
        }
 out:
-       if (sym2)
+       if (sym2) {
                printf(" %s", sym->name);
+               if (sym2 == sym) {
+                       printf("\n");
+                       sym2 = NULL;
+               }
+       }
        sym->flags &= ~SYMBOL_CHECK;
        return sym2;
 }
index 8f65ccac5158fb113858011019d588faec3eaae9..e3f28b9d59f4723347cc3c941adcfaa7305e119f 100644 (file)
@@ -33,8 +33,8 @@ int file_write_dep(const char *name)
        FILE *out;
 
        if (!name)
-               name = ".config.cmd";
-       out = fopen(".config.tmp", "w");
+               name = ".kconfig.d";
+       out = fopen("..config.tmp", "w");
        if (!out)
                return 1;
        fprintf(out, "deps_config := \\\n");
@@ -44,12 +44,15 @@ int file_write_dep(const char *name)
                else
                        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);
-       rename(".config.tmp", name);
+       rename("..config.tmp", name);
        return 0;
 }
 
+
 /* Allocate initial growable sting */
 struct gstr str_new(void)
 {
@@ -100,7 +103,7 @@ void str_printf(struct gstr *gs, const char *fmt, ...)
        va_end(ap);
 }
 
-/* Retreive value of growable string */
+/* Retrieve value of growable string */
 const char *str_get(struct gstr *gs)
 {
        return gs->s;
diff --git a/package/config/zconf.gperf b/package/config/zconf.gperf
new file mode 100644 (file)
index 0000000..9b44c80
--- /dev/null
@@ -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
+%%
diff --git a/package/config/zconf.hash.c_shipped b/package/config/zconf.hash.c_shipped
new file mode 100644 (file)
index 0000000..47c8b5b
--- /dev/null
@@ -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;
+}
+
index 55517b2877cdb610c57acaae904647e57cfe5d8f..cfa46077c6b43a45dad6d89c60ea5dd274c566cf 100644 (file)
 
 #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;
 
 struct buffer {
@@ -32,29 +36,28 @@ struct buffer *current_buf;
 static int last_ts, first_ts;
 
 static void zconf_endhelp(void);
-static struct buffer *zconf_endfile(void);
+static void zconf_endfile(void);
 
 void new_string(void)
 {
        text = malloc(START_STRSIZE);
        text_asize = START_STRSIZE;
-       text_ptr = text;
        text_size = 0;
-       *text_ptr = 0;
+       *text = 0;
 }
 
 void append_string(const char *str, int size)
 {
        int new_size = text_size + size + 1;
        if (new_size > text_asize) {
+               new_size += START_STRSIZE - 1;
+               new_size &= -START_STRSIZE;
                text = realloc(text, 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_ptr = 0;
+       text[text_size] = 0;
 }
 
 void alloc_string(const char *str, int size)
@@ -72,10 +75,13 @@ n   [A-Za-z0-9_]
        int str = 0;
        int ts, i;
 
-[ \t]*#.*\n    current_file->lineno++;
+[ \t]*#.*\n    |
+[ \t]*\n       {
+       current_file->lineno++;
+       return T_EOL;
+}
 [ \t]*#.*
 
-[ \t]*\n       current_file->lineno++; return T_EOL;
 
 [ \t]+ {
        BEGIN(COMMAND);
@@ -88,42 +94,25 @@ n   [A-Za-z0-9_]
 
 
 <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}+    {
+               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);
                zconflval.string = text;
                return T_WORD;
        }
        .
-       \n      current_file->lineno++; BEGIN(INITIAL);
+       \n      {
+               BEGIN(INITIAL);
+               current_file->lineno++;
+               return T_EOL;
+       }
 }
 
 <PARAM>{
@@ -134,8 +123,6 @@ n   [A-Za-z0-9_]
        "!"     return T_NOT;
        "="     return T_EQUAL;
        "!="    return T_UNEQUAL;
-       "if"    return T_IF;
-       "on"    return T_ON;
        \"|\'   {
                str = yytext[0];
                new_string();
@@ -144,6 +131,11 @@ n  [A-Za-z0-9_]
        \n      BEGIN(INITIAL); current_file->lineno++; return T_EOL;
        ---     /* ignore */
        ({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);
                zconflval.string = text;
                return T_WORD;
@@ -236,9 +228,9 @@ n   [A-Za-z0-9_]
 }
 
 <<EOF>>        {
-       if (current_buf) {
+       if (current_file) {
                zconf_endfile();
-               return T_EOF;
+               return T_EOL;
        }
        fclose(yyin);
        yyterminate();
@@ -329,7 +321,7 @@ void zconf_nextfile(const char *name)
        current_file = file;
 }
 
-static struct buffer *zconf_endfile(void)
+static void zconf_endfile(void)
 {
        struct buffer *parent;
 
@@ -345,22 +337,14 @@ static struct buffer *zconf_endfile(void)
        }
        free(current_buf);
        current_buf = parent;
-
-       return parent;
 }
 
 int zconf_lineno(void)
 {
-       if (current_buf)
-               return current_file->lineno - 1;
-       else
-               return 0;
+       return current_pos.lineno;
 }
 
 char *zconf_curname(void)
 {
-       if (current_buf)
-               return current_file->name;
-       else
-               return "<none>";
+       return current_pos.file ? current_pos.file->name : "<none>";
 }
index ed612a058c96091274bbe16c15be5a19ca3ea230..28e1985ad19041078f9878deead92e336ac619d3 100644 (file)
@@ -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,
-   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
    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
    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
    Bison output file, you may use that output file without restriction.
@@ -36,6 +36,9 @@
 /* Identify Bison output.  */
 #define YYBISON 1
 
+/* Bison version.  */
+#define YYBISON_VERSION "2.1"
+
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 
@@ -45,8 +48,7 @@
 /* Using locations.  */
 #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 yylex   zconflex
 #define yyerror zconferror
      T_REQUIRES = 272,
      T_OPTIONAL = 273,
      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
+/* Tokens.  */
 #define T_MAINMENU 258
 #define T_MENU 259
 #define T_ENDMENU 260
 #define T_REQUIRES 272
 #define T_OPTIONAL 273
 #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
 
 
 
 #include <string.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         0x0001
@@ -170,14 +166,18 @@ int cdebug = PRINTD;
 
 extern int zconflex(void);
 static void zconfprint(const char *err, ...);
+static void zconf_error(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];
 
 static struct menu *current_menu, *current_entry;
 
+#define YYDEBUG 0
+#if YYDEBUG
 #define YYERROR_VERBOSE
+#endif
 
 
 /* Enabling traces.  */
@@ -193,16 +193,22 @@ static struct menu *current_menu, *current_entry;
 # define YYERROR_VERBOSE 0
 #endif
 
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
 
 typedef union YYSTYPE {
-       int token;
        char *string;
+       struct file *file;
        struct symbol *symbol;
        struct expr *expr;
        struct menu *menu;
+       struct kconf_id *id;
 } YYSTYPE;
-/* Line 191 of yacc.c.  */
+/* Line 196 of yacc.c.  */
 
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -214,26 +220,48 @@ typedef union YYSTYPE {
 /* 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
 
 /* 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
-#    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
@@ -242,25 +270,51 @@ typedef union YYSTYPE {
 # ifdef YYSTACK_ALLOC
    /* Pacify GCC's `empty if-body' warning. */
 #  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
-#  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
-#  define YYSTACK_ALLOC malloc
-#  define YYSTACK_FREE free
 # endif
 #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
 
 
 #if (! defined (yyoverflow) \
      && (! defined (__cplusplus) \
-        || (YYSTYPE_IS_TRIVIAL)))
+        || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
-  short yyss;
+  short int yyss;
   YYSTYPE yyvs;
   };
 
@@ -270,20 +324,20 @@ union yyalloc
 /* The size of an array large to enough to hold all stacks, each with
    N elements.  */
 # define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (short) + sizeof (YYSTYPE))                                \
+     ((N) * (sizeof (short int) + sizeof (YYSTYPE))                    \
       + YYSTACK_GAP_MAXIMUM)
 
 /* Copy COUNT objects from FROM to TO.  The source and destination do
    not overlap.  */
 # ifndef YYCOPY
-#  if 1 < __GNUC__
+#  if defined (__GNUC__) && 1 < __GNUC__
 #   define YYCOPY(To, From, Count) \
       __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
 #  else
 #   define YYCOPY(To, From, Count)             \
       do                                       \
        {                                       \
-         register YYSIZE_T yyi;                \
+         YYSIZE_T yyi;                         \
          for (yyi = 0; yyi < (Count); yyi++)   \
            (To)[yyi] = (From)[yyi];            \
        }                                       \
@@ -312,28 +366,28 @@ union yyalloc
 #if defined (__STDC__) || defined (__cplusplus)
    typedef signed char yysigned_char;
 #else
-   typedef short yysigned_char;
+   typedef short int yysigned_char;
 #endif
 
 /* YYFINAL -- State number of the termination state. */
-#define YYFINAL  2
+#define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   201
+#define YYLAST   275
 
 /* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  42
+#define YYNTOKENS  36
 /* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  41
+#define YYNNTS  45
 /* YYNRULES -- Number of rules. */
-#define YYNRULES  104
+#define YYNRULES  110
 /* YYNRULES -- Number of states. */
-#define YYNSTATES  182
+#define YYNSTATES  183
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   296
+#define YYMAXUTOK   290
 
-#define YYTRANSLATE(YYX)                                               \
+#define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* 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,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41
+      35
 };
 
 #if YYDEBUG
 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
    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. */
 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.  */
-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
 
-#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. */
 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
 
 # ifdef YYPRINT
 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
    token YYLEX-NUM.  */
-static const unsigned short yytoknum[] =
+static const unsigned short int yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      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
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 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.  */
 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
@@ -517,169 +575,167 @@ static const unsigned char yyr2[] =
    means the default is an error.  */
 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]. */
-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
    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].  */
-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
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    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
    symbol of state STATE-NUM.  */
 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 yyclearin      (yychar = YYEMPTY)
 #define YYEMPTY                (-2)
@@ -687,7 +743,7 @@ static const unsigned char yystos[] =
 
 #define YYACCEPT       goto yyacceptlab
 #define YYABORT                goto yyabortlab
-#define YYERROR                goto yyerrlab1
+#define YYERROR                goto yyerrorlab
 
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
@@ -709,26 +765,59 @@ do                                                                \
       goto yybackup;                                           \
     }                                                          \
   else                                                         \
-    {                                                          \
-      yyerror ("syntax error: cannot back up");\
+    {                                                          \
+      yyerror (YY_("syntax error: cannot back up")); \
       YYERROR;                                                 \
     }                                                          \
 while (0)
 
+
 #define YYTERROR       1
 #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
-# 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
 
+
+/* 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.  */
 
 #ifdef YYLEX_PARAM
@@ -751,36 +840,30 @@ do {                                              \
     YYFPRINTF Args;                            \
 } 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 {                                                           \
   if (yydebug)                                                 \
     {                                                          \
       YYFPRINTF (stderr, "%s ", Title);                                \
-      yysymprint (stderr,                                      \
-                  Token, Value);       \
+      yysymprint (stderr,                                      \
+                  Type, Value);        \
       YYFPRINTF (stderr, "\n");                                        \
     }                                                          \
 } while (0)
 
 /*------------------------------------------------------------------.
 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (cinluded).                                                   |
+| TOP (included).                                                   |
 `------------------------------------------------------------------*/
 
 #if defined (__STDC__) || defined (__cplusplus)
 static void
-yy_stack_print (short *bottom, short *top)
+yy_stack_print (short int *bottom, short int *top)
 #else
 static void
 yy_stack_print (bottom, top)
-    short *bottom;
-    short *top;
+    short int *bottom;
+    short int *top;
 #endif
 {
   YYFPRINTF (stderr, "Stack now");
@@ -810,13 +893,13 @@ yy_reduce_print (yyrule)
 #endif
 {
   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.  */
   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)         \
@@ -830,8 +913,7 @@ do {                                        \
 int yydebug;
 #else /* !YYDEBUG */
 # 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_REDUCE_PRINT(Rule)
 #endif /* !YYDEBUG */
@@ -846,13 +928,9 @@ int yydebug;
    if the built-in stack extension method is used).
 
    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.  */
 
-#if YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
 #ifndef YYMAXDEPTH
 # define YYMAXDEPTH 10000
 #endif
@@ -874,7 +952,7 @@ yystrlen (yystr)
      const char *yystr;
 #   endif
 {
-  register const char *yys = yystr;
+  const char *yys = yystr;
 
   while (*yys++ != '\0')
     continue;
@@ -899,8 +977,8 @@ yystpcpy (yydest, yysrc)
      const char *yysrc;
 #   endif
 {
-  register char *yyd = yydest;
-  register const char *yys = yysrc;
+  char *yyd = yydest;
+  const char *yys = yysrc;
 
   while ((*yyd++ = *yys++) != '\0')
     continue;
@@ -910,7 +988,55 @@ yystpcpy (yydest, yysrc)
 #  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 */
 
 \f
 
@@ -934,15 +1060,15 @@ yysymprint (yyoutput, yytype, yyvaluep)
   (void) yyvaluep;
 
   if (yytype < YYNTOKENS)
-    {
-      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
-      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
-    }
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
   else
     YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
 
+
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
   switch (yytype)
     {
       default:
@@ -958,10 +1084,11 @@ yysymprint (yyoutput, yytype, yyvaluep)
 
 #if defined (__STDC__) || defined (__cplusplus)
 static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
 #else
 static void
-yydestruct (yytype, yyvaluep)
+yydestruct (yymsg, yytype, yyvaluep)
+    const char *yymsg;
     int yytype;
     YYSTYPE *yyvaluep;
 #endif
@@ -969,8 +1096,42 @@ yydestruct (yytype, yyvaluep)
   /* Pacify ``unused variable'' warnings.  */
   (void) yyvaluep;
 
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
   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:
         break;
@@ -996,10 +1157,10 @@ int yyparse ();
 
 
 
-/* The lookahead symbol.  */
+/* The look-ahead symbol.  */
 int yychar;
 
-/* The semantic value of the lookahead symbol.  */
+/* The semantic value of the look-ahead symbol.  */
 YYSTYPE yylval;
 
 /* Number of syntax errors so far.  */
@@ -1025,17 +1186,17 @@ yyparse (void)
 #else
 int
 yyparse ()
-
+    ;
 #endif
 #endif
 {
   
-  register int yystate;
-  register int yyn;
+  int yystate;
+  int yyn;
   int yyresult;
   /* Number of tokens to shift before error messages enabled.  */
   int yyerrstatus;
-  /* Lookahead token as an internal (translated) token number.  */
+  /* Look-ahead token as an internal (translated) token number.  */
   int yytoken = 0;
 
   /* Three stacks and their tools:
@@ -1047,14 +1208,14 @@ yyparse ()
      to reallocate them elsewhere.  */
 
   /* 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.  */
   YYSTYPE yyvsa[YYINITDEPTH];
   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
           memory.  */
        YYSTYPE *yyvs1 = yyvs;
-       short *yyss1 = yyss;
+       short int *yyss1 = yyss;
 
 
        /* Each stack pointer address is followed by the size of the
           data in use in that stack, in bytes.  This used to be a
           conditional around just the two extra args, but that might
           be undefined if yyoverflow is a macro.  */
-       yyoverflow ("parser stack overflow",
+       yyoverflow (YY_("memory exhausted"),
                    &yyss1, yysize * sizeof (*yyssp),
                    &yyvs1, yysize * sizeof (*yyvsp),
 
@@ -1129,21 +1290,21 @@ yyparse ()
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
-      goto yyoverflowlab;
+      goto yyexhaustedlab;
 # else
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-       goto yyoverflowlab;
+       goto yyexhaustedlab;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
        yystacksize = YYMAXDEPTH;
 
       {
-       short *yyss1 = yyss;
+       short int *yyss1 = yyss;
        union yyalloc *yyptr =
          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
        if (! yyptr)
-         goto yyoverflowlab;
+         goto yyexhaustedlab;
        YYSTACK_RELOCATE (yyss);
        YYSTACK_RELOCATE (yyvs);
 
@@ -1175,18 +1336,18 @@ yyparse ()
 yybackup:
 
 /* 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: */
 
-  /* 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];
   if (yyn == YYPACT_NINF)
     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)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
@@ -1201,7 +1362,7 @@ yybackup:
   else
     {
       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
@@ -1221,8 +1382,8 @@ yybackup:
   if (yyn == YYFINAL)
     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.  */
   if (yychar != YYEOF)
@@ -1273,35 +1434,47 @@ yyreduce:
     {
         case 8:
 
-    { zconfprint("unexpected 'endmenu' statement"); ;}
+    { zconf_error("unexpected end statement"); ;}
     break;
 
   case 9:
 
-    { zconfprint("unexpected 'endif' statement"); ;}
+    { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); ;}
     break;
 
   case 10:
 
-    { zconfprint("unexpected 'endchoice' statement"); ;}
+    {
+       zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name);
+;}
     break;
 
   case 11:
 
-    { zconfprint("syntax error"); yyerrok; ;}
+    { zconf_error("invalid statement"); ;}
     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;
        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;
 
-  case 19:
+  case 28:
 
     {
        menu_end_entry();
@@ -1309,17 +1482,17 @@ yyreduce:
 ;}
     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;
        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;
 
-  case 21:
+  case 30:
 
     {
        if (current_entry->prompt)
@@ -1331,97 +1504,75 @@ yyreduce:
 ;}
     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;
 
-  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;
 
-  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;
 
-  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;
 
-  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;
 
-  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;
 
-  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;
 
-  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;
 
-  case 38:
+  case 48:
 
     {
        struct symbol *sym = sym_lookup(NULL, 0);
@@ -1432,57 +1583,45 @@ yyreduce:
 ;}
     break;
 
-  case 39:
+  case 49:
 
     {
-       menu_end_entry();
-       menu_add_menu();
+       (yyval.menu) = menu_add_menu();
 ;}
     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();
                printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
        }
 ;}
     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());
 ;}
     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;
 
-  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;
@@ -1490,115 +1629,89 @@ yyreduce:
 ;}
     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;
 
-  case 55:
+  case 64:
 
     {
        printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
        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;
 
-  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();
                printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
        }
 ;}
     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_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());
 ;}
     break;
 
-  case 64:
+  case 72:
 
     {
-       menu_end_entry();
-       menu_add_menu();
+       (yyval.menu) = menu_add_menu();
 ;}
     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();
                printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
        }
 ;}
     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;
 
-  case 75:
+  case 80:
 
     {
        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());
 ;}
     break;
 
-  case 76:
+  case 81:
 
     {
        menu_end_entry();
 ;}
     break;
 
-  case 77:
+  case 82:
 
     {
        printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
@@ -1606,118 +1719,119 @@ yyreduce:
 ;}
     break;
 
-  case 78:
+  case 83:
 
     {
-       current_entry->sym->help = yyvsp[0].string;
+       current_entry->sym->help = (yyvsp[0].string);
 ;}
     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());
 ;}
     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());
 ;}
     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());
 ;}
     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;
 
-  case 89:
+  case 95:
 
-    { yyval.token = T_ENDMENU; ;}
+    { (yyval.id) = (yyvsp[-1].id); ;}
     break;
 
-  case 90:
+  case 96:
 
-    { yyval.token = T_ENDCHOICE; ;}
+    { (yyval.id) = (yyvsp[-1].id); ;}
     break;
 
-  case 91:
+  case 97:
 
-    { yyval.token = T_ENDIF; ;}
+    { (yyval.id) = (yyvsp[-1].id); ;}
     break;
 
-  case 94:
+  case 100:
 
-    { yyval.expr = NULL; ;}
+    { (yyval.expr) = NULL; ;}
     break;
 
-  case 95:
+  case 101:
 
-    { yyval.expr = yyvsp[0].expr; ;}
+    { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
-  case 96:
+  case 102:
 
-    { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); ;}
+    { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;}
     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;
 
-  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;
 
-  case 99:
+  case 105:
 
-    { yyval.expr = yyvsp[-1].expr; ;}
+    { (yyval.expr) = (yyvsp[-1].expr); ;}
     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;
 
-  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;
 
-  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;
 
-  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;
 
-  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;
 
 
+      default: break;
     }
 
-/* Line 999 of yacc.c.  */
+/* Line 1126 of yacc.c.  */
 
 \f
   yyvsp -= yylen;
@@ -1757,87 +1871,152 @@ yyerrlab:
 
       if (YYPACT_NINF < yyn && yyn < YYLAST)
        {
-         YYSIZE_T yysize = 0;
          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
             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)
-             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);
              YYSTACK_FREE (yymsg);
            }
          else
-           yyerror ("syntax error; also virtual memory exhausted");
+           {
+             yyerror (YY_("syntax error"));
+             goto yyexhaustedlab;
+           }
        }
       else
 #endif /* YYERROR_VERBOSE */
-       yyerror ("syntax error");
+       yyerror (YY_("syntax error"));
     }
 
 
 
   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.  */
 
-      /* 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.  */
   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:
   yyerrstatus = 3;     /* Each real token shifted decrements this.  */
 
@@ -1859,22 +2038,22 @@ yyerrlab1:
       if (yyssp == yyss)
        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);
     }
 
   if (yyn == YYFINAL)
     YYACCEPT;
 
-  YYDPRINTF ((stderr, "Shifting error token, "));
-
   *++yyvsp = yylval;
 
 
+  /* Shift the error token. */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
   yystate = yyn;
   goto yynewstate;
 
@@ -1894,16 +2073,25 @@ yyabortlab:
   goto yyreturn;
 
 #ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here.  |
-`----------------------------------------------*/
-yyoverflowlab:
-  yyerror ("parser stack overflow");
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
   yyresult = 2;
   /* Fall through.  */
 #endif
 
 yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+                yytoken, &yylval);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                 yystos[*yyssp], yyvsp);
+      YYPOPSTACK;
+    }
 #ifndef yyoverflow
   if (yyss != yyssa)
     YYSTACK_FREE (yyss);
@@ -1924,22 +2112,30 @@ void conf_parse(const char *name)
 
        sym_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();
        if (zconfnerrs)
                exit(1);
+       if (!modules_sym->prop) {
+               struct property *prop;
+
+               prop = prop_alloc(P_DEFAULT, modules_sym);
+               prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
+       }
        menu_finalize(&rootmenu);
        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)
@@ -1951,20 +2147,25 @@ const char *zconf_tokenname(int token)
        case T_ENDCHOICE:       return "endchoice";
        case T_IF:              return "if";
        case T_ENDIF:           return "endif";
+       case T_DEPENDS:         return "depends";
        }
        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++;
                return false;
        }
        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++;
                return false;
        }
@@ -1975,7 +2176,19 @@ static void zconfprint(const char *err, ...)
 {
        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);
        vfprintf(stderr, err, ap);
        va_end(ap);
@@ -1984,7 +2197,9 @@ static void zconfprint(const char *err, ...)
 
 static void zconferror(const char *err)
 {
+#if YYDEBUG
        fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+#endif
 }
 
 void print_quoted_string(FILE *out, const char *str)
index bc9431831fc62dc135f0441c75fe3a98c5469047..438fe4bed6530613e3563e98173437ad0609d443 100644 (file)
 #include <string.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         0x0001
@@ -20,61 +25,60 @@ int cdebug = PRINTD;
 
 extern int zconflex(void);
 static void zconfprint(const char *err, ...);
+static void zconf_error(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];
 
 static struct menu *current_menu, *current_entry;
 
+#define YYDEBUG 0
+#if YYDEBUG
 #define YYERROR_VERBOSE
+#endif
 %}
-%expect 40
+%expect 26
 
 %union
 {
-       int token;
        char *string;
+       struct file *file;
        struct symbol *symbol;
        struct expr *expr;
        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 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_QUOTE
 %token T_UNEQUAL
-%token T_EOF
-%token T_EOL
 %token T_CLOSE_PAREN
 %token T_OPEN_PAREN
-%token T_ON
-%token T_SELECT
-%token T_RANGE
+%token T_EOL
 
 %left T_OR
 %left T_AND
@@ -82,38 +86,55 @@ static struct menu *current_menu, *current_entry;
 %nonassoc T_NOT
 
 %type <string> prompt
-%type <string> source
 %type <symbol> symbol
 %type <expr> 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
        | config_stmt
        | menuconfig_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:
          /* empty */
        | config_option_list config_option
+       | config_option_list symbol_option
        | config_option_list depends
        | config_option_list help
+       | config_option_list option_error
        | 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
@@ -212,7 +199,11 @@ config_option: T_PROMPT prompt if_expr T_EOL
 config_option: T_DEFAULT expr if_expr T_EOL
 {
        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
@@ -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());
 };
 
+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: T_CHOICE T_EOL
@@ -240,8 +251,7 @@ choice: T_CHOICE T_EOL
 
 choice_entry: choice choice_option_list
 {
-       menu_end_entry();
-       menu_add_menu();
+       $$ = menu_add_menu();
 };
 
 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:
          /* empty */
@@ -266,6 +271,7 @@ choice_option_list:
        | choice_option_list depends
        | choice_option_list help
        | choice_option_list T_EOL
+       | choice_option_list option_error
 ;
 
 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());
 };
 
-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
@@ -294,24 +299,27 @@ choice_option: T_OPTIONAL 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:
          /* empty */
-       | choice_block common_block
+       | choice_block common_stmt
 ;
 
 /* 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());
        menu_add_entry(NULL);
        menu_add_dep($2);
-       menu_end_entry();
-       menu_add_menu();
+       $$ = menu_add_menu();
 };
 
 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:
          /* empty */
-       | if_block common_block
+       | if_block common_stmt
        | if_block menu_stmt
        | if_block choice_stmt
 ;
@@ -342,14 +345,13 @@ if_block:
 menu: T_MENU prompt T_EOL
 {
        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());
 };
 
 menu_entry: menu depends_list
 {
-       menu_end_entry();
-       menu_add_menu();
+       $$ = menu_add_menu();
 };
 
 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:
          /* empty */
-       | menu_block common_block
+       | menu_block common_stmt
        | menu_block menu_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);
-};
-
-source_stmt: source
-{
-       zconf_nextfile($1);
+       zconf_nextfile($2);
 };
 
 /* comment entry */
@@ -392,7 +383,7 @@ source_stmt: source
 comment: T_COMMENT prompt T_EOL
 {
        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());
 };
 
@@ -416,9 +407,11 @@ help: help_start T_HELPTEXT
 
 /* 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
@@ -443,20 +436,22 @@ prompt_stmt_opt:
          /* empty */
        | prompt if_expr
 {
-       menu_add_prop(P_PROMPT, $1, NULL, $2);
+       menu_add_prompt(P_PROMPT, $1, $2);
 };
 
 prompt:          T_WORD
        | 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; }
        | T_IF expr                     { $$ = $2; }
@@ -486,22 +481,30 @@ void conf_parse(const char *name)
 
        sym_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();
        if (zconfnerrs)
                exit(1);
+       if (!modules_sym->prop) {
+               struct property *prop;
+
+               prop = prop_alloc(P_DEFAULT, modules_sym);
+               prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
+       }
        menu_finalize(&rootmenu);
        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)
@@ -513,20 +516,25 @@ const char *zconf_tokenname(int token)
        case T_ENDCHOICE:       return "endchoice";
        case T_IF:              return "if";
        case T_ENDIF:           return "endif";
+       case T_DEPENDS:         return "depends";
        }
        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++;
                return false;
        }
        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++;
                return false;
        }
@@ -537,7 +545,19 @@ static void zconfprint(const char *err, ...)
 {
        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);
        vfprintf(stderr, err, ap);
        va_end(ap);
@@ -546,7 +566,9 @@ static void zconfprint(const char *err, ...)
 
 static void zconferror(const char *err)
 {
+#if YYDEBUG
        fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+#endif
 }
 
 void print_quoted_string(FILE *out, const char *str)