Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild
Linus Torvalds [Mon, 26 Jun 2006 18:05:15 +0000 (11:05 -0700)]
* git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild: (40 commits)
  kbuild: trivial fixes in Makefile
  kbuild: adding symbols in Kconfig and defconfig to TAGS
  kbuild: replace abort() with exit(1)
  kbuild: support for %.symtypes files
  kbuild: fix silentoldconfig recursion
  kbuild: add option for stripping modules while installing them
  kbuild: kill some false positives from modpost
  kbuild: export-symbol usage report generator
  kbuild: fix make -rR breakage
  kbuild: append -dirty for updated but uncommited changes
  kbuild: append git revision for all untagged commits
  kbuild: fix module.symvers parsing in modpost
  kbuild: ignore make's built-in rules & variables
  kbuild: bugfix with initramfs
  kbuild: modpost build fix
  kbuild: check license compatibility when building modules
  kbuild: export-type enhancement to modpost.c
  kbuild: add dependency on kernel.release to the package targets
  kbuild: `make kernelrelease' speedup
  kconfig: KCONFIG_OVERWRITECONFIG
  ...

48 files changed:
Documentation/kbuild/makefiles.txt
Makefile
arch/arm/Makefile
arch/sh/Makefile
arch/xtensa/Makefile
drivers/mtd/Kconfig
drivers/mtd/maps/Kconfig
drivers/scsi/Kconfig
include/linux/license.h [new file with mode: 0644]
init/Kconfig
kernel/module.c
scripts/Kbuild.include
scripts/Makefile.build
scripts/Makefile.host
scripts/Makefile.lib
scripts/Makefile.modinst
scripts/Makefile.modpost
scripts/basic/Makefile
scripts/basic/split-include.c [deleted file]
scripts/export_report.pl [new file with mode: 0644]
scripts/genksyms/genksyms.c
scripts/genksyms/genksyms.h
scripts/genksyms/lex.c_shipped
scripts/genksyms/lex.l
scripts/kconfig/conf.c
scripts/kconfig/confdata.c
scripts/kconfig/expr.c
scripts/kconfig/expr.h
scripts/kconfig/gconf.c
scripts/kconfig/lex.zconf.c_shipped
scripts/kconfig/lkc.h
scripts/kconfig/lkc_proto.h
scripts/kconfig/menu.c
scripts/kconfig/qconf.cc
scripts/kconfig/qconf.h
scripts/kconfig/symbol.c
scripts/kconfig/util.c
scripts/kconfig/zconf.gperf
scripts/kconfig/zconf.hash.c_shipped
scripts/kconfig/zconf.tab.c_shipped
scripts/kconfig/zconf.y
scripts/mod/mk_elfconfig.c
scripts/mod/modpost.c
scripts/mod/modpost.h
scripts/package/mkspec
scripts/setlocalversion
sound/oss/Kconfig
usr/Makefile

index a9c00fa..14ef386 100644 (file)
@@ -1123,6 +1123,14 @@ The top Makefile exports the following variables:
        $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE).  The user may
        override this value on the command line if desired.
 
+    INSTALL_MOD_STRIP
+
+       If this variable is specified, will cause modules to be stripped
+       after they are installed.  If INSTALL_MOD_STRIP is '1', then the
+       default option --strip-debug will be used.  Otherwise,
+       INSTALL_MOD_STRIP will used as the option(s) to the strip command.
+
+
 === 8 Makefile language
 
 The kernel Makefiles are designed to run with GNU Make.  The Makefiles
index 1700d3f..e9560c6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -71,7 +71,7 @@ endif
 # In both cases the working directory must be the root of the kernel src.
 # 1) O=
 # Use "make O=dir/to/store/output/files/"
-# 
+#
 # 2) Set KBUILD_OUTPUT
 # Set the environment variable KBUILD_OUTPUT to point to the directory
 # where the output files shall be placed.
@@ -178,18 +178,20 @@ CROSS_COMPILE     ?=
 # Architecture as present in compile.h
 UTS_MACHINE := $(ARCH)
 
+KCONFIG_CONFIG ?= .config
+
 # SHELL used by kbuild
 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
          else if [ -x /bin/bash ]; then echo /bin/bash; \
          else echo sh; fi ; fi)
 
-HOSTCC         = gcc
-HOSTCXX        = g++
-HOSTCFLAGS     = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
-HOSTCXXFLAGS   = -O2
+HOSTCC       = gcc
+HOSTCXX      = g++
+HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+HOSTCXXFLAGS = -O2
 
-#      Decide whether to build built-in, modular, or both.
-#      Normally, just do built-in.
+# Decide whether to build built-in, modular, or both.
+# Normally, just do built-in.
 
 KBUILD_MODULES :=
 KBUILD_BUILTIN := 1
@@ -197,7 +199,7 @@ KBUILD_BUILTIN := 1
 #      If we have only "make modules", don't compile built-in objects.
 #      When we're building modules with modversions, we need to consider
 #      the built-in objects during the descend as well, in order to
-#      make sure the checksums are uptodate before we record them.
+#      make sure the checksums are up to date before we record them.
 
 ifeq ($(MAKECMDGOALS),modules)
   KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
@@ -230,7 +232,7 @@ export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
 #
 # If $(quiet) is empty, the whole command will be printed.
 # If it is set to "quiet_", only the short version will be printed. 
-# If it is set to "silent_", nothing wil be printed at all, since
+# If it is set to "silent_", nothing will be printed at all, since
 # the variable $(silent_cmd_cc_o_c) doesn't exist.
 #
 # A simple variant is to prefix commands with $(Q) - that's useful
@@ -265,10 +267,9 @@ MAKEFLAGS += --include-dir=$(srctree)
 # We need some generic definitions
 include  $(srctree)/scripts/Kbuild.include
 
-# For maximum performance (+ possibly random breakage, uncomment
-# the following)
-
-#MAKEFLAGS += -rR
+# Do not use make's built-in rules and variables
+# This increases performance and avoid hard-to-debug behavour
+MAKEFLAGS += -rR
 
 # Make variables (CC, etc...)
 
@@ -305,21 +306,21 @@ LINUXINCLUDE    := -Iinclude \
 
 CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
-CFLAGS                 := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-                  -fno-strict-aliasing -fno-common
-AFLAGS         := -D__ASSEMBLY__
+CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
+                   -fno-strict-aliasing -fno-common
+AFLAGS          := -D__ASSEMBLY__
 
-# Read KERNELRELEASE from .kernelrelease (if it exists)
-KERNELRELEASE = $(shell cat .kernelrelease 2> /dev/null)
+# Read KERNELRELEASE from include/config/kernel.release (if it exists)
+KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
 KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
-export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION \
-       ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
-       CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
-       HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
+export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
+export ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
+export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
+export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 
 export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
-export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE 
+export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
 export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
 
 # When compiling out-of-tree modules, put MODVERDIR in the module
@@ -357,12 +358,13 @@ endif
 # catch them early, and hand them over to scripts/kconfig/Makefile
 # It is allowed to specify more targets when calling make, including
 # mixing *config targets and build targets.
-# For example 'make oldconfig all'. 
+# For example 'make oldconfig all'.
 # Detect when mixed targets is specified, and make a second invocation
 # of make so .config is not included in this case either (for *config).
 
 no-dot-config-targets := clean mrproper distclean \
-                        cscope TAGS tags help %docs check%
+                        cscope TAGS tags help %docs check% \
+                        kernelrelease kernelversion
 
 config-targets := 0
 mixed-targets  := 0
@@ -404,9 +406,8 @@ include $(srctree)/arch/$(ARCH)/Makefile
 export KBUILD_DEFCONFIG
 
 config %config: scripts_basic outputmakefile FORCE
-       $(Q)mkdir -p include/linux
+       $(Q)mkdir -p include/linux include/config
        $(Q)$(MAKE) $(build)=scripts/kconfig $@
-       $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
 
 else
 # ===========================================================================
@@ -416,13 +417,11 @@ else
 ifeq ($(KBUILD_EXTMOD),)
 # Additional helpers built in scripts/
 # Carefully list dependencies so we do not try to build scripts twice
-# in parrallel
+# in parallel
 PHONY += scripts
-scripts: scripts_basic include/config/MARKER
+scripts: scripts_basic include/config/auto.conf
        $(Q)$(MAKE) $(build)=$(@)
 
-scripts_basic: include/linux/autoconf.h
-
 # Objects we will link into vmlinux / subdirs we need to visit
 init-y         := init/
 drivers-y      := drivers/ sound/
@@ -436,31 +435,32 @@ ifeq ($(dot-config),1)
 
 # Read in dependencies to all Kconfig* files, make sure to run
 # oldconfig if changes are detected.
--include .kconfig.d
+-include include/config/auto.conf.cmd
+-include include/config/auto.conf
 
-include .config
-
-# If .config needs to be updated, it will be done via the dependency
-# that autoconf has on .config.
 # To avoid any implicit rule to kick in, define an empty command
-.config .kconfig.d: ;
+$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
 
-# If .config is newer than include/linux/autoconf.h, someone tinkered
+# If .config is newer than include/config/auto.conf, someone tinkered
 # with it and forgot to run make oldconfig.
-# If kconfig.d is missing then we are probarly in a cleaned tree so
+# if auto.conf.cmd is missing then we are probably in a cleaned tree so
 # we execute the config step to be sure to catch updated Kconfig files
-include/linux/autoconf.h: .kconfig.d .config
-       $(Q)mkdir -p include/linux
+include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
+ifeq ($(KBUILD_EXTMOD),)
        $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
 else
+       $(error kernel configuration not valid - run 'make prepare' in $(srctree) to update it)
+endif
+
+else
 # Dummy target needed, because used as prerequisite
-include/linux/autoconf.h: ;
+include/config/auto.conf: ;
 endif
 
 # The all: target is the default when no target is given on the
 # command line.
 # This allow a user to issue only 'make' to build a kernel including modules
-# Defaults vmlinux but it is usually overriden in the arch makefile
+# Defaults vmlinux but it is usually overridden in the arch makefile
 all: vmlinux
 
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
@@ -492,11 +492,11 @@ CHECKFLAGS     += $(NOSTDINC_FLAGS)
 # warn about C99 declaration after statement
 CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
 
-# disable pointer signedness warnings in gcc 4.0
+# disable pointer signed / unsigned warnings in gcc 4.0
 CFLAGS += $(call cc-option,-Wno-pointer-sign,)
 
 # Default kernel image to build when no specific target is given.
-# KBUILD_IMAGE may be overruled on the commandline or
+# KBUILD_IMAGE may be overruled on the command line or
 # set in the environment
 # Also any assignments in arch/$(ARCH)/Makefile take precedence over
 # this default value
@@ -510,12 +510,29 @@ export    INSTALL_PATH ?= /boot
 #
 # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
 # relocations required by build roots.  This is not defined in the
-# makefile but the arguement can be passed to make if needed.
+# makefile but the argument can be passed to make if needed.
 #
 
 MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
 export MODLIB
 
+#
+#  INSTALL_MOD_STRIP, if defined, will cause modules to be
+#  stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
+#  the default option --strip-debug will be used.  Otherwise,
+#  INSTALL_MOD_STRIP will used as the options to the strip command.
+
+ifdef INSTALL_MOD_STRIP
+ifeq ($(INSTALL_MOD_STRIP),1)
+mod_strip_cmd = $STRIP) --strip-debug
+else
+mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
+endif # INSTALL_MOD_STRIP=1
+else
+mod_strip_cmd = true
+endif # INSTALL_MOD_STRIP
+export mod_strip_cmd
+
 
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
@@ -539,7 +556,7 @@ libs-y              := $(libs-y1) $(libs-y2)
 
 # Build vmlinux
 # ---------------------------------------------------------------------------
-# vmlinux is build from the objects selected by $(vmlinux-init) and
+# vmlinux is built from the objects selected by $(vmlinux-init) and
 # $(vmlinux-main). Most are built-in.o files from top-level directories
 # in the kernel tree, others are specified in arch/$(ARCH)Makefile.
 # Ordering when linking is important, and $(vmlinux-init) must be first.
@@ -590,7 +607,7 @@ quiet_cmd_vmlinux_version = GEN     .version
        $(MAKE) $(build)=init
 
 # Generate System.map
-quiet_cmd_sysmap = SYSMAP 
+quiet_cmd_sysmap = SYSMAP
       cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
 
 # Link of vmlinux
@@ -719,7 +736,7 @@ $(vmlinux-dirs): prepare scripts
        $(Q)$(MAKE) $(build)=$@
 
 # Build the kernel release string
-# The KERNELRELEASE is stored in a file named .kernelrelease
+# The KERNELRELEASE is stored in a file named include/config/kernel.release
 # to be used when executing for example make install or make modules_install
 #
 # Take the contents of any files called localversion* and the config
@@ -737,10 +754,10 @@ _localver = $(foreach f, $(__localver), $(if $(findstring ~, $(f)),,$(f)))
 localver = $(subst $(space),, \
           $(shell cat /dev/null $(_localver)) \
           $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
-              
+
 # If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
 # and if the SCM is know a tag from the SCM is appended.
-# The appended tag is determinded by the SCM used.
+# The appended tag is determined by the SCM used.
 #
 # Currently, only git is supported.
 # Other SCMs can edit scripts/setlocalversion and add the appropriate
@@ -753,9 +770,9 @@ endif
 
 localver-full = $(localver)$(localver-auto)
 
-# Store (new) KERNELRELASE string in .kernelrelease
+# Store (new) KERNELRELASE string in include/config/kernel.release
 kernelrelease = $(KERNELVERSION)$(localver-full)
-.kernelrelease: FORCE
+include/config/kernel.release: include/config/auto.conf FORCE
        $(Q)rm -f $@
        $(Q)echo $(kernelrelease) > $@
 
@@ -776,10 +793,10 @@ PHONY += prepare-all
 # and if so do:
 # 1) Check that make has not been executed in the kernel src $(srctree)
 # 2) Create the include2 directory, used for the second asm symlink
-prepare3: .kernelrelease
+prepare3: include/config/kernel.release
 ifneq ($(KBUILD_SRC),)
        @echo '  Using $(srctree) as source for kernel'
-       $(Q)if [ -f $(srctree)/.config ]; then \
+       $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
                echo "  $(srctree) is not clean, please run 'make mrproper'";\
                echo "  in the '$(srctree)' directory.";\
                /bin/false; \
@@ -792,7 +809,7 @@ endif
 prepare2: prepare3 outputmakefile
 
 prepare1: prepare2 include/linux/version.h include/asm \
-                   include/config/MARKER
+                   include/config/auto.conf
 ifneq ($(KBUILD_MODULES),)
        $(Q)mkdir -p $(MODVERDIR)
        $(Q)rm -f $(MODVERDIR)/*
@@ -806,27 +823,20 @@ prepare0: archprepare FORCE
 # All the preparing..
 prepare prepare-all: prepare0
 
-#      Leave this as default for preprocessing vmlinux.lds.S, which is now
-#      done in arch/$(ARCH)/kernel/Makefile
+# Leave this as default for preprocessing vmlinux.lds.S, which is now
+# done in arch/$(ARCH)/kernel/Makefile
 
 export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
 
-#      FIXME: The asm symlink changes when $(ARCH) changes. That's
-#      hard to detect, but I suppose "make mrproper" is a good idea
-#      before switching between archs anyway.
+# FIXME: The asm symlink changes when $(ARCH) changes. That's
+# hard to detect, but I suppose "make mrproper" is a good idea
+# before switching between archs anyway.
 
 include/asm:
        @echo '  SYMLINK $@ -> include/asm-$(ARCH)'
        $(Q)if [ ! -d include ]; then mkdir -p include; fi;
        @ln -fsn asm-$(ARCH) $@
 
-#      Split autoconf.h into include/linux/config/*
-
-include/config/MARKER: scripts/basic/split-include include/linux/autoconf.h
-       @echo '  SPLIT   include/linux/autoconf.h -> include/config/*'
-       @scripts/basic/split-include include/linux/autoconf.h include/config
-       @touch $@
-
 # Generate some files
 # ---------------------------------------------------------------------------
 
@@ -846,7 +856,7 @@ define filechk_version.h
        )
 endef
 
-include/linux/version.h: $(srctree)/Makefile .config .kernelrelease FORCE
+include/linux/version.h: $(srctree)/Makefile include/config/kernel.release FORCE
        $(call filechk,version.h)
 
 # ---------------------------------------------------------------------------
@@ -860,7 +870,7 @@ depend dep:
 
 ifdef CONFIG_MODULES
 
-#      By default, build modules as well
+# By default, build modules as well
 
 all: modules
 
@@ -942,7 +952,7 @@ CLEAN_FILES +=      vmlinux System.map \
 MRPROPER_DIRS  += include/config include2
 MRPROPER_FILES += .config .config.old include/asm .version .old_version \
                   include/linux/autoconf.h include/linux/version.h \
-                 .kernelrelease Module.symvers tags TAGS cscope*
+                 Module.symvers tags TAGS cscope*
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -958,8 +968,9 @@ clean: archclean $(clean-dirs)
        $(call cmd,rmdirs)
        $(call cmd,rmfiles)
        @find . $(RCS_FIND_IGNORE) \
-               \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-               -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
+               \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+               -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
+               -o -name '*.symtypes' \) \
                -type f -print | xargs rm -f
 
 # mrproper - Delete all generated files, including .config
@@ -982,9 +993,9 @@ PHONY += distclean
 
 distclean: mrproper
        @find $(srctree) $(RCS_FIND_IGNORE) \
-               \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
+               \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
                -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
-               -o -name '.*.rej' -o -size 0 \
+               -o -name '.*.rej' -o -size 0 \
                -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
                -type f -print | xargs rm -f
 
@@ -994,9 +1005,9 @@ distclean: mrproper
 # rpm target kept for backward compatibility
 package-dir    := $(srctree)/scripts/package
 
-%pkg: FORCE
+%pkg: include/config/kernel.release FORCE
        $(Q)$(MAKE) $(build)=$(package-dir) $@
-rpm: FORCE
+rpm: include/config/kernel.release FORCE
        $(Q)$(MAKE) $(build)=$(package-dir) $@
 
 
@@ -1077,7 +1088,7 @@ else # KBUILD_EXTMOD
 # make M=dir modules   Make all modules in specified dir
 # make M=dir          Same as 'make M=dir modules'
 # make M=dir modules_install
-#                      Install the modules build in the module directory
+#                      Install the modules built in the module directory
 #                      Assumes install directory is already created
 
 # We are always building modules
@@ -1136,7 +1147,7 @@ clean:    rm-dirs := $(MODVERDIR)
 clean: $(clean-dirs)
        $(call cmd,rmdirs)
        @find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
-               \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+               \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
                -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
                -type f -print | xargs rm -f
 
@@ -1175,31 +1186,41 @@ else
 ALLINCLUDE_ARCHS := $(ARCH)
 endif
 else
-#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behaviour.
+#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behavour.
 ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS)
 endif
 
 ALLSOURCE_ARCHS := $(ARCH)
 
-define all-sources
-       ( find $(__srctree) $(RCS_FIND_IGNORE) \
+define find-sources
+        ( find $(__srctree) $(RCS_FIND_IGNORE) \
               \( -name include -o -name arch \) -prune -o \
-              -name '*.[chS]' -print; \
+              -name $1 -print; \
          for ARCH in $(ALLSOURCE_ARCHS) ; do \
               find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
-                   -name '*.[chS]' -print; \
+                   -name $1 -print; \
          done ; \
          find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
-              -name '*.[chS]' -print; \
+              -name $1 -print; \
          find $(__srctree)include $(RCS_FIND_IGNORE) \
               \( -name config -o -name 'asm-*' \) -prune \
-              -o -name '*.[chS]' -print; \
+              -o -name $1 -print; \
          for ARCH in $(ALLINCLUDE_ARCHS) ; do \
               find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
-                   -name '*.[chS]' -print; \
+                   -name $1 -print; \
          done ; \
          find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
-              -name '*.[chS]' -print )
+              -name $1 -print )
+endef
+
+define all-sources
+       $(call find-sources,'*.[chS]')
+endef
+define all-kconfigs
+       $(call find-sources,'Kconfig*')
+endef
+define all-defconfigs
+       $(call find-sources,'defconfig')
 endef
 
 quiet_cmd_cscope-file = FILELST cscope.files
@@ -1219,7 +1240,13 @@ define cmd_TAGS
                 echo "-I __initdata,__exitdata,__acquires,__releases  \
                       -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL              \
                       --extra=+f --c-kinds=+px"`;                     \
-                $(all-sources) | xargs etags $$ETAGSF -a
+                $(all-sources) | xargs etags $$ETAGSF -a;             \
+       if test "x$$ETAGSF" = x; then                                 \
+               $(all-kconfigs) | xargs etags -a                      \
+               --regex='/^config[ \t]+\([a-zA-Z0-9_]+\)/\1/';        \
+               $(all-defconfigs) | xargs etags -a                    \
+               --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/';     \
+       fi
 endef
 
 TAGS: FORCE
@@ -1259,14 +1286,14 @@ namespacecheck:
 endif #ifeq ($(config-targets),1)
 endif #ifeq ($(mixed-targets),1)
 
-PHONY += checkstack
+PHONY += checkstack kernelrelease kernelversion
 checkstack:
        $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
        $(PERL) $(src)/scripts/checkstack.pl $(ARCH)
 
 kernelrelease:
-       $(if $(wildcard .kernelrelease), $(Q)echo $(KERNELRELEASE), \
-       $(error kernelrelease not valid - run 'make *config' to update it))
+       $(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
+       $(error kernelrelease not valid - run 'make prepare' to update it))
 kernelversion:
        @echo $(KERNELVERSION)
 
@@ -1301,6 +1328,8 @@ endif
        $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
 %.o: %.S prepare scripts FORCE
        $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.symtypes: %.c prepare scripts FORCE
+       $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
 
 # Modules
 / %/: prepare scripts FORCE
index 282b14e..a3bbaaf 100644 (file)
@@ -177,7 +177,7 @@ boot := arch/arm/boot
 #      them changed.  We use .arch to indicate when they were updated
 #      last, otherwise make uses the target directory mtime.
 
-include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/MARKER
+include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/auto.conf
        @echo '  SYMLINK include/asm-arm/arch -> include/asm-arm/$(INCDIR)'
 ifneq ($(KBUILD_SRC),)
        $(Q)mkdir -p include/asm-arm
index c72e17a..e467a45 100644 (file)
@@ -147,7 +147,7 @@ endif
 #      them changed.  We use .arch and .mach to indicate when they were
 #      updated last, otherwise make uses the target directory mtime.
 
-include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER
+include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/auto.conf
        @echo '  SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)'
        $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
        $(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu
@@ -157,7 +157,7 @@ include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER
 #      don't, just reference the parent directory so the semantics are
 #      kept roughly the same.
 
-include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER
+include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/auto.conf
        @echo -n '  SYMLINK include/asm-sh/mach -> '
        $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
        $(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
index 98fac84..3a3a4c6 100644 (file)
@@ -71,7 +71,7 @@ archprepare: $(archinc)/.platform
 # Update machine cpu and platform symlinks if something which affects
 # them changed.
 
-$(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/MARKER
+$(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/auto.conf
        @echo '  SYMLINK $(archinc)/xtensa/config -> $(archinc)/xtensa/config-$(CPU)'
        $(Q)mkdir -p $(archinc)
        $(Q)mkdir -p $(archinc)/xtensa
index 5ac265d..1344ad7 100644 (file)
@@ -86,14 +86,14 @@ config MTD_REDBOOT_DIRECTORY_BLOCK
          block and "-2" means the penultimate block.
 
 config MTD_REDBOOT_PARTS_UNALLOCATED
-       bool "  Include unallocated flash regions"
+       bool "Include unallocated flash regions"
        depends on MTD_REDBOOT_PARTS
        help
          If you need to register each unallocated flash region as a MTD
          'partition', enable this option.
 
 config MTD_REDBOOT_PARTS_READONLY
-       bool "  Force read-only for RedBoot system images"
+       bool "Force read-only for RedBoot system images"
        depends on MTD_REDBOOT_PARTS
        help
          If you need to force read-only for 'RedBoot', 'RedBoot Config' and
index 6bdaacc..83d0b2a 100644 (file)
@@ -212,7 +212,7 @@ config MTD_NETtel
          Support for flash chips on NETtel/SecureEdge/SnapGear boards.
 
 config MTD_ALCHEMY
-       tristate '  AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support'
+       tristate "AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support"
        depends on SOC_AU1X00
        help
          Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards
index 44728ae..c84b02a 100644 (file)
@@ -1169,7 +1169,7 @@ config SCSI_NCR_Q720
          you do not have this SCSI card, so say N.
 
 config SCSI_NCR53C8XX_DEFAULT_TAGS
-       int "  default tagged command queue depth"
+       int "default tagged command queue depth"
        depends on SCSI_ZALON || SCSI_NCR_Q720
        default "8"
        ---help---
@@ -1195,7 +1195,7 @@ config SCSI_NCR53C8XX_DEFAULT_TAGS
          There is no safe option other than using good SCSI devices.
 
 config SCSI_NCR53C8XX_MAX_TAGS
-       int "  maximum number of queued commands"
+       int "maximum number of queued commands"
        depends on SCSI_ZALON || SCSI_NCR_Q720
        default "32"
        ---help---
@@ -1212,7 +1212,7 @@ config SCSI_NCR53C8XX_MAX_TAGS
          There is no safe option and the default answer is recommended.
 
 config SCSI_NCR53C8XX_SYNC
-       int "  synchronous transfers frequency in MHz"
+       int "synchronous transfers frequency in MHz"
        depends on SCSI_ZALON || SCSI_NCR_Q720
        default "20"
        ---help---
@@ -1246,7 +1246,7 @@ config SCSI_NCR53C8XX_SYNC
          terminations and SCSI conformant devices.
 
 config SCSI_NCR53C8XX_PROFILE
-       bool "  enable profiling"
+       bool "enable profiling"
        depends on SCSI_ZALON || SCSI_NCR_Q720
        help
          This option allows you to enable profiling information gathering.
@@ -1257,7 +1257,7 @@ config SCSI_NCR53C8XX_PROFILE
          The normal answer therefore is N.
 
 config SCSI_NCR53C8XX_NO_DISCONNECT
-       bool "  not allow targets to disconnect"
+       bool "not allow targets to disconnect"
        depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
        help
          This option is only provided for safety if you suspect some SCSI
diff --git a/include/linux/license.h b/include/linux/license.h
new file mode 100644 (file)
index 0000000..decdbf4
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __LICENSE_H
+#define __LICENSE_H
+
+static inline int license_is_gpl_compatible(const char *license)
+{
+       return (strcmp(license, "GPL") == 0
+               || strcmp(license, "GPL v2") == 0
+               || strcmp(license, "GPL and additional rights") == 0
+               || strcmp(license, "Dual BSD/GPL") == 0
+               || strcmp(license, "Dual MIT/GPL") == 0
+               || strcmp(license, "Dual MPL/GPL") == 0);
+}
+
+#endif
index 36b02d5..df55b36 100644 (file)
@@ -1,3 +1,11 @@
+config DEFCONFIG_LIST
+       string
+       option defconfig_list
+       default "/lib/modules/$UNAME_RELEASE/.config"
+       default "/etc/kernel-config"
+       default "/boot/config-$UNAME_RELEASE"
+       default "arch/$ARCH/defconfig"
+
 menu "Code maturity level options"
 
 config EXPERIMENTAL
index 08811e2..10e5b87 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <asm/cacheflush.h>
+#include <linux/license.h>
 
 #if 0
 #define DEBUGP printk
@@ -1251,16 +1252,6 @@ static void layout_sections(struct module *mod,
        }
 }
 
-static inline int license_is_gpl_compatible(const char *license)
-{
-       return (strcmp(license, "GPL") == 0
-               || strcmp(license, "GPL v2") == 0
-               || strcmp(license, "GPL and additional rights") == 0
-               || strcmp(license, "Dual BSD/GPL") == 0
-               || strcmp(license, "Dual MIT/GPL") == 0
-               || strcmp(license, "Dual MPL/GPL") == 0);
-}
-
 static void set_license(struct module *mod, const char *license)
 {
        if (!license)
index b0d067b..ac5f275 100644 (file)
@@ -13,6 +13,11 @@ space   := $(empty) $(empty)
 depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
 
 ###
+# basetarget equals the filename of the target with no extension.
+# So 'foo/bar.o' becomes 'bar'
+basetarget = $(basename $(notdir $@))
+
+###
 # Escape single quote for use in echo statements
 escsq = $(subst $(squote),'\$(squote)',$1)
 
index e48e60d..3cb445c 100644 (file)
@@ -8,7 +8,7 @@ PHONY := __build
 __build:
 
 # Read .config if it exist, otherwise ignore
--include .config
+-include include/config/auto.conf
 
 include scripts/Kbuild.include
 
@@ -117,7 +117,7 @@ $(real-objs-m:.o=.lst): quiet_modtag := [M]
 $(obj-m)              : quiet_modtag := [M]
 
 # Default for not multi-part modules
-modname = $(*F)
+modname = $(basetarget)
 
 $(multi-objs-m)         : modname = $(modname-multi)
 $(multi-objs-m:.o=.i)   : modname = $(modname-multi)
@@ -140,6 +140,15 @@ cmd_cc_i_c       = $(CPP) $(c_flags)   -o $@ $<
 %.i: %.c FORCE
        $(call if_changed_dep,cc_i_c)
 
+quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
+cmd_cc_symtypes_c         = \
+               $(CPP) -D__GENKSYMS__ $(c_flags) $<                     \
+               | $(GENKSYMS) -T $@ >/dev/null;                         \
+               test -s $@ || rm -f $@
+
+%.symtypes : %.c FORCE
+       $(call if_changed_dep,cc_symtypes_c)
+
 # C (.c) files
 # The C file is compiled and updated dependency information is generated.
 # (See cmd_cc_o_c + relevant part of rule_cc_o_c)
@@ -166,7 +175,8 @@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
 cmd_modversions =                                                      \
        if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then     \
                $(CPP) -D__GENKSYMS__ $(c_flags) $<                     \
-               | $(GENKSYMS) -a $(ARCH)                                \
+               | $(GENKSYMS) $(if $(KBUILD_SYMTYPES),                  \
+                             -T $(@D)/$(@F:.o=.symtypes)) -a $(ARCH)   \
                > $(@D)/.tmp_$(@F:.o=.ver);                             \
                                                                        \
                $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F)              \
index 2d51970..18ecd4d 100644 (file)
@@ -33,8 +33,8 @@
 __hostprogs := $(sort $(hostprogs-y)$(hostprogs-m))
 
 # hostprogs-y := tools/build may have been specified. Retreive directory
-obj-dirs += $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
-obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs))))
+host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
+host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs))))
 
 
 # C code
@@ -73,13 +73,17 @@ host-cxxmulti       := $(addprefix $(obj)/,$(host-cxxmulti))
 host-cxxobjs   := $(addprefix $(obj)/,$(host-cxxobjs))
 host-cshlib    := $(addprefix $(obj)/,$(host-cshlib))
 host-cshobjs   := $(addprefix $(obj)/,$(host-cshobjs))
-obj-dirs        := $(addprefix $(obj)/,$(obj-dirs))
+host-objdirs    := $(addprefix $(obj)/,$(host-objdirs))
+
+obj-dirs += $(host-objdirs)
 
 #####
 # Handle options to gcc. Support building with separate output directory
 
-_hostc_flags   = $(HOSTCFLAGS)   $(HOST_EXTRACFLAGS)   $(HOSTCFLAGS_$(*F).o)
-_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o)
+_hostc_flags   = $(HOSTCFLAGS)   $(HOST_EXTRACFLAGS)   \
+                 $(HOSTCFLAGS_$(basetarget).o)
+_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
+                 $(HOSTCXXFLAGS_$(basetarget).o)
 
 ifeq ($(KBUILD_SRC),)
 __hostc_flags  = $(_hostc_flags)
index 2cb4935..fc498fe 100644 (file)
@@ -82,12 +82,12 @@ obj-dirs    := $(addprefix $(obj)/,$(obj-dirs))
 #       than one module. In that case KBUILD_MODNAME will be set to foo_bar,
 #       where foo and bar are the name of the modules.
 name-fix = $(subst $(comma),_,$(subst -,_,$1))
-basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(*F)))"
+basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
 modname_flags  = $(if $(filter 1,$(words $(modname))),\
                  -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
 
-_c_flags       = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o)
-_a_flags       = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
+_c_flags       = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(basetarget).o)
+_a_flags       = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
 _cpp_flags     = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F))
 
 # If building the kernel in a separate objtree expand all occurrences
index 2686dd5..f0ff248 100644 (file)
@@ -17,7 +17,7 @@ __modinst: $(modules)
        @:
 
 quiet_cmd_modules_install = INSTALL $@
-      cmd_modules_install = mkdir -p $(2); cp $@ $(2)
+      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
 
 # Modules built outside the kernel source tree go into extra by default
 INSTALL_MOD_DIR ?= extra
index 0e056cf..e83613e 100644 (file)
@@ -35,7 +35,7 @@
 PHONY := _modpost
 _modpost: __modpost
 
-include .config
+include include/config/auto.conf
 include scripts/Kbuild.include
 include scripts/Makefile.lib
 
@@ -72,7 +72,7 @@ $(modules:.ko=.mod.c): __modpost ;
 # Step 5), compile all *.mod.c files
 
 # modname is set to make c_flags define KBUILD_MODNAME
-modname = $(*F)
+modname = $(basetarget)
 
 quiet_cmd_cc_o_c = CC      $@
       cmd_cc_o_c = $(CC) $(c_flags) $(CFLAGS_MODULE)   \
index f22e94c..2f60070 100644 (file)
@@ -1,17 +1,15 @@
 ###
 # Makefile.basic list the most basic programs used during the build process.
 # The programs listed herein is what is needed to do the basic stuff,
-# such as splitting .config and fix dependency file.
+# such as fix dependency file.
 # This initial step is needed to avoid files to be recompiled
 # when kernel configuration changes (which is what happens when
 # .config is included by main Makefile.
 # ---------------------------------------------------------------------------
 # fixdep:       Used to generate dependency information during build process
-# split-include: Divide all config symbols up in a number of files in
-#                include/config/...
 # docproc:      Used in Documentation/docbook
 
-hostprogs-y    := fixdep split-include docproc
+hostprogs-y    := fixdep docproc
 always         := $(hostprogs-y)
 
 # fixdep is needed to compile other host programs
diff --git a/scripts/basic/split-include.c b/scripts/basic/split-include.c
deleted file mode 100644 (file)
index 459c452..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * split-include.c
- *
- * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
- * This is a C version of syncdep.pl by Werner Almesberger.
- *
- * This program takes autoconf.h as input and outputs a directory full
- * of one-line include files, merging onto the old values.
- *
- * Think of the configuration options as key-value pairs.  Then there
- * are five cases:
- *
- *    key      old value   new value   action
- *
- *    KEY-1    VALUE-1     VALUE-1     leave file alone
- *    KEY-2    VALUE-2A    VALUE-2B    write VALUE-2B into file
- *    KEY-3    -           VALUE-3     write VALUE-3  into file
- *    KEY-4    VALUE-4     -           write an empty file
- *    KEY-5    (empty)     -           leave old empty file alone
- */
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define ERROR_EXIT(strExit)                                            \
-    {                                                                  \
-       const int errnoSave = errno;                                    \
-       fprintf(stderr, "%s: ", str_my_name);                           \
-       errno = errnoSave;                                              \
-       perror((strExit));                                              \
-       exit(1);                                                        \
-    }
-
-
-
-int main(int argc, const char * argv [])
-{
-    const char * str_my_name;
-    const char * str_file_autoconf;
-    const char * str_dir_config;
-
-    FILE * fp_config;
-    FILE * fp_target;
-    FILE * fp_find;
-
-    int buffer_size;
-
-    char * line;
-    char * old_line;
-    char * list_target;
-    char * ptarget;
-
-    struct stat stat_buf;
-
-    /* Check arg count. */
-    if (argc != 3)
-    {
-       fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]);
-       exit(1);
-    }
-
-    str_my_name       = argv[0];
-    str_file_autoconf = argv[1];
-    str_dir_config    = argv[2];
-
-    /* Find a buffer size. */
-    if (stat(str_file_autoconf, &stat_buf) != 0)
-       ERROR_EXIT(str_file_autoconf);
-    buffer_size = 2 * stat_buf.st_size + 4096;
-
-    /* Allocate buffers. */
-    if ( (line        = malloc(buffer_size)) == NULL
-    ||   (old_line    = malloc(buffer_size)) == NULL
-    ||   (list_target = malloc(buffer_size)) == NULL )
-       ERROR_EXIT(str_file_autoconf);
-
-    /* Open autoconfig file. */
-    if ((fp_config = fopen(str_file_autoconf, "r")) == NULL)
-       ERROR_EXIT(str_file_autoconf);
-
-    /* Make output directory if needed. */
-    if (stat(str_dir_config, &stat_buf) != 0)
-    {
-       if (mkdir(str_dir_config, 0755) != 0)
-           ERROR_EXIT(str_dir_config);
-    }
-
-    /* Change to output directory. */
-    if (chdir(str_dir_config) != 0)
-       ERROR_EXIT(str_dir_config);
-
-    /* Put initial separator into target list. */
-    ptarget = list_target;
-    *ptarget++ = '\n';
-
-    /* Read config lines. */
-    while (fgets(line, buffer_size, fp_config))
-    {
-       const char * str_config;
-       int is_same;
-       int itarget;
-
-       if (line[0] != '#')
-           continue;
-       if ((str_config = strstr(line, "CONFIG_")) == NULL)
-           continue;
-
-       /* Make the output file name. */
-       str_config += sizeof("CONFIG_") - 1;
-       for (itarget = 0; !isspace(str_config[itarget]); itarget++)
-       {
-           int c = (unsigned char) str_config[itarget];
-           if (isupper(c)) c = tolower(c);
-           if (c == '_')   c = '/';
-           ptarget[itarget] = c;
-       }
-       ptarget[itarget++] = '.';
-       ptarget[itarget++] = 'h';
-       ptarget[itarget++] = '\0';
-
-       /* Check for existing file. */
-       is_same = 0;
-       if ((fp_target = fopen(ptarget, "r")) != NULL)
-       {
-           fgets(old_line, buffer_size, fp_target);
-           if (fclose(fp_target) != 0)
-               ERROR_EXIT(ptarget);
-           if (!strcmp(line, old_line))
-               is_same = 1;
-       }
-
-       if (!is_same)
-       {
-           /* Auto-create directories. */
-           int islash;
-           for (islash = 0; islash < itarget; islash++)
-           {
-               if (ptarget[islash] == '/')
-               {
-                   ptarget[islash] = '\0';
-                   if (stat(ptarget, &stat_buf) != 0
-                   &&  mkdir(ptarget, 0755)     != 0)
-                       ERROR_EXIT( ptarget );
-                   ptarget[islash] = '/';
-               }
-           }
-
-           /* Write the file. */
-           if ((fp_target = fopen(ptarget, "w" )) == NULL)
-               ERROR_EXIT(ptarget);
-           fputs(line, fp_target);
-           if (ferror(fp_target) || fclose(fp_target) != 0)
-               ERROR_EXIT(ptarget);
-       }
-
-       /* Update target list */
-       ptarget += itarget;
-       *(ptarget-1) = '\n';
-    }
-
-    /*
-     * Close autoconfig file.
-     * Terminate the target list.
-     */
-    if (fclose(fp_config) != 0)
-       ERROR_EXIT(str_file_autoconf);
-    *ptarget = '\0';
-
-    /*
-     * Fix up existing files which have no new value.
-     * This is Case 4 and Case 5.
-     *
-     * I re-read the tree and filter it against list_target.
-     * This is crude.  But it avoids data copies.  Also, list_target
-     * is compact and contiguous, so it easily fits into cache.
-     *
-     * Notice that list_target contains strings separated by \n,
-     * with a \n before the first string and after the last.
-     * fgets gives the incoming names a terminating \n.
-     * So by having an initial \n, strstr will find exact matches.
-     */
-
-    fp_find = popen("find * -type f -name \"*.h\" -print", "r");
-    if (fp_find == 0)
-       ERROR_EXIT( "find" );
-
-    line[0] = '\n';
-    while (fgets(line+1, buffer_size, fp_find))
-    {
-       if (strstr(list_target, line) == NULL)
-       {
-           /*
-            * This is an old file with no CONFIG_* flag in autoconf.h.
-            */
-
-           /* First strip the \n. */
-           line[strlen(line)-1] = '\0';
-
-           /* Grab size. */
-           if (stat(line+1, &stat_buf) != 0)
-               ERROR_EXIT(line);
-
-           /* If file is not empty, make it empty and give it a fresh date. */
-           if (stat_buf.st_size != 0)
-           {
-               if ((fp_target = fopen(line+1, "w")) == NULL)
-                   ERROR_EXIT(line);
-               if (fclose(fp_target) != 0)
-                   ERROR_EXIT(line);
-           }
-       }
-    }
-
-    if (pclose(fp_find) != 0)
-       ERROR_EXIT("find");
-
-    return 0;
-}
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
new file mode 100644 (file)
index 0000000..9ed00d9
--- /dev/null
@@ -0,0 +1,169 @@
+#!/usr/bin/perl -w
+#
+# (C) Copyright IBM Corporation 2006.
+#      Released under GPL v2.
+#      Author : Ram Pai (linuxram@us.ibm.com)
+#
+# Usage: export_report.pl -k Module.symvers [-o report_file ] -f *.mod.c
+#
+
+use Getopt::Std;
+use strict;
+
+sub numerically {
+       my $no1 = (split /\s+/, $a)[1];
+       my $no2 = (split /\s+/, $b)[1];
+       return $no1 <=> $no2;
+}
+
+sub alphabetically {
+       my ($module1, $value1) = @{$a};
+       my ($module2, $value2) = @{$b};
+       return $value1 <=> $value2 || $module2 cmp $module1;
+}
+
+sub print_depends_on {
+       my ($href) = @_;
+       print "\n";
+       while (my ($mod, $list) = each %$href) {
+               print "\t$mod:\n";
+               foreach my $sym (sort numerically @{$list}) {
+                       my ($symbol, $no) = split /\s+/, $sym;
+                       printf("\t\t%-25s\t%-25d\n", $symbol, $no);
+               }
+               print "\n";
+       }
+       print "\n";
+       print "~"x80 , "\n";
+}
+
+sub usage {
+        print "Usage: @_ -h -k Module.symvers  [ -o outputfile ] \n",
+             "\t-f: treat all the non-option argument as .mod.c files. ",
+             "Recommend using this as the last option\n",
+             "\t-h: print detailed help\n",
+             "\t-k: the path to Module.symvers file. By default uses ",
+             "the file from the current directory\n",
+             "\t-o outputfile: output the report to outputfile\n";
+       exit 0;
+}
+
+sub collectcfiles {
+        my @file = `cat .tmp_versions/*.mod | grep '.*\.ko\$'`;
+        @file = grep {s/\.ko/.mod.c/} @file;
+       chomp @file;
+        return @file;
+}
+
+my (%SYMBOL, %MODULE, %opt, @allcfiles);
+
+if (not getopts('hk:o:f',\%opt) or defined $opt{'h'}) {
+        usage($0);
+}
+
+if (defined $opt{'f'}) {
+       @allcfiles = @ARGV;
+} else {
+       @allcfiles = collectcfiles();
+}
+
+if (not defined $opt{'k'}) {
+       $opt{'k'} = "Module.symvers";
+}
+
+unless (open(MODULE_SYMVERS, $opt{'k'})) {
+       die "Sorry, cannot open $opt{'k'}: $!\n";
+}
+
+if (defined $opt{'o'}) {
+       unless (open(OUTPUT_HANDLE, ">$opt{'o'}")) {
+               die "Sorry, cannot open $opt{'o'} $!\n";
+       }
+       select OUTPUT_HANDLE;
+}
+#
+# collect all the symbols and their attributes from the
+# Module.symvers file
+#
+while ( <MODULE_SYMVERS> ) {
+       chomp;
+       my (undef, $symbol, $module, $gpl) = split;
+       $SYMBOL { $symbol } =  [ $module , "0" , $symbol, $gpl];
+}
+close(MODULE_SYMVERS);
+
+#
+# collect the usage count of each symbol.
+#
+foreach my $thismod (@allcfiles) {
+       unless (open(MODULE_MODULE, $thismod)) {
+               print "Sorry, cannot open $thismod: $!\n";
+               next;
+       }
+       my $state=0;
+       while ( <MODULE_MODULE> ) {
+               chomp;
+               if ($state eq 0) {
+                       $state = 1 if ($_ =~ /static const struct modversion_info/);
+                       next;
+               }
+               if ($state eq 1) {
+                       $state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/);
+                       next;
+               }
+               if ($state eq 2) {
+                       if ( $_ !~ /0x[0-9a-f]{7,8},/ ) {
+                               next;
+                       }
+                       my $sym = (split /([,"])/,)[4];
+                       my ($module, $value, $symbol, $gpl) = @{$SYMBOL{$sym}};
+                       $SYMBOL{ $sym } =  [ $module, $value+1, $symbol, $gpl];
+                       push(@{$MODULE{$thismod}} , $sym);
+               }
+       }
+       if ($state ne 2) {
+               print "WARNING:$thismod is not built with CONFIG_MODVERSION enabled\n";
+       }
+       close(MODULE_MODULE);
+}
+
+print "\tThis file reports the exported symbols usage patterns by in-tree\n",
+       "\t\t\t\tmodules\n";
+printf("%s\n\n\n","x"x80);
+printf("\t\t\t\tINDEX\n\n\n");
+printf("SECTION 1: Usage counts of all exported symbols\n");
+printf("SECTION 2: List of modules and the exported symbols they use\n");
+printf("%s\n\n\n","x"x80);
+printf("SECTION 1:\tThe exported symbols and their usage count\n\n");
+printf("%-25s\t%-25s\t%-5s\t%-25s\n", "Symbol", "Module", "Usage count",
+       "export type");
+
+#
+# print the list of unused exported symbols
+#
+foreach my $list (sort alphabetically values(%SYMBOL)) {
+       my ($module, $value, $symbol, $gpl) = @{$list};
+       printf("%-25s\t%-25s\t%-10s\t", $symbol, $module, $value);
+       if (defined $gpl) {
+               printf("%-25s\n",$gpl);
+       } else {
+               printf("\n");
+       }
+}
+printf("%s\n\n\n","x"x80);
+
+printf("SECTION 2:\n\tThis section reports export-symbol-usage of in-kernel
+modules. Each module lists the modules, and the symbols from that module that
+it uses.  Each listed symbol reports the number of modules using it\n");
+
+print "~"x80 , "\n";
+while (my ($thismod, $list) = each %MODULE) {
+       my %depends;
+       $thismod =~ s/\.mod\.c/.ko/;
+       print "\t\t\t$thismod\n";
+       foreach my $symbol (@{$list}) {
+               my ($module, $value, undef, $gpl) = @{$SYMBOL{$symbol}};
+               push (@{$depends{"$module"}}, "$symbol $value");
+       }
+       print_depends_on(\%depends);
+}
index 5b0344e..b038182 100644 (file)
@@ -42,7 +42,7 @@ static FILE *debugfile;
 int cur_line = 1;
 char *cur_filename;
 
-static int flag_debug, flag_dump_defs, flag_warnings;
+static int flag_debug, flag_dump_defs, flag_dump_types, flag_warnings;
 static const char *arch = "";
 static const char *mod_prefix = "";
 
@@ -50,6 +50,7 @@ static int errors;
 static int nsyms;
 
 static struct symbol *expansion_trail;
+static struct symbol *visited_symbols;
 
 static const char *const symbol_type_name[] = {
        "normal", "typedef", "enum", "struct", "union"
@@ -176,6 +177,7 @@ struct symbol *add_symbol(const char *name, enum symbol_type type,
        sym->type = type;
        sym->defn = defn;
        sym->expansion_trail = NULL;
+       sym->visited = NULL;
        sym->is_extern = is_extern;
 
        sym->hash_next = symtab[h];
@@ -236,26 +238,11 @@ static int equal_list(struct string_list *a, struct string_list *b)
 
 static void print_node(FILE * f, struct string_list *list)
 {
-       switch (list->tag) {
-       case SYM_STRUCT:
-               putc('s', f);
-               goto printit;
-       case SYM_UNION:
-               putc('u', f);
-               goto printit;
-       case SYM_ENUM:
-               putc('e', f);
-               goto printit;
-       case SYM_TYPEDEF:
-               putc('t', f);
-               goto printit;
-
-             printit:
+       if (list->tag != SYM_NORMAL) {
+               putc(symbol_type_name[list->tag][0], f);
                putc('#', f);
-       case SYM_NORMAL:
-               fputs(list->string, f);
-               break;
        }
+       fputs(list->string, f);
 }
 
 static void print_list(FILE * f, struct string_list *list)
@@ -287,9 +274,9 @@ static void print_list(FILE * f, struct string_list *list)
        }
 }
 
-static unsigned long expand_and_crc_list(struct string_list *list,
-                                        unsigned long crc)
+static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
 {
+       struct string_list *list = sym->defn;
        struct string_list **e, **b;
        struct string_list *tmp, **tmp2;
        int elem = 1;
@@ -332,7 +319,7 @@ static unsigned long expand_and_crc_list(struct string_list *list,
                        } else {
                                subsym->expansion_trail = expansion_trail;
                                expansion_trail = subsym;
-                               crc = expand_and_crc_list(subsym->defn, crc);
+                               crc = expand_and_crc_sym(subsym, crc);
                        }
                        break;
 
@@ -382,12 +369,22 @@ static unsigned long expand_and_crc_list(struct string_list *list,
                        } else {
                                subsym->expansion_trail = expansion_trail;
                                expansion_trail = subsym;
-                               crc = expand_and_crc_list(subsym->defn, crc);
+                               crc = expand_and_crc_sym(subsym, crc);
                        }
                        break;
                }
        }
 
+       {
+               static struct symbol **end = &visited_symbols;
+
+               if (!sym->visited) {
+                       *end = sym;
+                       end = &sym->visited;
+                       sym->visited = (struct symbol *)-1L;
+               }
+       }
+
        return crc;
 }
 
@@ -406,7 +403,7 @@ void export_symbol(const char *name)
 
                expansion_trail = (struct symbol *)-1L;
 
-               crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
+               crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
 
                sym = expansion_trail;
                while (sym != (struct symbol *)-1L) {
@@ -464,6 +461,7 @@ static void genksyms_usage(void)
 
 int main(int argc, char **argv)
 {
+       FILE *dumpfile = NULL;
        int o;
 
 #ifdef __GNU_LIBRARY__
@@ -473,15 +471,16 @@ int main(int argc, char **argv)
                {"warnings", 0, 0, 'w'},
                {"quiet", 0, 0, 'q'},
                {"dump", 0, 0, 'D'},
+               {"dump-types", 1, 0, 'T'},
                {"version", 0, 0, 'V'},
                {"help", 0, 0, 'h'},
                {0, 0, 0, 0}
        };
 
-       while ((o = getopt_long(argc, argv, "a:dwqVDk:p:",
+       while ((o = getopt_long(argc, argv, "a:dwqVDT:k:p:",
                                &long_opts[0], NULL)) != EOF)
 #else                          /* __GNU_LIBRARY__ */
-       while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF)
+       while ((o = getopt(argc, argv, "a:dwqVDT:k:p:")) != EOF)
 #endif                         /* __GNU_LIBRARY__ */
                switch (o) {
                case 'a':
@@ -502,6 +501,14 @@ int main(int argc, char **argv)
                case 'D':
                        flag_dump_defs = 1;
                        break;
+               case 'T':
+                       flag_dump_types = 1;
+                       dumpfile = fopen(optarg, "w");
+                       if (!dumpfile) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       break;
                case 'h':
                        genksyms_usage();
                        return 0;
@@ -524,6 +531,24 @@ int main(int argc, char **argv)
 
        yyparse();
 
+       if (flag_dump_types && visited_symbols) {
+               while (visited_symbols != (struct symbol *)-1L) {
+                       struct symbol *sym = visited_symbols;
+
+                       if (sym->type != SYM_NORMAL) {
+                               putc(symbol_type_name[sym->type][0], dumpfile);
+                               putc('#', dumpfile);
+                       }
+                       fputs(sym->name, dumpfile);
+                       putc(' ', dumpfile);
+                       print_list(dumpfile, sym->defn);
+                       putc('\n', dumpfile);
+
+                       visited_symbols = sym->visited;
+                       sym->visited = NULL;
+               }
+       }
+
        if (flag_debug) {
                fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
                        nsyms, HASH_BUCKETS,
index ab6f34f..2668287 100644 (file)
@@ -41,6 +41,7 @@ struct symbol {
        enum symbol_type type;
        struct string_list *defn;
        struct symbol *expansion_trail;
+       struct symbol *visited;
        int is_extern;
 };
 
index 1218053..37ba982 100644 (file)
@@ -2023,7 +2023,7 @@ repeat:
       break;
 
     default:
-      abort();
+      exit(1);
     }
 fini:
 
index fe0dfee..5e544a0 100644 (file)
@@ -392,7 +392,7 @@ repeat:
       break;
 
     default:
-      abort();
+      exit(1);
     }
 fini:
 
index 8012d10..4dcb886 100644 (file)
@@ -539,6 +539,7 @@ int main(int ac, char **av)
        name = av[i];
        if (!name) {
                printf(_("%s: Kconfig file missing\n"), av[0]);
+               exit(1);
        }
        conf_parse(name);
        //zconfdump(stdout);
@@ -573,7 +574,7 @@ int main(int ac, char **av)
        case set_random:
                name = getenv("KCONFIG_ALLCONFIG");
                if (name && !stat(name, &tmpstat)) {
-                       conf_read_simple(name);
+                       conf_read_simple(name, S_DEF_USER);
                        break;
                }
                switch (input_mode) {
@@ -584,9 +585,9 @@ int main(int ac, char **av)
                default: break;
                }
                if (!stat(name, &tmpstat))
-                       conf_read_simple(name);
+                       conf_read_simple(name, S_DEF_USER);
                else if (!stat("all.config", &tmpstat))
-                       conf_read_simple("all.config");
+                       conf_read_simple("all.config", S_DEF_USER);
                break;
        default:
                break;
@@ -599,7 +600,15 @@ int main(int ac, char **av)
                        input_mode = ask_silent;
                        valid_stdin = 1;
                }
-       }
+       } else if (sym_change_count) {
+               name = getenv("KCONFIG_NOSILENTUPDATE");
+               if (name && *name) {
+                       fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
+                       return 1;
+               }
+       } else
+               goto skip_check;
+
        do {
                conf_cnt = 0;
                check_conf(&rootmenu);
@@ -608,5 +617,11 @@ int main(int ac, char **av)
                fprintf(stderr, _("\n*** Error during writing of the kernel 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"));
+               return 1;
+       }
+
        return 0;
 }
index 1b5df58..2ee48c3 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <sys/stat.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -20,19 +21,8 @@ static void conf_warning(const char *fmt, ...)
 static const char *conf_filename;
 static int conf_lineno, conf_warnings, conf_unsaved;
 
-const char conf_def_filename[] = ".config";
-
 const char conf_defname[] = "arch/$ARCH/defconfig";
 
-const char *conf_confnames[] = {
-       ".config",
-       "/lib/modules/$UNAME_RELEASE/.config",
-       "/etc/kernel-config",
-       "/boot/config-$UNAME_RELEASE",
-       conf_defname,
-       NULL,
-};
-
 static void conf_warning(const char *fmt, ...)
 {
        va_list ap;
@@ -44,6 +34,13 @@ static void conf_warning(const char *fmt, ...)
        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;
@@ -86,51 +83,65 @@ char *conf_get_default_confname(void)
        return name;
 }
 
-int conf_read_simple(const char *name)
+int conf_read_simple(const char *name, int def)
 {
        FILE *in = NULL;
        char line[1024];
        char *p, *p2;
        struct symbol *sym;
-       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_change_count++;
+               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;
+                                        "# 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_CHANGED;
+               sym->flags &= ~(def_flags|SYMBOL_VALID);
                if (sym_is_choice(sym))
-                       sym->flags &= ~SYMBOL_NEW;
-               sym->flags &= ~SYMBOL_VALID;
+                       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;
                }
        }
 
@@ -147,19 +158,26 @@ int conf_read_simple(const char *name)
                        *p++ = 0;
                        if (strncmp(p, "is not set", 10))
                                continue;
-                       sym = sym_find(line + 9);
-                       if (!sym) {
-                               conf_warning("trying to assign nonexistent symbol %s", line + 9);
-                               break;
-                       } else if (!(sym->flags & SYMBOL_NEW)) {
+                       if (def == S_DEF_USER) {
+                               sym = sym_find(line + 9);
+                               if (!sym) {
+                                       conf_warning("trying to assign nonexistent symbol %s", line + 9);
+                                       break;
+                               }
+                       } else {
+                               sym = sym_lookup(line + 9, 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:
                                ;
@@ -177,34 +195,48 @@ int conf_read_simple(const char *name)
                        p2 = strchr(p, '\n');
                        if (p2)
                                *p2 = 0;
-                       sym = sym_find(line + 7);
-                       if (!sym) {
-                               conf_warning("trying to assign nonexistent symbol %s", line + 7);
-                               break;
-                       } else if (!(sym->flags & SYMBOL_NEW)) {
+                       if (def == S_DEF_USER) {
+                               sym = sym_find(line + 7);
+                               if (!sym) {
+                                       conf_warning("trying to assign nonexistent symbol %s", line + 7);
+                                       break;
+                               }
+                       } else {
+                               sym = sym_lookup(line + 7, 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;
@@ -221,9 +253,10 @@ int conf_read_simple(const char *name)
                                }
                        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 {
                                        conf_warning("symbol value '%s' invalid for %s", p, sym->name);
                                        continue;
@@ -241,24 +274,24 @@ int conf_read_simple(const char *name)
                }
                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) {
+                               if (cs->def[def].tri == yes) {
                                        conf_warning("%s creates inconsistent choice state", sym->name);
-                                       cs->flags |= SYMBOL_NEW;
+                                       cs->flags &= ~def_flags;
                                }
                                break;
                        case yes:
-                               if (cs->user.tri != no) {
+                               if (cs->def[def].tri != no) {
                                        conf_warning("%s creates inconsistent choice state", sym->name);
-                                       cs->flags |= SYMBOL_NEW;
+                                       cs->flags &= ~def_flags;
                                } else
-                                       cs->user.val = sym;
+                                       cs->def[def].val = sym;
                                break;
                        }
-                       cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
+                       cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri);
                }
        }
        fclose(in);
@@ -273,9 +306,11 @@ int conf_read(const char *name)
        struct symbol *sym;
        struct property *prop;
        struct expr *e;
-       int i;
+       int i, flags;
+
+       sym_change_count = 0;
 
-       if (conf_read_simple(name))
+       if (conf_read_simple(name, S_DEF_USER))
                return 1;
 
        for_all_symbols(i, sym) {
@@ -287,12 +322,12 @@ int conf_read(const char *name)
                        switch (sym->type) {
                        case S_BOOLEAN:
                        case S_TRISTATE:
-                               if (sym->user.tri != sym_get_tristate_value(sym))
+                               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->user.val))
+                               if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
                                        goto sym_ok;
                                break;
                        }
@@ -304,15 +339,13 @@ int conf_read(const char *name)
        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;
-                                       sym->flags &= ~SYMBOL_VALID;
-                               }
+                               if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val))
+                                       sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
                        default:
                                break;
                        }
@@ -320,19 +353,21 @@ 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 = conf_warnings || conf_unsaved;
+       sym_change_count += conf_warnings || conf_unsaved;
 
        return 0;
 }
 
 int conf_write(const char *name)
 {
-       FILE *out, *out_h;
+       FILE *out;
        struct symbol *sym;
        struct menu *menu;
        const char *basename;
@@ -351,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);
@@ -359,23 +394,24 @@ 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;
-       out_h = NULL;
-       if (!name) {
-               out_h = fopen(".tmpconfig.h", "w");
-               if (!out_h)
-                       return 1;
-               file_write_dep(NULL);
-       }
+
        sym = sym_lookup("KERNELVERSION", 0);
        sym_calc_value(sym);
        time(&now);
@@ -391,16 +427,6 @@ int conf_write(const char *name)
                     sym_get_string_value(sym),
                     use_timestamp ? "# " : "",
                     use_timestamp ? ctime(&now) : "");
-       if (out_h)
-               fprintf(out_h, "/*\n"
-                              " * Automatically generated C config: don't edit\n"
-                              " * Linux kernel version: %s\n"
-                              "%s%s"
-                              " */\n"
-                              "#define AUTOCONF_INCLUDED\n",
-                              sym_get_string_value(sym),
-                              use_timestamp ? " * " : "",
-                              use_timestamp ? ctime(&now) : "");
 
        if (!sym_change_count)
                sym_clear_all_valid();
@@ -416,11 +442,6 @@ int conf_write(const char *name)
                                     "#\n"
                                     "# %s\n"
                                     "#\n", str);
-                       if (out_h)
-                               fprintf(out_h, "\n"
-                                              "/*\n"
-                                              " * %s\n"
-                                              " */\n", str);
                } else if (!(sym->flags & SYMBOL_CHOICE)) {
                        sym_calc_value(sym);
                        if (!(sym->flags & SYMBOL_WRITE))
@@ -438,59 +459,39 @@ int conf_write(const char *name)
                                switch (sym_get_tristate_value(sym)) {
                                case no:
                                        fprintf(out, "# CONFIG_%s is not set\n", sym->name);
-                                       if (out_h)
-                                               fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
                                        break;
                                case mod:
                                        fprintf(out, "CONFIG_%s=m\n", sym->name);
-                                       if (out_h)
-                                               fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
                                        break;
                                case yes:
                                        fprintf(out, "CONFIG_%s=y\n", sym->name);
-                                       if (out_h)
-                                               fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
                                        break;
                                }
                                break;
                        case S_STRING:
-                               // fix me
                                str = sym_get_string_value(sym);
                                fprintf(out, "CONFIG_%s=\"", sym->name);
-                               if (out_h)
-                                       fprintf(out_h, "#define CONFIG_%s \"", sym->name);
-                               do {
+                               while (1) {
                                        l = strcspn(str, "\"\\");
                                        if (l) {
                                                fwrite(str, l, 1, out);
-                                               if (out_h)
-                                                       fwrite(str, l, 1, out_h);
-                                       }
-                                       str += l;
-                                       while (*str == '\\' || *str == '"') {
-                                               fprintf(out, "\\%c", *str);
-                                               if (out_h)
-                                                       fprintf(out_h, "\\%c", *str);
-                                               str++;
+                                               str += l;
                                        }
-                               } while (*str);
+                                       if (!*str)
+                                               break;
+                                       fprintf(out, "\\%c", *str++);
+                               }
                                fputs("\"\n", out);
-                               if (out_h)
-                                       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, "CONFIG_%s=%s\n", sym->name, str);
-                                       if (out_h)
-                                               fprintf(out_h, "#define CONFIG_%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);
-                               if (out_h)
-                                       fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
                                break;
                        }
                }
@@ -510,21 +511,253 @@ int conf_write(const char *name)
                }
        }
        fclose(out);
-       if (out_h) {
-               fclose(out_h);
-               rename(".tmpconfig.h", "include/linux/autoconf.h");
+
+       if (*tmpname) {
+               strcat(dirname, name ? name : conf_get_configname());
+               strcat(dirname, ".old");
+               rename(newname, dirname);
+               if (rename(tmpname, newname))
+                       return 1;
        }
-       if (!name || basename != conf_def_filename) {
-               if (!name)
-                       name = conf_def_filename;
-               sprintf(tmpname, "%s.old", name);
-               rename(name, tmpname);
+
+       printf(_("#\n"
+                "# configuration written to %s\n"
+                "#\n"), newname);
+
+       sym_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;
+
+       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("KERNELVERSION", 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));
+       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));
+
+       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, "CONFIG_%s=m\n", sym->name);
+                               fprintf(out_h, "#define CONFIG_%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);
+                               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);
+                       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, "CONFIG_%s=%s\n", sym->name, str);
+                               fprintf(out_h, "#define CONFIG_%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);
+                       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;
 }
index 30e4f9d..6f98dbf 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 1b36ef1..6084525 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,10 +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_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
@@ -149,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);
index 665bd53..7b0d3a9 100644 (file)
@@ -114,12 +114,6 @@ const char *dbg_print_flags(int val)
 
        bzero(buf, 256);
 
-       if (val & SYMBOL_YES)
-               strcat(buf, "yes/");
-       if (val & SYMBOL_MOD)
-               strcat(buf, "mod/");
-       if (val & SYMBOL_NO)
-               strcat(buf, "no/");
        if (val & SYMBOL_CONST)
                strcat(buf, "const/");
        if (val & SYMBOL_CHECK)
@@ -138,8 +132,6 @@ const char *dbg_print_flags(int val)
                strcat(buf, "write/");
        if (val & SYMBOL_CHANGED)
                strcat(buf, "changed/");
-       if (val & SYMBOL_NEW)
-               strcat(buf, "new/");
        if (val & SYMBOL_AUTO)
                strcat(buf, "auto/");
 
@@ -1192,9 +1184,7 @@ static gchar **fill_row(struct menu *menu)
 
        row[COL_OPTION] =
            g_strdup_printf("%s %s", menu_get_prompt(menu),
-                           sym ? (sym->
-                                  flags & SYMBOL_NEW ? "(NEW)" : "") :
-                           "");
+                           sym && sym_has_value(sym) ? "(NEW)" : "");
 
        if (show_all && !menu_is_visible(menu))
                row[COL_COLOR] = g_strdup("DarkGray");
index 24e3c8c..800f8c7 100644 (file)
@@ -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
@@ -820,6 +832,8 @@ void alloc_string(const char *str, int size)
 #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.
  */
@@ -942,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;
@@ -1452,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 )
@@ -1969,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 yy_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 * yy_str )
+YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr )
 {
     
-       return zconf_scan_bytes(yy_str,strlen(yy_str) );
+       return zconf_scan_bytes(yystr,strlen(yystr) );
 }
 
 /** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
@@ -1988,7 +2002,7 @@ YY_BUFFER_STATE zconf_scan_string (yyconst char * yy_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;
@@ -1996,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 )
@@ -2125,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)
 {
@@ -2140,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;
 }
 
@@ -2151,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
@@ -2160,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;
@@ -2191,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();
index 527f60c..2628023 100644 (file)
@@ -40,6 +40,10 @@ extern "C" {
 
 #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;
@@ -60,8 +64,6 @@ int zconf_lineno(void);
 char *zconf_curname(void);
 
 /* confdata.c */
-extern const char conf_def_filename[];
-
 char *conf_get_default_confname(void);
 
 /* kconfig_load.c */
@@ -78,6 +80,7 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
 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);
 
@@ -99,6 +102,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);
@@ -137,7 +141,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 b6a389c..a263746 100644 (file)
@@ -2,8 +2,9 @@
 /* confdata.c */
 P(conf_parse,void,(const char *name));
 P(conf_read,int,(const char *name));
-P(conf_read_simple,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));
 
 /* menu.c */
 P(rootmenu,struct menu,);
@@ -38,4 +39,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));
index 0fce20c..c86c27f 100644 (file)
@@ -114,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));
 }
@@ -124,15 +124,20 @@ 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;
 }
@@ -152,6 +157,24 @@ 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 ||
@@ -325,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);
index 4590cd3..393f374 100644 (file)
@@ -6,16 +6,20 @@
 #include <qapplication.h>
 #include <qmainwindow.h>
 #include <qtoolbar.h>
+#include <qlayout.h>
 #include <qvbox.h>
 #include <qsplitter.h>
 #include <qlistview.h>
-#include <qtextview.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>
 #endif
 
 static QApplication *configApp;
+static ConfigSettings *configSettings;
 
 static inline QString qgettext(const char* str)
 {
-  return QString::fromLocal8Bit(gettext(str));
+       return QString::fromLocal8Bit(gettext(str));
 }
 
 static inline QString qgettext(const QString& str)
 {
-  return QString::fromLocal8Bit(gettext(str.latin1()));
-}
-
-ConfigSettings::ConfigSettings()
-       : showAll(false), showName(false), showRange(false), showData(false)
-{
-}
-
-#if QT_VERSION >= 300
-/**
- * Reads the list column settings from the application settings.
- */
-void ConfigSettings::readListSettings()
-{
-       showAll = readBoolEntry("/kconfig/qconf/showAll", false);
-       showName = readBoolEntry("/kconfig/qconf/showName", false);
-       showRange = readBoolEntry("/kconfig/qconf/showRange", false);
-       showData = readBoolEntry("/kconfig/qconf/showData", false);
+       return QString::fromLocal8Bit(gettext(str.latin1()));
 }
 
 /**
@@ -88,76 +76,7 @@ bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value
                stringList.push_back(QString::number(*it));
        return writeEntry(key, stringList);
 }
-#endif
-
-
-/*
- * 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 (!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;
-               }
-       }
-}
 
 #if QT_VERSION >= 300
 /*
@@ -355,6 +274,12 @@ ConfigItem::~ConfigItem(void)
        }
 }
 
+ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
+       : Parent(parent)
+{
+       connect(this, SIGNAL(lostFocus()), SLOT(hide()));
+}
+
 void ConfigLineEdit::show(ConfigItem* i)
 {
        item = i;
@@ -385,14 +310,14 @@ void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
        hide();
 }
 
-ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv, ConfigSettings* configSettings)
-       : Parent(p), cview(cv),
+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)
+         rootEntry(0), headerPopup(0)
 {
        int i;
 
@@ -406,11 +331,14 @@ ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv, ConfigSettings* conf
        connect(this, SIGNAL(selectionChanged(void)),
                SLOT(updateSelection(void)));
 
-       if (configSettings) {
-               showAll = configSettings->showAll;
-               showName = configSettings->showName;
-               showRange = configSettings->showRange;
-               showData = configSettings->showData;
+       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++)
@@ -441,6 +369,30 @@ void ConfigList::reinit(void)
        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;
@@ -450,9 +402,8 @@ void ConfigList::updateSelection(void)
        if (!item)
                return;
 
-       cview->setHelp(item);
-
        menu = item->menu;
+       emit menuChanged(menu);
        if (!menu)
                return;
        type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
@@ -464,8 +415,20 @@ void ConfigList::updateList(ConfigItem* item)
 {
        ConfigItem* last = 0;
 
-       if (!rootEntry)
-               goto update;
+       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))) {
@@ -491,14 +454,6 @@ update:
        triggerUpdate();
 }
 
-void ConfigList::setAllOpen(bool open)
-{
-       QListViewItemIterator it(this);
-
-       for (; it.current(); it++)
-               it.current()->setOpen(open);
-}
-
 void ConfigList::setValue(ConfigItem* item, tristate val)
 {
        struct symbol* sym;
@@ -581,6 +536,7 @@ void ConfigList::setRootMenu(struct menu *menu)
        rootEntry = menu;
        updateListAll();
        setSelected(currentItem(), hasFocus());
+       ensureItemVisible(currentItem());
 }
 
 void ConfigList::setParentMenu(void)
@@ -603,6 +559,74 @@ void ConfigList::setParentMenu(void)
        }
 }
 
+/*
+ * 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 (!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();
@@ -610,7 +634,7 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
        struct menu *menu;
        enum prop_type type;
 
-       if (ev->key() == Key_Escape && mode != fullMode) {
+       if (ev->key() == Key_Escape && mode != fullMode && mode != listMode) {
                emit parentSelected();
                ev->accept();
                return;
@@ -755,23 +779,62 @@ skip:
 
 void ConfigList::focusInEvent(QFocusEvent *e)
 {
+       struct menu *menu = NULL;
+
        Parent::focusInEvent(e);
 
-       QListViewItem* item = currentItem();
-       if (!item)
-               return;
+       ConfigItem* item = (ConfigItem *)currentItem();
+       if (item) {
+               setSelected(item, TRUE);
+               menu = item->menu;
+       }
+       emit gotFocus(menu);
+}
 
-       setSelected(item, TRUE);
-       emit gotFocus();
+void ConfigList::contextMenuEvent(QContextMenuEvent *e)
+{
+       if (e->y() <= header()->geometry().bottom()) {
+               if (!headerPopup) {
+                       QAction *action;
+
+                       headerPopup = new QPopupMenu(this);
+                       action = new QAction("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("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("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, ConfigMainWindow* cview,
-                      ConfigSettings *configSettings)
-       : Parent(parent)
+ConfigView::ConfigView(QWidget* parent, const char *name)
+       : Parent(parent, name)
 {
-       list = new ConfigList(this, cview, configSettings);
+       list = new ConfigList(this, name);
        lineEdit = new ConfigLineEdit(this);
        lineEdit->hide();
 
@@ -791,6 +854,50 @@ ConfigView::~ConfigView(void)
        }
 }
 
+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;
@@ -807,6 +914,347 @@ void ConfigView::updateListAll(void)
                v->list->updateListAll();
 }
 
+ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
+       : Parent(parent, name), menu(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;
+       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("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();
+
+       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
  */
@@ -818,42 +1266,30 @@ ConfigMainWindow::ConfigMainWindow(void)
 
        QWidget *d = configApp->desktop();
 
-       ConfigSettings* configSettings = new ConfigSettings();
-#if QT_VERSION >= 300
-       width = configSettings->readNumEntry("/kconfig/qconf/window width", d->width() - 64);
-       height = configSettings->readNumEntry("/kconfig/qconf/window height", d->height() - 64);
+       width = configSettings->readNumEntry("/window width", d->width() - 64);
+       height = configSettings->readNumEntry("/window height", d->height() - 64);
        resize(width, height);
-       x = configSettings->readNumEntry("/kconfig/qconf/window x", 0, &ok);
+       x = configSettings->readNumEntry("/window x", 0, &ok);
        if (ok)
-               y = configSettings->readNumEntry("/kconfig/qconf/window y", 0, &ok);
+               y = configSettings->readNumEntry("/window y", 0, &ok);
        if (ok)
                move(x, y);
-       showDebug = configSettings->readBoolEntry("/kconfig/qconf/showDebug", false);
-
-       // read list settings into configSettings, will be used later for ConfigList setup
-       configSettings->readListSettings();
-#else
-       width = d->width() - 64;
-       height = d->height() - 64;
-       resize(width, height);
-       showDebug = false;
-#endif
 
        split1 = new QSplitter(this);
        split1->setOrientation(QSplitter::Horizontal);
        setCentralWidget(split1);
 
-       menuView = new ConfigView(split1, this, configSettings);
+       menuView = new ConfigView(split1, "menu");
        menuList = menuView->list;
 
        split2 = new QSplitter(split1);
        split2->setOrientation(QSplitter::Vertical);
 
        // create config tree
-       configView = new ConfigView(split2, this, configSettings);
+       configView = new ConfigView(split2, "config");
        configList = configView->list;
 
-       helpText = new QTextView(split2);
+       helpText = new ConfigInfoView(split2, "help");
        helpText->setTextFormat(Qt::RichText);
 
        setTabOrder(configList, helpText);
@@ -873,6 +1309,8 @@ ConfigMainWindow::ConfigMainWindow(void)
          connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
        QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
          connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
+       QAction *searchAction = new QAction("Search", "&Search", 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);
@@ -882,24 +1320,29 @@ ConfigMainWindow::ConfigMainWindow(void)
 
        QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
          showNameAction->setToggleAction(TRUE);
-         showNameAction->setOn(configList->showName);
-         connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool)));
+         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);
-         connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool)));
        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);
-         connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool)));
        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);
-         connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool)));
        QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
          showDebugAction->setToggleAction(TRUE);
-         showDebugAction->setOn(showDebug);
-         connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
+         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()));
@@ -923,6 +1366,8 @@ ConfigMainWindow::ConfigMainWindow(void)
        saveAction->addTo(config);
        saveAsAction->addTo(config);
        config->insertSeparator();
+       searchAction->addTo(config);
+       config->insertSeparator();
        quitAction->addTo(config);
 
        // create options menu
@@ -942,20 +1387,27 @@ ConfigMainWindow::ConfigMainWindow(void)
        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(void)),
-               SLOT(listFocusChanged(void)));
-       connect(menuList, SIGNAL(gotFocus(void)),
+       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 *)));
 
-#if QT_VERSION >= 300
-       QString listMode = configSettings->readEntry("/kconfig/qconf/listMode", "symbol");
+       QString listMode = configSettings->readEntry("/listMode", "symbol");
        if (listMode == "single")
                showSingleView();
        else if (listMode == "full")
@@ -964,162 +1416,13 @@ ConfigMainWindow::ConfigMainWindow(void)
                showSplitView();
 
        // UI setup done, restore splitter positions
-       QValueList<int> sizes = configSettings->readSizes("/kconfig/qconf/split1", &ok);
+       QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
        if (ok)
                split1->setSizes(sizes);
 
-       sizes = configSettings->readSizes("/kconfig/qconf/split2", &ok);
+       sizes = configSettings->readSizes("/split2", &ok);
        if (ok)
                split2->setSizes(sizes);
-#else
-       showSplitView();
-#endif
-       delete configSettings;
-}
-
-static QString 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;
-}
-
-static void expr_print_help(void *data, const char *str)
-{
-       reinterpret_cast<QString*>(data)->append(print_filter(str));
-}
-
-/*
- * display a new help entry as soon as a new menu entry is selected
- */
-void ConfigMainWindow::setHelp(QListViewItem* item)
-{
-       struct symbol* sym;
-       struct menu* menu = 0;
-
-       configList->parent()->lineEdit->hide();
-       if (item)
-               menu = ((ConfigItem*)item)->menu;
-       if (!menu) {
-               helpText->setText(QString::null);
-               return;
-       }
-
-       QString head, debug, help;
-       menu = ((ConfigItem*)item)->menu;
-       sym = menu->sym;
-       if (sym) {
-               if (menu->prompt) {
-                       head += "<big><b>";
-                       head += print_filter(_(menu->prompt->text));
-                       head += "</b></big>";
-                       if (sym->name) {
-                               head += " (";
-                               head += print_filter(_(sym->name));
-                               head += ")";
-                       }
-               } else if (sym->name) {
-                       head += "<big><b>";
-                       head += print_filter(_(sym->name));
-                       head += "</b></big>";
-               }
-               head += "<br><br>";
-
-               if (showDebug) {
-                       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 += "prompt: ";
-                                       debug += print_filter(_(prop->text));
-                                       debug += "<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>";
-               }
-
-               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);
-       helpText->setText(head + debug + help);
 }
 
 void ConfigMainWindow::loadConfig(void)
@@ -1147,21 +1450,73 @@ void ConfigMainWindow::saveConfigAs(void)
                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);
        backAction->setEnabled(TRUE);
 }
 
-void ConfigMainWindow::listFocusChanged(void)
+void ConfigMainWindow::setMenuLink(struct menu *menu)
 {
-       if (menuList->hasFocus()) {
-               if (menuList->mode == menuMode)
+       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();
-               setHelp(menuList->selectedItem());
-       } else if (configList->hasFocus()) {
-               setHelp(configList->selectedItem());
+                       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)
@@ -1223,53 +1578,6 @@ void ConfigMainWindow::showFullView(void)
        configList->setFocus();
 }
 
-void ConfigMainWindow::setShowAll(bool b)
-{
-       if (configList->showAll == b)
-               return;
-       configList->showAll = b;
-       configList->updateListAll();
-       menuList->showAll = b;
-       menuList->updateListAll();
-}
-
-void ConfigMainWindow::setShowDebug(bool b)
-{
-       if (showDebug == b)
-               return;
-       showDebug = b;
-}
-
-void ConfigMainWindow::setShowName(bool b)
-{
-       if (configList->showName == b)
-               return;
-       configList->showName = b;
-       configList->reinit();
-       menuList->showName = b;
-       menuList->reinit();
-}
-
-void ConfigMainWindow::setShowRange(bool b)
-{
-       if (configList->showRange == b)
-               return;
-       configList->showRange = b;
-       configList->reinit();
-       menuList->showRange = b;
-       menuList->reinit();
-}
-
-void ConfigMainWindow::setShowData(bool b)
-{
-       if (configList->showData == b)
-               return;
-       configList->showData = b;
-       configList->reinit();
-       menuList->showData = b;
-       menuList->reinit();
-}
-
 /*
  * ask for saving configuration before quitting
  * TODO ask only when something changed
@@ -1324,17 +1632,10 @@ void ConfigMainWindow::showAbout(void)
 
 void ConfigMainWindow::saveSettings(void)
 {
-#if QT_VERSION >= 300
-       ConfigSettings *configSettings = new ConfigSettings;
-       configSettings->writeEntry("/kconfig/qconf/window x", pos().x());
-       configSettings->writeEntry("/kconfig/qconf/window y", pos().y());
-       configSettings->writeEntry("/kconfig/qconf/window width", size().width());
-       configSettings->writeEntry("/kconfig/qconf/window height", size().height());
-       configSettings->writeEntry("/kconfig/qconf/showName", configList->showName);
-       configSettings->writeEntry("/kconfig/qconf/showRange", configList->showRange);
-       configSettings->writeEntry("/kconfig/qconf/showData", configList->showData);
-       configSettings->writeEntry("/kconfig/qconf/showAll", configList->showAll);
-       configSettings->writeEntry("/kconfig/qconf/showDebug", showDebug);
+       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) {
@@ -1350,13 +1651,10 @@ void ConfigMainWindow::saveSettings(void)
                entry = "full";
                break;
        }
-       configSettings->writeEntry("/kconfig/qconf/listMode", entry);
+       configSettings->writeEntry("/listMode", entry);
 
-       configSettings->writeSizes("/kconfig/qconf/split1", split1->sizes());
-       configSettings->writeSizes("/kconfig/qconf/split2", split2->sizes());
-
-       delete configSettings;
-#endif
+       configSettings->writeSizes("/split1", split1->sizes());
+       configSettings->writeSizes("/split2", split2->sizes());
 }
 
 void fixup_rootmenu(struct menu *menu)
@@ -1414,13 +1712,19 @@ int main(int ac, char** av)
        conf_read(NULL);
        //zconfdump(stdout);
 
+       configSettings = new ConfigSettings();
+       configSettings->beginGroup("/kconfig/qconf");
        v = new ConfigMainWindow();
 
        //zconfdump(stdout);
-       v->show();
+       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;
 }
index e52f3e9..6a9e3b1 100644 (file)
@@ -7,9 +7,25 @@
 #if QT_VERSION >= 300
 #include <qsettings.h>
 #else
-class QSettings { };
+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;
@@ -18,64 +34,38 @@ class ConfigMainWindow;
 
 class ConfigSettings : public QSettings {
 public:
-       ConfigSettings();
-
-#if QT_VERSION >= 300
-       void readListSettings();
        QValueList<int> readSizes(const QString& key, bool *ok);
        bool writeSizes(const QString& key, const QValueList<int>& value);
-#endif
-
-       bool showAll;
-       bool showName;
-       bool showRange;
-       bool showData;
-};
-
-class ConfigView : public QVBox {
-       Q_OBJECT
-       typedef class QVBox Parent;
-public:
-       ConfigView(QWidget* parent, ConfigMainWindow* cview, ConfigSettings* configSettings);
-       ~ConfigView(void);
-       static void updateList(ConfigItem* item);
-       static void updateListAll(void);
-
-public:
-       ConfigList* list;
-       ConfigLineEdit* lineEdit;
-
-       static ConfigView* viewList;
-       ConfigView* nextView;
 };
 
 enum colIdx {
        promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
 };
 enum listMode {
-       singleMode, menuMode, symbolMode, fullMode
+       singleMode, menuMode, symbolMode, fullMode, listMode
 };
 
 class ConfigList : public QListView {
        Q_OBJECT
        typedef class QListView Parent;
 public:
-       ConfigList(ConfigView* p, ConfigMainWindow* cview, ConfigSettings *configSettings);
+       ConfigList(ConfigView* p, const char *name = 0);
        void reinit(void);
        ConfigView* parent(void) const
        {
                return (ConfigView*)Parent::parent();
        }
+       ConfigItem* findConfigItem(struct menu *);
 
 protected:
-       ConfigMainWindow* cview;
-
        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);
 
@@ -83,10 +73,12 @@ public slots:
        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(void);
+       void gotFocus(struct menu *);
 
 public:
        void updateListAll(void)
@@ -137,6 +129,7 @@ public:
        struct menu *rootEntry;
        QColorGroup disabledColorGroup;
        QColorGroup inactivedColorGroup;
+       QPopupMenu* headerPopup;
 
 private:
        int colMap[colNr];
@@ -208,9 +201,7 @@ class ConfigLineEdit : public QLineEdit {
        Q_OBJECT
        typedef class QLineEdit Parent;
 public:
-       ConfigLineEdit(ConfigView* parent)
-       : Parent(parent)
-       { }
+       ConfigLineEdit(ConfigView* parent);
        ConfigView* parent(void) const
        {
                return (ConfigView*)Parent::parent();
@@ -222,26 +213,104 @@ 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
 public:
        ConfigMainWindow(void);
 public slots:
-       void setHelp(QListViewItem* item);
        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 setShowAll(bool);
-       void setShowDebug(bool);
-       void setShowRange(bool);
-       void setShowName(bool);
-       void setShowData(bool);
        void showIntro(void);
        void showAbout(void);
        void saveSettings(void);
@@ -249,15 +318,14 @@ public slots:
 protected:
        void closeEvent(QCloseEvent *e);
 
+       ConfigSearchWindow *searchWindow;
        ConfigView *menuView;
        ConfigList *menuList;
        ConfigView *configView;
        ConfigList *configList;
-       QTextView *helpText;
+       ConfigInfoView *helpText;
        QToolBar *toolBar;
        QAction *backAction;
        QSplitter* split1;
        QSplitter* split2;
-
-       bool showDebug;
 };
index 3d7877a..ee225ce 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 },
@@ -31,6 +31,7 @@ struct symbol symbol_yes = {
 };
 
 int sym_change_count;
+struct symbol *sym_defconfig_list;
 struct symbol *modules_sym;
 tristate modules_val;
 
@@ -227,7 +228,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)
@@ -306,7 +307,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)
@@ -329,7 +330,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;
                        }
                }
@@ -352,10 +353,13 @@ void sym_calc_value(struct symbol *sym)
                sym->curr.val = sym_calc_choice(sym);
        sym_validate_range(sym);
 
-       if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
+       if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
                sym_set_changed(sym);
-       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);
@@ -426,8 +430,8 @@ 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);
        }
        /*
@@ -439,21 +443,18 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val)
                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_NEW;
+                               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;
 }
@@ -591,20 +592,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;
 
@@ -679,7 +680,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;
 
index 656d2c8..e3f28b9 100644 (file)
@@ -44,7 +44,9 @@ int file_write_dep(const char *name)
                else
                        fprintf(out, "\t%s\n", file->name);
        }
-       fprintf(out, "\n.config include/linux/autoconf.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);
        return 0;
index b032206..9b44c80 100644 (file)
@@ -39,5 +39,8 @@ 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
 %%
index 345f0fc..47c8b5b 100644 (file)
@@ -53,10 +53,10 @@ kconf_id_hash (register const char *str, register unsigned int len)
       47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
       47, 47, 47, 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, 10, 15,
-       0,  0,  5, 47,  0,  0, 47, 47,  0, 10,
-       0, 20, 20, 20,  5,  0,  0, 20, 47, 47,
-      20, 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,
@@ -88,69 +88,75 @@ kconf_id_hash (register const char *str, register unsigned int len)
 
 struct kconf_id_strings_t
   {
-    char kconf_id_strings_str2[sizeof("if")];
-    char kconf_id_strings_str3[sizeof("int")];
-    char kconf_id_strings_str4[sizeof("help")];
-    char kconf_id_strings_str5[sizeof("endif")];
-    char kconf_id_strings_str6[sizeof("select")];
-    char kconf_id_strings_str7[sizeof("endmenu")];
-    char kconf_id_strings_str8[sizeof("tristate")];
-    char kconf_id_strings_str9[sizeof("endchoice")];
+    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("string")];
-    char kconf_id_strings_str12[sizeof("default")];
-    char kconf_id_strings_str13[sizeof("def_bool")];
-    char kconf_id_strings_str14[sizeof("menu")];
-    char kconf_id_strings_str16[sizeof("def_boolean")];
-    char kconf_id_strings_str17[sizeof("def_tristate")];
-    char kconf_id_strings_str18[sizeof("mainmenu")];
-    char kconf_id_strings_str20[sizeof("menuconfig")];
-    char kconf_id_strings_str21[sizeof("config")];
-    char kconf_id_strings_str22[sizeof("on")];
-    char kconf_id_strings_str23[sizeof("hex")];
-    char kconf_id_strings_str26[sizeof("source")];
-    char kconf_id_strings_str27[sizeof("depends")];
-    char kconf_id_strings_str28[sizeof("optional")];
-    char kconf_id_strings_str31[sizeof("enable")];
-    char kconf_id_strings_str32[sizeof("comment")];
-    char kconf_id_strings_str33[sizeof("requires")];
+    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_str41[sizeof("choice")];
-    char kconf_id_strings_str46[sizeof("prompt")];
+    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 =
   {
-    "if",
-    "int",
-    "help",
-    "endif",
-    "select",
-    "endmenu",
-    "tristate",
-    "endchoice",
-    "range",
+    "on",
     "string",
     "default",
     "def_bool",
-    "menu",
+    "range",
     "def_boolean",
     "def_tristate",
-    "mainmenu",
-    "menuconfig",
-    "config",
-    "on",
     "hex",
-    "source",
-    "depends",
+    "defconfig_list",
+    "option",
+    "if",
     "optional",
-    "enable",
-    "comment",
+    "endif",
+    "choice",
+    "endmenu",
     "requires",
+    "endchoice",
+    "config",
+    "modules",
+    "int",
+    "menu",
+    "prompt",
+    "depends",
+    "tristate",
     "bool",
+    "menuconfig",
+    "select",
     "boolean",
-    "choice",
-    "prompt"
+    "help",
+    "source",
+    "comment",
+    "mainmenu",
+    "enable"
   };
 #define kconf_id_strings ((const char *) &kconf_id_strings_contents)
 #ifdef __GNUC__
@@ -161,9 +167,9 @@ kconf_id_lookup (register const char *str, register unsigned int len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 30,
+      TOTAL_KEYWORDS = 33,
       MIN_WORD_LENGTH = 2,
-      MAX_WORD_LENGTH = 12,
+      MAX_WORD_LENGTH = 14,
       MIN_HASH_VALUE = 2,
       MAX_HASH_VALUE = 46
     };
@@ -171,43 +177,48 @@ kconf_id_lookup (register const char *str, register unsigned int len)
   static struct kconf_id wordlist[] =
     {
       {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2,            T_IF,           TF_COMMAND|TF_PARAM},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3,            T_TYPE,         TF_COMMAND, S_INT},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str4,            T_HELP,         TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5,            T_ENDIF,        TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6,            T_SELECT,       TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7,    T_ENDMENU,      TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8,    T_TYPE,         TF_COMMAND, S_TRISTATE},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9,    T_ENDCHOICE,    TF_COMMAND},
+      {(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_TYPE,         TF_COMMAND, S_STRING},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,   T_DEFAULT,      TF_COMMAND, S_UNKNOWN},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13,   T_DEFAULT,      TF_COMMAND, S_BOOLEAN},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,           T_MENU,         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_DEFAULT,      TF_COMMAND, S_BOOLEAN},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,   T_DEFAULT,      TF_COMMAND, S_TRISTATE},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,   T_MAINMENU,     TF_COMMAND},
+      {(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_MENUCONFIG,   TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21,           T_CONFIG,       TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,           T_ON,           TF_PARAM},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,           T_TYPE,         TF_COMMAND, S_HEX},
-      {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26,           T_SOURCE,       TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27,   T_DEPENDS,      TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28,   T_OPTIONAL,     TF_COMMAND},
-      {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31,           T_SELECT,       TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32,   T_COMMENT,      TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33,   T_REQUIRES,     TF_COMMAND},
+      {(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},
-      {-1}, {-1},
+      {(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}, {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,           T_CHOICE,       TF_COMMAND},
-      {-1}, {-1}, {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,           T_PROMPT,       TF_COMMAND}
+      {-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)
index ea7755d..2fb0a4f 100644 (file)
@@ -1,7 +1,7 @@
-/* A Bison parser, made by GNU Bison 2.0.  */
+/* 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, 2004 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"
 
      T_DEFAULT = 276,
      T_SELECT = 277,
      T_RANGE = 278,
-     T_ON = 279,
-     T_WORD = 280,
-     T_WORD_QUOTE = 281,
-     T_UNEQUAL = 282,
-     T_CLOSE_PAREN = 283,
-     T_OPEN_PAREN = 284,
-     T_EOL = 285,
-     T_OR = 286,
-     T_AND = 287,
-     T_EQUAL = 288,
-     T_NOT = 289
+     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_DEFAULT 276
 #define T_SELECT 277
 #define T_RANGE 278
-#define T_ON 279
-#define T_WORD 280
-#define T_WORD_QUOTE 281
-#define T_UNEQUAL 282
-#define T_CLOSE_PAREN 283
-#define T_OPEN_PAREN 284
-#define T_EOL 285
-#define T_OR 286
-#define T_AND 287
-#define T_EQUAL 288
-#define T_NOT 289
+#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
 
 
 
@@ -187,6 +193,11 @@ 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 {
@@ -197,7 +208,7 @@ typedef union YYSTYPE {
        struct menu *menu;
        struct kconf_id *id;
 } YYSTYPE;
-/* Line 190 of yacc.c.  */
+/* Line 196 of yacc.c.  */
 
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -209,17 +220,36 @@ typedef union YYSTYPE {
 /* Copy the second part of user declarations.  */
 
 
-/* Line 213 of yacc.c.  */
+/* Line 219 of yacc.c.  */
 
 
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
+#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 YYFREE
-#  define YYFREE free
+#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 YYMALLOC
-#  define YYMALLOC malloc
+# ifndef YY_
+#  define YY_(msgid) msgid
 # endif
+#endif
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
 
 /* The parser invokes alloca or malloc; define the necessary symbols.  */
 
@@ -229,6 +259,10 @@ typedef union YYSTYPE {
 #    define YYSTACK_ALLOC __builtin_alloca
 #   else
 #    define YYSTACK_ALLOC alloca
+#    if defined (__STDC__) || defined (__cplusplus)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     define YYINCLUDED_STDLIB_H
+#    endif
 #   endif
 #  endif
 # endif
@@ -236,13 +270,39 @@ typedef union YYSTYPE {
 # ifdef YYSTACK_ALLOC
    /* Pacify GCC's `empty if-body' warning. */
 #  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-#  if defined (__STDC__) || defined (__cplusplus)
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   define YYSIZE_T size_t
+#  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
 #  define YYSTACK_ALLOC YYMALLOC
 #  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1)
+#  endif
+#  ifdef __cplusplus
+extern "C" {
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \
+       && (defined (__STDC__) || defined (__cplusplus)))
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \
+       && (defined (__STDC__) || defined (__cplusplus)))
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifdef __cplusplus
+}
+#  endif
 # endif
 #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
 
@@ -277,7 +337,7 @@ union yyalloc
 #   define YYCOPY(To, From, Count)             \
       do                                       \
        {                                       \
-         register YYSIZE_T yyi;                \
+         YYSIZE_T yyi;                         \
          for (yyi = 0; yyi < (Count); yyi++)   \
            (To)[yyi] = (From)[yyi];            \
        }                                       \
@@ -312,22 +372,22 @@ union yyalloc
 /* YYFINAL -- State number of the termination state. */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   264
+#define YYLAST   275
 
 /* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  35
+#define YYNTOKENS  36
 /* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  42
+#define YYNNTS  45
 /* YYNRULES -- Number of rules. */
-#define YYNRULES  104
+#define YYNRULES  110
 /* YYNRULES -- Number of states. */
-#define YYNSTATES  175
+#define YYNSTATES  183
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   289
+#define YYMAXUTOK   290
 
-#define YYTRANSLATE(YYX)                                               \
+#define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
@@ -361,7 +421,8 @@ static const unsigned char yytranslate[] =
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        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
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35
 };
 
 #if YYDEBUG
@@ -372,72 +433,75 @@ static const unsigned short int yyprhs[] =
        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,   104,   109,
-     114,   119,   125,   128,   131,   133,   137,   138,   141,   144,
-     147,   150,   153,   158,   162,   165,   170,   171,   174,   178,
-     180,   184,   185,   188,   191,   194,   198,   201,   203,   207,
-     208,   211,   214,   217,   221,   225,   228,   231,   234,   235,
-     238,   241,   244,   249,   253,   257,   258,   261,   263,   265,
-     268,   271,   274,   276,   279,   280,   283,   285,   289,   293,
-     297,   300,   304,   308,   310
+      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[] =
 {
-      36,     0,    -1,    37,    -1,    -1,    37,    39,    -1,    37,
-      50,    -1,    37,    61,    -1,    37,     3,    71,    73,    -1,
-      37,    72,    -1,    37,    25,     1,    30,    -1,    37,    38,
-       1,    30,    -1,    37,     1,    30,    -1,    16,    -1,    19,
+      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,    30,    -1,    56,    -1,    65,    -1,    42,    -1,    44,
-      -1,    63,    -1,    25,     1,    30,    -1,     1,    30,    -1,
-      10,    25,    30,    -1,    41,    45,    -1,    11,    25,    30,
-      -1,    43,    45,    -1,    -1,    45,    46,    -1,    45,    69,
-      -1,    45,    67,    -1,    45,    40,    -1,    45,    30,    -1,
-      20,    70,    30,    -1,    19,    71,    74,    30,    -1,    21,
-      75,    74,    30,    -1,    22,    25,    74,    30,    -1,    23,
-      76,    76,    74,    30,    -1,     7,    30,    -1,    47,    51,
-      -1,    72,    -1,    48,    53,    49,    -1,    -1,    51,    52,
-      -1,    51,    69,    -1,    51,    67,    -1,    51,    30,    -1,
-      51,    40,    -1,    19,    71,    74,    30,    -1,    20,    70,
-      30,    -1,    18,    30,    -1,    21,    25,    74,    30,    -1,
-      -1,    53,    39,    -1,    14,    75,    73,    -1,    72,    -1,
-      54,    57,    55,    -1,    -1,    57,    39,    -1,    57,    61,
-      -1,    57,    50,    -1,     4,    71,    30,    -1,    58,    68,
-      -1,    72,    -1,    59,    62,    60,    -1,    -1,    62,    39,
-      -1,    62,    61,    -1,    62,    50,    -1,     6,    71,    30,
-      -1,     9,    71,    30,    -1,    64,    68,    -1,    12,    30,
-      -1,    66,    13,    -1,    -1,    68,    69,    -1,    68,    30,
-      -1,    68,    40,    -1,    16,    24,    75,    30,    -1,    16,
-      75,    30,    -1,    17,    75,    30,    -1,    -1,    71,    74,
-      -1,    25,    -1,    26,    -1,     5,    30,    -1,     8,    30,
-      -1,    15,    30,    -1,    30,    -1,    73,    30,    -1,    -1,
-      14,    75,    -1,    76,    -1,    76,    33,    76,    -1,    76,
-      27,    76,    -1,    29,    75,    28,    -1,    34,    75,    -1,
-      75,    31,    75,    -1,    75,    32,    75,    -1,    25,    -1,
-      26,    -1
+      -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 int yyrline[] =
 {
-       0,   103,   103,   105,   107,   108,   109,   110,   111,   112,
-     113,   117,   121,   121,   121,   121,   121,   121,   121,   125,
-     126,   127,   128,   129,   130,   134,   135,   141,   149,   155,
-     163,   173,   175,   176,   177,   178,   179,   182,   190,   196,
-     206,   212,   220,   229,   234,   242,   245,   247,   248,   249,
-     250,   251,   254,   260,   271,   277,   287,   289,   294,   302,
-     310,   313,   315,   316,   317,   322,   329,   334,   342,   345,
-     347,   348,   349,   352,   360,   367,   374,   380,   387,   389,
-     390,   391,   394,   399,   404,   412,   414,   419,   420,   423,
-     424,   425,   429,   430,   433,   434,   437,   438,   439,   440,
-     441,   442,   443,   446,   447
+       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[] =
 {
@@ -445,17 +509,18 @@ static const char *const yytname[] =
   "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_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",
+  "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", "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
+  "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
 
@@ -467,24 +532,25 @@ 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
+     285,   286,   287,   288,   289,   290
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const unsigned char yyr1[] =
 {
-       0,    35,    36,    37,    37,    37,    37,    37,    37,    37,
-      37,    37,    38,    38,    38,    38,    38,    38,    38,    39,
-      39,    39,    39,    39,    39,    40,    40,    41,    42,    43,
-      44,    45,    45,    45,    45,    45,    45,    46,    46,    46,
-      46,    46,    47,    48,    49,    50,    51,    51,    51,    51,
-      51,    51,    52,    52,    52,    52,    53,    53,    54,    55,
-      56,    57,    57,    57,    57,    58,    59,    60,    61,    62,
-      62,    62,    62,    63,    64,    65,    66,    67,    68,    68,
-      68,    68,    69,    69,    69,    70,    70,    71,    71,    72,
-      72,    72,    73,    73,    74,    74,    75,    75,    75,    75,
-      75,    75,    75,    76,    76
+       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.  */
@@ -493,14 +559,15 @@ static const unsigned char yyr2[] =
        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,     3,     4,     4,
-       4,     5,     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
+       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
@@ -511,175 +578,164 @@ static const unsigned char yydefact[] =
        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,    46,    56,     5,    61,    20,    78,    69,     6,    24,
-      78,    21,     8,    11,    87,    88,     0,     0,    89,     0,
-      42,    90,     0,     0,     0,   103,   104,     0,     0,     0,
-      96,    91,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    92,     7,    65,    73,    74,    27,    29,     0,
-     100,     0,     0,    58,     0,     0,     9,    10,     0,     0,
-       0,     0,     0,    85,     0,     0,     0,     0,    36,    35,
-      32,     0,    34,    33,     0,     0,    85,     0,    50,    51,
-      47,    49,    48,    57,    45,    44,    62,    64,    60,    63,
-      59,    80,    81,    79,    70,    72,    68,    71,    67,    93,
-      99,   101,   102,    98,    97,    26,    76,     0,     0,     0,
-      94,     0,    94,    94,    94,     0,     0,    77,    54,    94,
-       0,    94,     0,    83,    84,     0,     0,    37,    86,     0,
-       0,    94,    25,     0,    53,     0,    82,    95,    38,    39,
-      40,     0,    52,    55,    41
+      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 int yydefgoto[] =
 {
-      -1,     1,     2,    25,    26,    99,    27,    28,    29,    30,
-      64,   100,    31,    32,   114,    33,    66,   110,    67,    34,
-     118,    35,    68,    36,    37,   126,    38,    70,    39,    40,
-      41,   101,   102,    69,   103,   141,   142,    42,    73,   156,
-      59,    60
+      -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 -78
+#define YYPACT_NINF -135
 static const short int yypact[] =
 {
-     -78,     2,   159,   -78,   -21,     0,     0,   -12,     0,     1,
-       4,     0,    27,    38,    60,    58,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   100,   -78,   104,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,    86,   113,   -78,   114,
-     -78,   -78,   125,   127,   128,   -78,   -78,    60,    60,   210,
-      65,   -78,   141,   142,    39,   103,   182,   200,     6,    66,
-       6,   131,   -78,   146,   -78,   -78,   -78,   -78,   -78,   196,
-     -78,    60,    60,   146,    40,    40,   -78,   -78,   155,   156,
-      -2,    60,     0,     0,    60,   105,    40,   194,   -78,   -78,
-     -78,   206,   -78,   -78,   183,     0,     0,   195,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,
-     -78,   197,   -78,   -78,   -78,   -78,   -78,    60,   213,   216,
-     212,   203,   212,   190,   212,    40,   208,   -78,   -78,   212,
-     222,   212,   219,   -78,   -78,    60,   223,   -78,   -78,   224,
-     225,   212,   -78,   226,   -78,   227,   -78,    47,   -78,   -78,
-     -78,   228,   -78,   -78,   -78
+    -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 int yypgoto[] =
 {
-     -78,   -78,   -78,   -78,   164,   -36,   -78,   -78,   -78,   -78,
-     230,   -78,   -78,   -78,   -78,    29,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,    59,   -78,   -78,   -78,
-     -78,   -78,   198,   220,    24,   157,    -5,   169,   202,    74,
-     -53,   -77
+    -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 -76
+#define YYTABLE_NINF -82
 static const short int yytable[] =
 {
-      46,    47,     3,    49,    79,    80,    52,   133,   134,    43,
-       6,     7,     8,     9,    10,    11,    12,    13,    48,   145,
-      14,    15,   137,    55,    56,    44,    45,    57,   131,   132,
-     109,    50,    58,   122,    51,   122,    24,   138,   139,   -28,
-      88,   143,   -28,   -28,   -28,   -28,   -28,   -28,   -28,   -28,
-     -28,    89,    53,   -28,   -28,    90,    91,   -28,    92,    93,
-      94,    95,    96,    54,    97,    55,    56,    88,   161,    98,
-     -66,   -66,   -66,   -66,   -66,   -66,   -66,   -66,    81,    82,
-     -66,   -66,    90,    91,   152,    55,    56,   140,    61,    57,
-     112,    97,    84,   123,    58,   123,   121,   117,    85,   125,
-     149,    62,   167,   -30,    88,    63,   -30,   -30,   -30,   -30,
-     -30,   -30,   -30,   -30,   -30,    89,    72,   -30,   -30,    90,
-      91,   -30,    92,    93,    94,    95,    96,   119,    97,   127,
-     144,   -75,    88,    98,   -75,   -75,   -75,   -75,   -75,   -75,
-     -75,   -75,   -75,    74,    75,   -75,   -75,    90,    91,   -75,
-     -75,   -75,   -75,   -75,   -75,    76,    97,    77,    78,    -2,
-       4,   121,     5,     6,     7,     8,     9,    10,    11,    12,
-      13,    86,    87,    14,    15,    16,   129,    17,    18,    19,
-      20,    21,    22,    88,    23,   135,   136,   -43,   -43,    24,
-     -43,   -43,   -43,   -43,    89,   146,   -43,   -43,    90,    91,
-     104,   105,   106,   107,   155,     7,     8,    97,    10,    11,
-      12,    13,   108,   148,    14,    15,   158,   159,   160,   147,
-     151,    81,    82,   163,   130,   165,   155,    81,    82,    82,
-      24,   113,   116,   157,   124,   171,   115,   120,   162,   128,
-      72,    81,    82,   153,    81,    82,   154,    81,    82,   166,
-      81,    82,   164,   168,   169,   170,   172,   173,   174,    65,
-      71,    83,     0,   150,   111
+      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 short int yycheck[] =
 {
-       5,     6,     0,     8,    57,    58,    11,    84,    85,    30,
-       4,     5,     6,     7,     8,     9,    10,    11,    30,    96,
-      14,    15,    24,    25,    26,    25,    26,    29,    81,    82,
-      66,    30,    34,    69,    30,    71,    30,    90,    91,     0,
-       1,    94,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    25,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    25,    25,    25,    26,     1,   145,    30,
-       4,     5,     6,     7,     8,     9,    10,    11,    31,    32,
-      14,    15,    16,    17,   137,    25,    26,    92,    30,    29,
-      66,    25,    27,    69,    34,    71,    30,    68,    33,    70,
-     105,     1,   155,     0,     1,     1,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    30,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    68,    25,    70,
-      25,     0,     1,    30,     3,     4,     5,     6,     7,     8,
-       9,    10,    11,    30,    30,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    30,    25,    30,    30,     0,
-       1,    30,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    30,    30,    14,    15,    16,    30,    18,    19,    20,
-      21,    22,    23,     1,    25,    30,    30,     5,     6,    30,
-       8,     9,    10,    11,    12,     1,    14,    15,    16,    17,
-      18,    19,    20,    21,    14,     5,     6,    25,     8,     9,
-      10,    11,    30,    30,    14,    15,   142,   143,   144,    13,
-      25,    31,    32,   149,    28,   151,    14,    31,    32,    32,
-      30,    67,    68,    30,    70,   161,    67,    68,    30,    70,
-      30,    31,    32,    30,    31,    32,    30,    31,    32,    30,
-      31,    32,    30,    30,    30,    30,    30,    30,    30,    29,
-      40,    59,    -1,   106,    66
+       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,    36,    37,     0,     1,     3,     4,     5,     6,     7,
+       0,    37,    38,     0,     1,     3,     4,     5,     6,     7,
        8,     9,    10,    11,    14,    15,    16,    18,    19,    20,
-      21,    22,    23,    25,    30,    38,    39,    41,    42,    43,
-      44,    47,    48,    50,    54,    56,    58,    59,    61,    63,
-      64,    65,    72,    30,    25,    26,    71,    71,    30,    71,
-      30,    30,    71,    25,    25,    25,    26,    29,    34,    75,
-      76,    30,     1,     1,    45,    45,    51,    53,    57,    68,
-      62,    68,    30,    73,    30,    30,    30,    30,    30,    75,
-      75,    31,    32,    73,    27,    33,    30,    30,     1,    12,
-      16,    17,    19,    20,    21,    22,    23,    25,    30,    40,
-      46,    66,    67,    69,    18,    19,    20,    21,    30,    40,
-      52,    67,    69,    39,    49,    72,    39,    50,    55,    61,
-      72,    30,    40,    69,    39,    50,    60,    61,    72,    30,
-      28,    75,    75,    76,    76,    30,    30,    24,    75,    75,
-      71,    70,    71,    75,    25,    76,     1,    13,    30,    71,
-      70,    25,    75,    30,    30,    14,    74,    30,    74,    74,
-      74,    76,    30,    74,    30,    74,    30,    75,    30,    30,
-      30,    74,    30,    30,    30
+      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)
@@ -709,8 +765,8 @@ do                                                          \
       goto yybackup;                                           \
     }                                                          \
   else                                                         \
-    {                                                          \
-      yyerror ("syntax error: cannot back up");\
+    {                                                          \
+      yyerror (YY_("syntax error: cannot back up")); \
       YYERROR;                                                 \
     }                                                          \
 while (0)
@@ -789,7 +845,7 @@ do {                                                                \
   if (yydebug)                                                 \
     {                                                          \
       YYFPRINTF (stderr, "%s ", Title);                                \
-      yysymprint (stderr,                                      \
+      yysymprint (stderr,                                      \
                   Type, Value);        \
       YYFPRINTF (stderr, "\n");                                        \
     }                                                          \
@@ -837,13 +893,13 @@ yy_reduce_print (yyrule)
 #endif
 {
   int yyi;
-  unsigned int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+  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)         \
@@ -872,7 +928,7 @@ 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.  */
 
 #ifndef YYMAXDEPTH
@@ -896,7 +952,7 @@ yystrlen (yystr)
      const char *yystr;
 #   endif
 {
-  register const char *yys = yystr;
+  const char *yys = yystr;
 
   while (*yys++ != '\0')
     continue;
@@ -921,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;
@@ -932,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
 
@@ -998,7 +1102,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 
   switch (yytype)
     {
-      case 48: /* choice_entry */
+      case 52: /* "choice_entry" */
 
         {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1008,7 +1112,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 };
 
         break;
-      case 54: /* if_entry */
+      case 58: /* "if_entry" */
 
         {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1018,7 +1122,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 };
 
         break;
-      case 59: /* menu_entry */
+      case 63: /* "menu_entry" */
 
         {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1082,13 +1186,13 @@ 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;
@@ -1106,12 +1210,12 @@ yyparse ()
   /* The state stack.  */
   short int yyssa[YYINITDEPTH];
   short int *yyss = yyssa;
-  register short int *yyssp;
+  short int *yyssp;
 
   /* The semantic value stack.  */
   YYSTYPE yyvsa[YYINITDEPTH];
   YYSTYPE *yyvs = yyvsa;
-  register YYSTYPE *yyvsp;
+  YYSTYPE *yyvsp;
 
 
 
@@ -1143,9 +1247,6 @@ yyparse ()
   yyssp = yyss;
   yyvsp = yyvs;
 
-
-  yyvsp[0] = yylval;
-
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -1178,7 +1279,7 @@ yyparse ()
           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),
 
@@ -1189,11 +1290,11 @@ 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;
@@ -1203,7 +1304,7 @@ yyparse ()
        union yyalloc *yyptr =
          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
        if (! yyptr)
-         goto yyoverflowlab;
+         goto yyexhaustedlab;
        YYSTACK_RELOCATE (yyss);
        YYSTACK_RELOCATE (yyvs);
 
@@ -1403,7 +1504,7 @@ yyreduce:
 ;}
     break;
 
-  case 37:
+  case 38:
 
     {
        menu_set_type((yyvsp[-2].id)->stype);
@@ -1413,7 +1514,7 @@ yyreduce:
 ;}
     break;
 
-  case 38:
+  case 39:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
@@ -1421,7 +1522,7 @@ yyreduce:
 ;}
     break;
 
-  case 39:
+  case 40:
 
     {
        menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr));
@@ -1433,7 +1534,7 @@ yyreduce:
 ;}
     break;
 
-  case 40:
+  case 41:
 
     {
        menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
@@ -1441,7 +1542,7 @@ yyreduce:
 ;}
     break;
 
-  case 41:
+  case 42:
 
     {
        menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr));
@@ -1449,7 +1550,29 @@ yyreduce:
 ;}
     break;
 
-  case 42:
+  case 45:
+
+    {
+       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 46:
+
+    { (yyval.string) = NULL; ;}
+    break;
+
+  case 47:
+
+    { (yyval.string) = (yyvsp[0].string); ;}
+    break;
+
+  case 48:
 
     {
        struct symbol *sym = sym_lookup(NULL, 0);
@@ -1460,14 +1583,14 @@ yyreduce:
 ;}
     break;
 
-  case 43:
+  case 49:
 
     {
        (yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 44:
+  case 50:
 
     {
        if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) {
@@ -1477,7 +1600,7 @@ yyreduce:
 ;}
     break;
 
-  case 52:
+  case 58:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
@@ -1485,7 +1608,7 @@ yyreduce:
 ;}
     break;
 
-  case 53:
+  case 59:
 
     {
        if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) {
@@ -1498,7 +1621,7 @@ yyreduce:
 ;}
     break;
 
-  case 54:
+  case 60:
 
     {
        current_entry->sym->flags |= SYMBOL_OPTIONAL;
@@ -1506,7 +1629,7 @@ yyreduce:
 ;}
     break;
 
-  case 55:
+  case 61:
 
     {
        if ((yyvsp[-3].id)->stype == S_UNKNOWN) {
@@ -1518,7 +1641,7 @@ yyreduce:
 ;}
     break;
 
-  case 58:
+  case 64:
 
     {
        printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
@@ -1528,7 +1651,7 @@ yyreduce:
 ;}
     break;
 
-  case 59:
+  case 65:
 
     {
        if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) {
@@ -1538,7 +1661,7 @@ yyreduce:
 ;}
     break;
 
-  case 65:
+  case 71:
 
     {
        menu_add_entry(NULL);
@@ -1547,14 +1670,14 @@ yyreduce:
 ;}
     break;
 
-  case 66:
+  case 72:
 
     {
        (yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 67:
+  case 73:
 
     {
        if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) {
@@ -1564,7 +1687,7 @@ yyreduce:
 ;}
     break;
 
-  case 73:
+  case 79:
 
     {
        printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
@@ -1572,7 +1695,7 @@ yyreduce:
 ;}
     break;
 
-  case 74:
+  case 80:
 
     {
        menu_add_entry(NULL);
@@ -1581,14 +1704,14 @@ yyreduce:
 ;}
     break;
 
-  case 75:
+  case 81:
 
     {
        menu_end_entry();
 ;}
     break;
 
-  case 76:
+  case 82:
 
     {
        printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
@@ -1596,14 +1719,14 @@ yyreduce:
 ;}
     break;
 
-  case 77:
+  case 83:
 
     {
        current_entry->sym->help = (yyvsp[0].string);
 ;}
     break;
 
-  case 82:
+  case 88:
 
     {
        menu_add_dep((yyvsp[-1].expr));
@@ -1611,7 +1734,7 @@ yyreduce:
 ;}
     break;
 
-  case 83:
+  case 89:
 
     {
        menu_add_dep((yyvsp[-1].expr));
@@ -1619,7 +1742,7 @@ yyreduce:
 ;}
     break;
 
-  case 84:
+  case 90:
 
     {
        menu_add_dep((yyvsp[-1].expr));
@@ -1627,87 +1750,88 @@ yyreduce:
 ;}
     break;
 
-  case 86:
+  case 92:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr));
 ;}
     break;
 
-  case 89:
+  case 95:
 
     { (yyval.id) = (yyvsp[-1].id); ;}
     break;
 
-  case 90:
+  case 96:
 
     { (yyval.id) = (yyvsp[-1].id); ;}
     break;
 
-  case 91:
+  case 97:
 
     { (yyval.id) = (yyvsp[-1].id); ;}
     break;
 
-  case 94:
+  case 100:
 
     { (yyval.expr) = NULL; ;}
     break;
 
-  case 95:
+  case 101:
 
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
-  case 96:
+  case 102:
 
     { (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)); ;}
     break;
 
-  case 98:
+  case 104:
 
     { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
     break;
 
-  case 99:
+  case 105:
 
     { (yyval.expr) = (yyvsp[-1].expr); ;}
     break;
 
-  case 100:
+  case 106:
 
     { (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)); ;}
     break;
 
-  case 102:
+  case 108:
 
     { (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)); ;}
     break;
 
-  case 104:
+  case 110:
 
     { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;}
     break;
 
 
+      default: break;
     }
 
-/* Line 1037 of yacc.c.  */
+/* Line 1126 of yacc.c.  */
 
 \f
   yyvsp -= yylen;
@@ -1747,12 +1871,36 @@ yyerrlab:
 
       if (YYPACT_NINF < yyn && yyn < YYLAST)
        {
-         YYSIZE_T yysize = 0;
          int yytype = YYTRANSLATE (yychar);
-         const char* yyprefix;
-         char *yymsg;
+         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;
+
          /* Start YYX at -YYN if negative to avoid negative indexes in
             YYCHECK.  */
          int yyxbegin = yyn < 0 ? -yyn : 0;
@@ -1760,48 +1908,68 @@ yyerrlab:
          /* Stay within bounds of both yycheck and yytname.  */
          int yychecklim = YYLAST - yyn;
          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-         int yycount = 0;
+         int yycount = 1;
+
+         yyarg[0] = yytname[yytype];
+         yyfmt = yystpcpy (yyformat, yyunexpected);
 
-         yyprefix = ", expecting ";
          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
              {
-               yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
-               yycount += 1;
-               if (yycount == 5)
+               if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
                  {
-                   yysize = 0;
+                   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;
              }
-         yysize += (sizeof ("syntax error, unexpected ")
-                    + yystrlen (yytname[yytype]));
-         yymsg = (char *) YYSTACK_ALLOC (yysize);
-         if (yymsg != 0)
-           {
-             char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
-             yyp = yystpcpy (yyp, yytname[yytype]);
 
-             if (yycount < 5)
+         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)
+           {
+             /* 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))
                {
-                 yyprefix = ", expecting ";
-                 for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-                   if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-                     {
-                       yyp = yystpcpy (yyp, yyprefix);
-                       yyp = yystpcpy (yyp, yytname[yyx]);
-                       yyprefix = " or ";
-                     }
+                 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"));
     }
 
 
@@ -1813,18 +1981,9 @@ yyerrlab:
 
       if (yychar <= YYEOF)
         {
-          /* If at end of input, pop the error token,
-            then the rest of the stack, then return failure.  */
+         /* Return failure if at end of input.  */
          if (yychar == YYEOF)
-            for (;;)
-              {
-
-                YYPOPSTACK;
-                if (yyssp == yyss)
-                  YYABORT;
-                yydestruct ("Error: popping",
-                             yystos[*yyssp], yyvsp);
-              }
+           YYABORT;
         }
       else
        {
@@ -1843,12 +2002,11 @@ yyerrlab:
 `---------------------------------------------------*/
 yyerrorlab:
 
-#ifdef __GNUC__
-  /* Pacify GCC when the user code never invokes YYERROR and the label
-     yyerrorlab therefore never appears in user code.  */
+  /* 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;
-#endif
 
 yyvsp -= yylen;
   yyssp -= yylen;
@@ -1911,23 +2069,29 @@ yyacceptlab:
 | yyabortlab -- YYABORT comes here.  |
 `-----------------------------------*/
 yyabortlab:
-  yydestruct ("Error: discarding lookahead",
-              yytoken, &yylval);
-  yychar = YYEMPTY;
   yyresult = 1;
   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);
@@ -1948,7 +2112,9 @@ void conf_parse(const char *name)
 
        sym_init();
        menu_init();
-       modules_sym = sym_lookup("MODULES", 0);
+       modules_sym = sym_lookup(NULL, 0);
+       modules_sym->type = S_BOOLEAN;
+       modules_sym->flags |= SYMBOL_AUTO;
        rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
 #if YYDEBUG
@@ -1958,6 +2124,12 @@ void conf_parse(const char *name)
        zconfparse();
        if (zconfnerrs)
                exit(1);
+       if (!modules_sym->prop) {
+               struct property *prop;
+
+               prop = prop_alloc(P_DEFAULT, modules_sym);
+               prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
+       }
        menu_finalize(&rootmenu);
        for_all_symbols(i, sym) {
                sym_check_deps(sym);
index 1f61fba..ab44feb 100644 (file)
@@ -71,6 +71,7 @@ static struct menu *current_menu, *current_entry;
 %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
@@ -91,6 +92,7 @@ static struct menu *current_menu, *current_entry;
 %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",
@@ -173,6 +175,7 @@ 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
@@ -215,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
@@ -458,7 +481,9 @@ void conf_parse(const char *name)
 
        sym_init();
        menu_init();
-       modules_sym = sym_lookup("MODULES", 0);
+       modules_sym = sym_lookup(NULL, 0);
+       modules_sym->type = S_BOOLEAN;
+       modules_sym->flags |= SYMBOL_AUTO;
        rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
 #if YYDEBUG
@@ -468,6 +493,12 @@ void conf_parse(const char *name)
        zconfparse();
        if (zconfnerrs)
                exit(1);
+       if (!modules_sym->prop) {
+               struct property *prop;
+
+               prop = prop_alloc(P_DEFAULT, modules_sym);
+               prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
+       }
        menu_finalize(&rootmenu);
        for_all_symbols(i, sym) {
                sym_check_deps(sym);
index 3c92c83..725d61c 100644 (file)
@@ -28,7 +28,7 @@ main(int argc, char **argv)
                printf("#define KERNEL_ELFCLASS ELFCLASS64\n");
                break;
        default:
-               abort();
+               exit(1);
        }
        switch (ei[EI_DATA]) {
        case ELFDATA2LSB:
@@ -38,7 +38,7 @@ main(int argc, char **argv)
                printf("#define KERNEL_ELFDATA ELFDATA2MSB\n");
                break;
        default:
-               abort();
+               exit(1);
        }
 
        if (sizeof(unsigned long) == 4) {
@@ -53,7 +53,7 @@ main(int argc, char **argv)
        else if (memcmp(endian_test.c, "\x02\x01", 2) == 0)
                printf("#define HOST_ELFDATA ELFDATA2LSB\n");
        else
-               abort();
+               exit(1);
 
        if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0))
                printf("#define MODULE_SYMBOL_PREFIX \"_\"\n");
index d0f86ed..0dd1617 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <ctype.h>
 #include "modpost.h"
+#include "../../include/linux/license.h"
 
 /* Are we using CONFIG_MODVERSIONS? */
 int modversions = 0;
@@ -22,6 +23,8 @@ int have_vmlinux = 0;
 static int all_versions = 0;
 /* If we are modposting external module set to 1 */
 static int external_module = 0;
+/* How a symbol is exported */
+enum export {export_plain, export_gpl, export_gpl_future, export_unknown};
 
 void fatal(const char *fmt, ...)
 {
@@ -97,6 +100,7 @@ static struct module *new_module(char *modname)
 
        /* add to list */
        mod->name = p;
+       mod->gpl_compatible = -1;
        mod->next = modules;
        modules = mod;
 
@@ -118,6 +122,7 @@ struct symbol {
        unsigned int kernel:1;     /* 1 if symbol is from kernel
                                    *  (only for external modules) **/
        unsigned int preloaded:1;  /* 1 if symbol from Module.symvers */
+       enum export  export;       /* Type of export */
        char name[0];
 };
 
@@ -153,7 +158,8 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak,
 }
 
 /* For the hash of exported symbols */
-static struct symbol *new_symbol(const char *name, struct module *module)
+static struct symbol *new_symbol(const char *name, struct module *module,
+                                enum export export)
 {
        unsigned int hash;