[U-Boot] [RFC PATCH 4/7] Add Kconfig scripts and related material
Simon Glass
sjg at chromium.org
Mon May 13 04:25:37 CEST 2013
This is taken from the Linux kernel 3.8-rc7.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
Makefile.kbuild | 1496 +++++++++++++++++
include/linux/kconfig.h | 46 +
scripts/Kbuild.include | 278 +++
scripts/Makefile | 42 +
scripts/Makefile.asm-generic | 24 +
scripts/Makefile.autoconf | 68 +
scripts/Makefile.build | 478 ++++++
scripts/Makefile.clean | 104 ++
scripts/Makefile.host | 170 ++
scripts/Makefile.lib | 378 +++++
scripts/Makefile.modpost | 148 ++
scripts/basic/.gitignore | 1 +
scripts/basic/Makefile | 15 +
scripts/basic/fixdep.c | 433 +++++
scripts/gcc-goto.sh | 21 +
scripts/kconfig/.gitignore | 22 +
scripts/kconfig/Makefile | 325 ++++
scripts/kconfig/POTFILES.in | 12 +
scripts/kconfig/check.sh | 14 +
scripts/kconfig/conf.c | 701 ++++++++
scripts/kconfig/confdata.c | 1164 +++++++++++++
scripts/kconfig/expr.c | 1168 +++++++++++++
scripts/kconfig/expr.h | 235 +++
scripts/kconfig/gconf.c | 1542 +++++++++++++++++
scripts/kconfig/gconf.glade | 661 ++++++++
scripts/kconfig/images.c | 326 ++++
scripts/kconfig/kxgettext.c | 235 +++
scripts/kconfig/list.h | 91 +
scripts/kconfig/lkc.h | 198 +++
scripts/kconfig/lkc_proto.h | 56 +
scripts/kconfig/lxdialog/.gitignore | 4 +
scripts/kconfig/lxdialog/BIG.FAT.WARNING | 4 +
scripts/kconfig/lxdialog/check-lxdialog.sh | 85 +
scripts/kconfig/lxdialog/checklist.c | 332 ++++
scripts/kconfig/lxdialog/dialog.h | 236 +++
scripts/kconfig/lxdialog/inputbox.c | 301 ++++
scripts/kconfig/lxdialog/menubox.c | 436 +++++
scripts/kconfig/lxdialog/textbox.c | 408 +++++
scripts/kconfig/lxdialog/util.c | 664 ++++++++
scripts/kconfig/lxdialog/yesno.c | 114 ++
scripts/kconfig/mconf.c | 963 +++++++++++
scripts/kconfig/menu.c | 644 +++++++
scripts/kconfig/merge_config.sh | 142 ++
scripts/kconfig/nconf.c | 1558 +++++++++++++++++
scripts/kconfig/nconf.gui.c | 654 ++++++++
scripts/kconfig/nconf.h | 96 ++
scripts/kconfig/qconf.cc | 1790 ++++++++++++++++++++
scripts/kconfig/qconf.h | 337 ++++
scripts/kconfig/streamline_config.pl | 634 +++++++
scripts/kconfig/symbol.c | 1310 +++++++++++++++
scripts/kconfig/util.c | 159 ++
scripts/kconfig/zconf.gperf | 47 +
scripts/kconfig/zconf.hash.c_shipped | 286 ++++
scripts/kconfig/zconf.l | 364 ++++
scripts/kconfig/zconf.lex.c_shipped | 2420 +++++++++++++++++++++++++++
scripts/kconfig/zconf.tab.c_shipped | 2504 ++++++++++++++++++++++++++++
scripts/kconfig/zconf.y | 740 ++++++++
scripts/link-vmlinux.sh | 226 +++
scripts/mkcompile_h | 100 ++
scripts/mksysmap | 45 +
scripts/mod/.gitignore | 5 +
scripts/mod/Makefile | 51 +
scripts/mod/devicetable-offsets.c | 178 ++
scripts/mod/empty.c | 1 +
scripts/mod/file2alias.c | 1236 ++++++++++++++
scripts/mod/mk_elfconfig.c | 57 +
scripts/mod/modpost.c | 2222 ++++++++++++++++++++++++
scripts/mod/modpost.h | 187 +++
scripts/mod/sumversion.c | 519 ++++++
scripts/setlocalversion | 176 ++
70 files changed, 32687 insertions(+)
create mode 100644 Makefile.kbuild
create mode 100644 include/linux/kconfig.h
create mode 100644 scripts/Kbuild.include
create mode 100644 scripts/Makefile
create mode 100644 scripts/Makefile.asm-generic
create mode 100644 scripts/Makefile.autoconf
create mode 100644 scripts/Makefile.build
create mode 100644 scripts/Makefile.clean
create mode 100644 scripts/Makefile.host
create mode 100644 scripts/Makefile.lib
create mode 100644 scripts/Makefile.modpost
create mode 100644 scripts/basic/.gitignore
create mode 100644 scripts/basic/Makefile
create mode 100644 scripts/basic/fixdep.c
create mode 100644 scripts/gcc-goto.sh
create mode 100644 scripts/kconfig/.gitignore
create mode 100644 scripts/kconfig/Makefile
create mode 100644 scripts/kconfig/POTFILES.in
create mode 100755 scripts/kconfig/check.sh
create mode 100644 scripts/kconfig/conf.c
create mode 100644 scripts/kconfig/confdata.c
create mode 100644 scripts/kconfig/expr.c
create mode 100644 scripts/kconfig/expr.h
create mode 100644 scripts/kconfig/gconf.c
create mode 100644 scripts/kconfig/gconf.glade
create mode 100644 scripts/kconfig/images.c
create mode 100644 scripts/kconfig/kxgettext.c
create mode 100644 scripts/kconfig/list.h
create mode 100644 scripts/kconfig/lkc.h
create mode 100644 scripts/kconfig/lkc_proto.h
create mode 100644 scripts/kconfig/lxdialog/.gitignore
create mode 100644 scripts/kconfig/lxdialog/BIG.FAT.WARNING
create mode 100644 scripts/kconfig/lxdialog/check-lxdialog.sh
create mode 100644 scripts/kconfig/lxdialog/checklist.c
create mode 100644 scripts/kconfig/lxdialog/dialog.h
create mode 100644 scripts/kconfig/lxdialog/inputbox.c
create mode 100644 scripts/kconfig/lxdialog/menubox.c
create mode 100644 scripts/kconfig/lxdialog/textbox.c
create mode 100644 scripts/kconfig/lxdialog/util.c
create mode 100644 scripts/kconfig/lxdialog/yesno.c
create mode 100644 scripts/kconfig/mconf.c
create mode 100644 scripts/kconfig/menu.c
create mode 100755 scripts/kconfig/merge_config.sh
create mode 100644 scripts/kconfig/nconf.c
create mode 100644 scripts/kconfig/nconf.gui.c
create mode 100644 scripts/kconfig/nconf.h
create mode 100644 scripts/kconfig/qconf.cc
create mode 100644 scripts/kconfig/qconf.h
create mode 100644 scripts/kconfig/streamline_config.pl
create mode 100644 scripts/kconfig/symbol.c
create mode 100644 scripts/kconfig/util.c
create mode 100644 scripts/kconfig/zconf.gperf
create mode 100644 scripts/kconfig/zconf.hash.c_shipped
create mode 100644 scripts/kconfig/zconf.l
create mode 100644 scripts/kconfig/zconf.lex.c_shipped
create mode 100644 scripts/kconfig/zconf.tab.c_shipped
create mode 100644 scripts/kconfig/zconf.y
create mode 100644 scripts/link-vmlinux.sh
create mode 100755 scripts/mkcompile_h
create mode 100644 scripts/mksysmap
create mode 100644 scripts/mod/.gitignore
create mode 100644 scripts/mod/Makefile
create mode 100644 scripts/mod/devicetable-offsets.c
create mode 100644 scripts/mod/empty.c
create mode 100644 scripts/mod/file2alias.c
create mode 100644 scripts/mod/mk_elfconfig.c
create mode 100644 scripts/mod/modpost.c
create mode 100644 scripts/mod/modpost.h
create mode 100644 scripts/mod/sumversion.c
create mode 100755 scripts/setlocalversion
diff --git a/Makefile.kbuild b/Makefile.kbuild
new file mode 100644
index 0000000..2547cca
--- /dev/null
+++ b/Makefile.kbuild
@@ -0,0 +1,1496 @@
+VERSION = 2013
+PATCHLEVEL = 04
+SUBLEVEL =
+EXTRAVERSION =
+NAME = Unicycling Gorilla
+
+# *DOCUMENTATION*
+# To see a list of typical targets execute "make help"
+# More info can be located in ./README
+# Comments in this file are targeted only to the developer, do not
+# expect to learn how to build the kernel reading this file.
+
+# Do not:
+# o use make's built-in rules and variables
+# (this increases performance and avoids hard-to-debug behaviour);
+# o print "Entering directory ...";
+MAKEFLAGS += -rR --no-print-directory
+
+# Avoid funny character set dependencies
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+# We are using a recursive build, so we need to do a little thinking
+# to get the ordering right.
+#
+# Most importantly: sub-Makefiles should only ever modify files in
+# their own directory. If in some directory we have a dependency on
+# a file in another dir (which doesn't happen often, but it's often
+# unavoidable when linking the built-in.o targets which finally
+# turn into vmlinux), we will call a sub make in that other dir, and
+# after that we are sure that everything which is in that other dir
+# is now up to date.
+#
+# The only cases where we need to modify files which have global
+# effects are thus separated out and done before the recursive
+# descending is started. They are now explicitly listed as the
+# prepare rule.
+
+# To put more focus on warnings, be less verbose as default
+# Use 'make V=1' to see the full commands
+
+ifeq ("$(origin V)", "command line")
+ KBUILD_VERBOSE = $(V)
+endif
+ifndef KBUILD_VERBOSE
+ KBUILD_VERBOSE = 0
+endif
+
+# Call a source code checker (by default, "sparse") as part of the
+# C compilation.
+#
+# Use 'make C=1' to enable checking of only re-compiled files.
+# Use 'make C=2' to enable checking of *all* source files, regardless
+# of whether they are re-compiled or not.
+#
+# See the file "Documentation/sparse.txt" for more details, including
+# where to get the "sparse" utility.
+
+ifeq ("$(origin C)", "command line")
+ KBUILD_CHECKSRC = $(C)
+endif
+ifndef KBUILD_CHECKSRC
+ KBUILD_CHECKSRC = 0
+endif
+
+# Use make M=dir to specify directory of external module to build
+# Old syntax make ... SUBDIRS=$PWD is still supported
+# Setting the environment variable KBUILD_EXTMOD take precedence
+ifdef SUBDIRS
+ KBUILD_EXTMOD ?= $(SUBDIRS)
+endif
+
+ifeq ("$(origin M)", "command line")
+ KBUILD_EXTMOD := $(M)
+endif
+
+# kbuild supports saving output files in a separate directory.
+# To locate output files in a separate directory two syntaxes are supported.
+# 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.
+# export KBUILD_OUTPUT=dir/to/store/output/files/
+# make
+#
+# The O= assignment takes precedence over the KBUILD_OUTPUT environment
+# variable.
+
+
+# KBUILD_SRC is set on invocation of make in OBJ directory
+# KBUILD_SRC is not intended to be used by the regular user (for now)
+ifeq ($(KBUILD_SRC),)
+
+# OK, Make called in directory where kernel src resides
+# Do we want to locate output files in a separate directory?
+ifeq ("$(origin O)", "command line")
+ KBUILD_OUTPUT := $(O)
+endif
+
+ifeq ("$(origin W)", "command line")
+ export KBUILD_ENABLE_EXTRA_GCC_CHECKS := $(W)
+endif
+
+# That's our default target when none is given on the command line
+PHONY := _all
+_all:
+
+# Cancel implicit rules on top Makefile
+$(CURDIR)/Makefile Makefile: ;
+
+MKCONFIG = $(srctree)/mkconfig
+
+ifneq ($(KBUILD_OUTPUT),)
+# Invoke a second make in the output directory, passing relevant variables
+# check that the output directory actually exists
+saved-output := $(KBUILD_OUTPUT)
+KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
+$(if $(KBUILD_OUTPUT),, \
+ $(error output directory "$(saved-output)" does not exist))
+
+PHONY += $(MAKECMDGOALS) sub-make
+
+$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
+ @:
+
+sub-make: FORCE
+ $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
+ KBUILD_SRC=$(CURDIR) \
+ KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile \
+ $(filter-out _all sub-make,$(MAKECMDGOALS))
+
+# Leave processing to above invocation of make
+skip-makefile := 1
+endif # ifneq ($(KBUILD_OUTPUT),)
+endif # ifeq ($(KBUILD_SRC),)
+
+# We process the rest of the Makefile if this is the final invocation of make
+ifeq ($(skip-makefile),)
+
+# If building an external module we do not care about the all: rule
+# but instead _all depend on modules
+PHONY += all
+ifeq ($(KBUILD_EXTMOD),)
+_all: all
+else
+_all: modules
+endif
+
+srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
+objtree := $(CURDIR)
+src := $(srctree)
+obj := $(objtree)
+
+VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
+
+export srctree objtree VPATH
+
+# We use Makefile.kbuild instead of Makefile for now. To be removed.
+MAKEFILE_NAME := $(srctree)/Makefile.kbuild
+
+# U-Boot's directory nanes used by old Makefiles. To be removed.
+TOPDIR := $(srctree)
+SRCTREE := $(srctree)
+OBJTREE = $(objtree)
+export SRCTREE TOPDIR OBJTREE
+
+# Export U-Boot variables
+export BOARD CPU SOC VENDOR
+
+# SUBARCH tells the usermode build what the underlying arch is. That is set
+# first, and if a usermode build is happening, the "ARCH=um" on the command
+# line overrides the setting of ARCH below. If a native build is happening,
+# then ARCH is assigned, getting whatever value it gets normally, and
+# SUBARCH is subsequently ignored.
+
+SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
+ -e s/sun4u/sparc64/ \
+ -e s/arm.*/arm/ -e s/sa110/arm/ \
+ -e s/s390x/s390/ -e s/parisc64/parisc/ \
+ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
+ -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
+
+# Cross compiling and selecting different set of gcc/bin-utils
+# ---------------------------------------------------------------------------
+#
+# When performing cross compilation for other architectures ARCH shall be set
+# to the target architecture. (See arch/* for the possibilities).
+# ARCH can be set during invocation of make:
+# make ARCH=ia64
+# Another way is to have ARCH set in the environment.
+# The default ARCH is the host where make is executed.
+
+# CROSS_COMPILE specify the prefix used for all executables used
+# during compilation. Only gcc and related bin-utils executables
+# are prefixed with $(CROSS_COMPILE).
+# CROSS_COMPILE can be set on the command line
+# make CROSS_COMPILE=ia64-linux-
+# Alternatively CROSS_COMPILE can be set in the environment.
+# A third alternative is to store a setting in .config so that plain
+# "make" in the configured kernel build directory always uses that.
+# Default value for CROSS_COMPILE is not to prefix executables
+# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
+#ARCH ?= $(SUBARCH)
+CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
+
+# Architecture as present in compile.h
+UTS_MACHINE := $(ARCH)
+SRCARCH := $(ARCH)
+
+# Additional ARCH settings for x86
+ifeq ($(ARCH),i386)
+ SRCARCH := x86
+endif
+ifeq ($(ARCH),x86_64)
+ SRCARCH := x86
+endif
+
+# Additional ARCH settings for sparc
+ifeq ($(ARCH),sparc32)
+ SRCARCH := sparc
+endif
+ifeq ($(ARCH),sparc64)
+ SRCARCH := sparc
+endif
+
+# Additional ARCH settings for sh
+ifeq ($(ARCH),sh64)
+ SRCARCH := sh
+endif
+
+# Additional ARCH settings for tile
+ifeq ($(ARCH),tilepro)
+ SRCARCH := tile
+endif
+ifeq ($(ARCH),tilegx)
+ SRCARCH := tile
+endif
+
+# Where to locate arch specific headers
+hdr-arch := $(SRCARCH)
+
+KCONFIG_CONFIG ?= .config
+export KCONFIG_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 -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
+HOSTCXXFLAGS = -O2
+
+# Decide whether to build built-in, modular, or both.
+# Normally, just do built-in.
+
+KBUILD_MODULES :=
+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 up to date before we record them.
+
+ifeq ($(MAKECMDGOALS),modules)
+ KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
+endif
+
+# If we have "make <whatever> modules", compile modules
+# in addition to whatever we do anyway.
+# Just "make" or "make all" shall build modules as well
+
+ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
+ KBUILD_MODULES := 1
+endif
+
+ifeq ($(MAKECMDGOALS),)
+ KBUILD_MODULES := 1
+endif
+
+# But for now at least, U-Boot does not have modules
+KBUILD_MODULES :=
+
+export KBUILD_MODULES KBUILD_BUILTIN
+export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
+
+# Beautify output
+# ---------------------------------------------------------------------------
+#
+# Normally, we echo the whole command before executing it. By making
+# that echo $($(quiet)$(cmd)), we now have the possibility to set
+# $(quiet) to choose other forms of output instead, e.g.
+#
+# quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
+# cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
+#
+# 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 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
+# for commands that shall be hidden in non-verbose mode.
+#
+# $(Q)ln $@ :<
+#
+# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
+# If KBUILD_VERBOSE equals 1 then the above command is displayed.
+
+ifeq ($(KBUILD_VERBOSE),1)
+ quiet =
+ Q =
+else
+ quiet=quiet_
+ Q = @
+endif
+
+# If the user is running make -s (silent mode), suppress echoing of
+# commands
+
+ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
+ quiet=silent_
+endif
+
+export quiet Q KBUILD_VERBOSE
+
+
+# Look for make include files relative to root of kernel src
+MAKEFLAGS += --include-dir=$(srctree)
+
+# We need some generic definitions (do not try to remake the file).
+$(srctree)/scripts/Kbuild.include: ;
+include $(srctree)/scripts/Kbuild.include
+
+# Make variables (CC, etc...)
+
+AS = $(CROSS_COMPILE)as
+LD = $(CROSS_COMPILE)ld
+CC = $(CROSS_COMPILE)gcc
+CPP = $(CC) -E
+AR = $(CROSS_COMPILE)ar
+NM = $(CROSS_COMPILE)nm
+STRIP = $(CROSS_COMPILE)strip
+OBJCOPY = $(CROSS_COMPILE)objcopy
+OBJDUMP = $(CROSS_COMPILE)objdump
+AWK = awk
+GENKSYMS = scripts/genksyms/genksyms
+INSTALLKERNEL := installkernel
+DEPMOD = /sbin/depmod
+PERL = perl
+CHECK = sparse
+
+CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
+ -Wbitwise -Wno-return-void $(CF)
+CFLAGS_MODULE =
+AFLAGS_MODULE =
+LDFLAGS_MODULE =
+CFLAGS_KERNEL =
+AFLAGS_KERNEL =
+CFLAGS_GCOV = -fprofile-arcs -ftest-coverage
+
+
+# Use USERINCLUDE when you must reference the UAPI directories only.
+USERINCLUDE := \
+ -I$(srctree)/arch/$(hdr-arch)/include/uapi \
+ -Iarch/$(hdr-arch)/include/generated/uapi \
+ -I$(srctree)/include/uapi \
+ -Iinclude/generated/uapi \
+ -include $(srctree)/include/linux/kconfig.h
+
+# Use LINUXINCLUDE when you must reference the include/ directory.
+# Needed to be compatible with the O= option
+LINUXINCLUDE := \
+ -I$(srctree)/arch/$(hdr-arch)/include \
+ -Iarch/$(hdr-arch)/include/generated \
+ $(if $(KBUILD_SRC), -I$(srctree)/include) \
+ -Iinclude \
+ $(USERINCLUDE)
+
+KBUILD_CPPFLAGS := -D__KERNEL__
+
+gccincdir := $(shell $(CC) -print-file-name=include)
+
+KBUILD_CFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs \
+ -fno-strict-aliasing -fno-common \
+ -Werror-implicit-function-declaration \
+ -Wno-format-security \
+ -fno-delete-null-pointer-checks \
+ -fno-builtin -ffreestanding
+KBUILD_AFLAGS_KERNEL :=
+KBUILD_CFLAGS_KERNEL :=
+KBUILD_AFLAGS := -D__ASSEMBLY__
+KBUILD_AFLAGS_MODULE := -DMODULE
+KBUILD_CFLAGS_MODULE := -DMODULE
+KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
+
+# Read KERNELRELEASE from include/config/kernel.release (if it exists)
+KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
+KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
+
+export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
+export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
+export CPP AR NM STRIP OBJCOPY OBJDUMP
+export MAKE AWK GENKSYMS INSTALLKERNEL PERL UTS_MACHINE
+export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
+
+export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
+export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV
+export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
+export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
+export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
+export KBUILD_ARFLAGS
+
+# When compiling out-of-tree modules, put MODVERDIR in the module
+# tree rather than in the kernel tree. The kernel tree might
+# even be read-only.
+export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
+
+# Files to ignore in find ... statements
+
+RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \
+ -o -name .pc -o -name .hg -o -name .git \) -prune -o
+export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \
+ --exclude CVS --exclude .pc --exclude .hg --exclude .git
+
+# ===========================================================================
+# Rules shared between *config targets and build targets
+
+# Basic helpers built in scripts/
+PHONY += scripts_basic
+scripts_basic:
+ $(Q)$(MAKE) $(build)=scripts/basic
+ $(Q)rm -f .tmp_quiet_recordmcount
+
+# To avoid any implicit rule to kick in, define an empty command.
+scripts/basic/%: scripts_basic ;
+
+PHONY += outputmakefile
+# outputmakefile generates a Makefile in the output directory, if using a
+# separate output directory. This allows convenient use of make in the
+# output directory.
+outputmakefile:
+ifneq ($(KBUILD_SRC),)
+ $(Q)ln -fsn $(srctree) source
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
+ $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
+endif
+
+# Support for using generic headers in asm-generic
+PHONY += asm-generic
+asm-generic:
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
+ src=asm obj=arch/$(SRCARCH)/include/generated/asm
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
+ src=uapi/asm obj=arch/$(SRCARCH)/include/generated/uapi/asm
+
+# To make sure we do not include .config for any of the *config targets
+# 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'.
+# Detect when mixed targets is specified, and make a second invocation
+# of make so .config is not included in this case either (for *config).
+
+version_h := include/generated/uapi/linux/version.h
+
+no-dot-config-targets := clean mrproper distclean \
+ cscope gtags TAGS tags help %docs check% coccicheck \
+ $(version_h) headers_% archheaders archscripts \
+ kernelversion %src-pkg
+
+config-targets := 0
+mixed-targets := 0
+dot-config := 1
+
+ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
+ ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
+ dot-config := 0
+ endif
+endif
+
+ifeq ($(KBUILD_EXTMOD),)
+ ifneq ($(filter config %config,$(MAKECMDGOALS)),)
+ config-targets := 1
+ ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
+ mixed-targets := 1
+ endif
+ endif
+endif
+
+ifeq ($(mixed-targets),1)
+# ===========================================================================
+# We're called with mixed targets (*config and build targets).
+# Handle them one by one.
+
+%:: FORCE
+ $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@
+
+else
+ifeq ($(config-targets),1)
+# ===========================================================================
+# *config targets only - make sure prerequisites are updated, and descend
+# in scripts/kconfig to make the *config target
+
+# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
+# KBUILD_DEFCONFIG may point out an alternative default configuration
+# used for 'make defconfig'arch/$(SRCARCH)/config.mk
+# include $(srctree)/arch/$(SRCARCH)/Makefile
+export KBUILD_DEFCONFIG KBUILD_KCONFIG
+
+config: scripts_basic outputmakefile FORCE
+ $(Q)mkdir -p include/linux include/config
+ $(Q)$(MAKE) $(build)=scripts/kconfig $@
+
+%_config: scripts_basic outputmakefile FORCE
+ $(Q)$(MKCONFIG) -A $(@:_config=)
+ $(Q)mkdir -p include/linux include/config
+ $(Q)$(MAKE) $(build)=scripts/kconfig $@
+ $(Q)rm -f $(objtree)/include/config/autoconf.mk.dep \
+ $(objtree)/include/config/autoconf.mk
+ $(Q)$(MAKE) -f scripts/Makefile.autoconf
+
+%config: scripts_basic outputmakefile FORCE
+ $(Q)mkdir -p include/linux include/config
+ $(Q)$(MAKE) $(build)=scripts/kconfig $@
+
+else
+# ===========================================================================
+# Build targets only - this includes vmlinux, arch specific targets, clean
+# targets and others. In general all targets except *config targets.
+
+SRCARCH = $(ARCH)
+include $(objtree)/include/config.mk
+include $(srctree)/arch/$(SRCARCH)/config.mk
+#include $(objtree)/include/config/autoconf.mk
+
+KBUILD_CFLAGS += $(PLATFORM_CPPFLAGS)
+
+ifeq ($(KBUILD_EXTMOD),)
+# Additional helpers built in scripts/
+# Carefully list dependencies so we do not try to build scripts twice
+# in parallel
+PHONY += scripts
+scripts: scripts_basic include/config/auto.conf include/config/tristate.conf
+ $(Q)$(MAKE) $(build)=$(@)
+
+HAVE_VENDOR_COMMON_LIB = $(if $(wildcard board/$(VENDOR)/common/Makefile),y,n)
+
+# Objects we will link into vmlinux / subdirs we need to visit
+arch-y := arch/$(SRCARCH)/
+board-y := board/$(VENDOR)/$(BOARD)/
+board-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
+core-y := common/
+disk-y := disk/
+drivers-y := drivers/
+fs-y := fs/
+init-y := init/
+libs-y := lib/
+net-y := net/
+spl-y := spl/
+endif # KBUILD_EXTMOD
+
+ifeq ($(dot-config),1)
+# Read in config
+-include include/config/auto.conf
+-include $(objtree)/include/config/autoconf.mk
+# -include $(srctree)/arch/$(SRCARCH)/config.mk
+
+ifeq ($(KBUILD_EXTMOD),)
+# Read in dependencies to all Kconfig* files, make sure to run
+# oldconfig if changes are detected.
+-include include/config/auto.conf.cmd
+
+# To avoid any implicit rule to kick in, define an empty command
+$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
+
+# If .config is newer than include/config/auto.conf, someone tinkered
+# with it and forgot to run make oldconfig.
+# 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/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
+ $(warning check $@ missing $^)
+ $(Q)$(MAKE) -f $(MAKEFILE_NAME) silentoldconfig
+else
+# external modules needs include/generated/autoconf.h and include/config/auto.conf
+# but do not care if they are up-to-date. Use auto.conf to trigger the test
+PHONY += include/config/auto.conf
+
+include/config/auto.conf:
+ $(Q)test -e include/generated/autoconf.h -a -e $@ || ( \
+ echo >&2; \
+ echo >&2 " ERROR: Kernel configuration is invalid."; \
+ echo >&2 " include/generated/autoconf.h or $@ are missing.";\
+ echo >&2 " Run 'make oldconfig && make prepare' on kernel src to fix it."; \
+ echo >&2 ; \
+ /bin/false)
+
+endif # KBUILD_EXTMOD
+
+else
+# Dummy target needed, because used as prerequisite
+include/config/auto.conf: ;
+endif # $(dot-config)
+
+# 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 to vmlinux, but the arch makefile usually adds further targets
+all: vmlinux
+
+ifdef CONFIG_SPL
+all: spl/u-boot
+endif
+
+ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
+KBUILD_CFLAGS += -Os
+else
+KBUILD_CFLAGS += -O2
+endif
+
+#include $(srctree)/arch/$(SRCARCH)/Makefile
+
+ifdef CONFIG_READABLE_ASM
+# Disable optimizations that make assembler listings hard to read.
+# reorder blocks reorders the control in the function
+# ipa clone creates specialized cloned functions
+# partial inlining inlines only parts of functions
+KBUILD_CFLAGS += $(call cc-option,-fno-reorder-blocks,) \
+ $(call cc-option,-fno-ipa-cp-clone,) \
+ $(call cc-option,-fno-partial-inlining)
+endif
+
+ifneq ($(CONFIG_FRAME_WARN),0)
+KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
+endif
+
+# Force gcc to behave correct even for buggy distributions
+ifndef CONFIG_CC_STACKPROTECTOR
+KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
+endif
+
+# This warning generated too much noise in a regular build.
+# Use make W=1 to enable this warning (see scripts/Makefile.build)
+KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
+
+ifdef CONFIG_FRAME_POINTER
+KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
+else
+# Some targets (ARM with Thumb2, for example), can't be built with frame
+# pointers. For those, we don't have FUNCTION_TRACER automatically
+# select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is
+# incompatible with -fomit-frame-pointer with current GCC, so we don't use
+# -fomit-frame-pointer with FUNCTION_TRACER.
+ifndef CONFIG_FUNCTION_TRACER
+KBUILD_CFLAGS += -fomit-frame-pointer
+endif
+endif
+
+ifdef CONFIG_DEBUG_INFO
+KBUILD_CFLAGS += -g
+KBUILD_AFLAGS += -gdwarf-2
+endif
+
+ifdef CONFIG_DEBUG_INFO_REDUCED
+KBUILD_CFLAGS += $(call cc-option, -femit-struct-debug-baseonly)
+endif
+
+ifdef CONFIG_FUNCTION_TRACER
+ifdef CONFIG_HAVE_FENTRY
+CC_USING_FENTRY := $(call cc-option, -mfentry -DCC_USING_FENTRY)
+endif
+KBUILD_CFLAGS += -pg $(CC_USING_FENTRY)
+KBUILD_AFLAGS += $(CC_USING_FENTRY)
+ifdef CONFIG_DYNAMIC_FTRACE
+ ifdef CONFIG_HAVE_C_RECORDMCOUNT
+ BUILD_C_RECORDMCOUNT := y
+ export BUILD_C_RECORDMCOUNT
+ endif
+endif
+endif
+
+# We trigger additional mismatches with less inlining
+ifdef CONFIG_DEBUG_SECTION_MISMATCH
+KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
+endif
+
+# arch Makefile may override CC so keep this after arch Makefile is included
+NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+CHECKFLAGS += $(NOSTDINC_FLAGS)
+
+# warn about C99 declaration after statement
+KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
+
+# disable pointer signed / unsigned warnings in gcc 4.0
+KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign)
+
+# disable invalid "can't wrap" optimizations for signed / pointers
+KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
+
+# conserve stack if available
+KBUILD_CFLAGS += $(call cc-option,-fconserve-stack)
+
+# use the deterministic mode of AR if available
+KBUILD_ARFLAGS := $(call ar-option,D)
+
+# check for 'asm goto'
+ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
+ KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
+endif
+
+# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
+KBUILD_CPPFLAGS += $(KCPPFLAGS)
+KBUILD_AFLAGS += $(KAFLAGS)
+KBUILD_CFLAGS += $(KCFLAGS)
+
+# Use --build-id when available.
+LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
+ $(call cc-ldoption, -Wl$(comma)--build-id,))
+KBUILD_LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID)
+LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID)
+
+ifeq ($(CONFIG_STRIP_ASM_SYMS),y)
+LDFLAGS_vmlinux += $(call ld-option, -X,)
+endif
+
+FINAL_LIBS := $(PLATFORM_LIBS)
+export FINAL_LIBS
+
+# Default kernel image to build when no specific target is given.
+# 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
+export KBUILD_IMAGE ?= vmlinux
+
+#
+# INSTALL_PATH specifies where to place the updated kernel and system map
+# images. Default is /boot, but you can set it to other values
+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 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 value will be 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
+
+
+ifdef CONFIG_MODULE_SIG_ALL
+MODSECKEY = ./signing_key.priv
+MODPUBKEY = ./signing_key.x509
+export MODPUBKEY
+mod_sign_cmd = perl $(srctree)/scripts/sign-file $(CONFIG_MODULE_SIG_HASH) $(MODSECKEY) $(MODPUBKEY)
+else
+mod_sign_cmd = true
+endif
+export mod_sign_cmd
+
+
+ifeq ($(KBUILD_EXTMOD),)
+#core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
+
+vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
+ $(arch-y) $(arch-m) $(board-y) $(board-m) \
+ $(disk-y) $(disk-m) $(fs-y) $(fs-m) \
+ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
+ $(net-y) $(net-m) $(libs-y) $(libs-m)))
+
+vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
+ $(init-n) $(init-) \
+ $(arch-y) $(arch-m) $(board-y) $(board-m) \
+ $(disk-y) $(disk-m) $(fs-y) $(fs-m) \
+ $(core-n) $(core-) $(drivers-n) $(drivers-) \
+ $(net-n) $(net-) $(libs-n) $(libs-))))
+
+arch-y := $(patsubst %/, %/built-in.o, $(arch-y))
+board-y := $(patsubst %/, %/built-in.o, $(board-y))
+core-y := $(patsubst %/, %/built-in.o, $(core-y))
+disk-y := $(patsubst %/, %/built-in.o, $(disk-y))
+drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
+fs-y := $(patsubst %/, %/built-in.o, $(fs-y))
+init-y := $(patsubst %/, %/built-in.o, $(init-y))
+net-y := $(patsubst %/, %/built-in.o, $(net-y))
+spl-y := $(patsubst %/, %/built-in.o, $(spl-y))
+# libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
+# libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
+# libs-y := $(libs-y1) $(libs-y2)
+
+libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
+
+# Externally visible symbols (used by link-vmlinux.sh)
+export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
+export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y) \
+ $(arch-y) $(board-y) $(disk-y) $(fs-y)
+export KBUILD_LDS := arch/$(SRCARCH)/cpu/u-boot.lds
+export LDFLAGS_vmlinux
+
+vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
+
+# Final link of vmlinux
+ cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux)
+quiet_cmd_link-vmlinux = LINK $@
+
+# Include targets which we want to
+# execute if the rest of the kernel build went well.
+vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE
+ifdef CONFIG_HEADERS_CHECK
+ $(Q)$(MAKE) -f $(MAKEFILE_NAME) headers_check
+endif
+ifdef CONFIG_SAMPLES
+ $(Q)$(MAKE) $(build)=samples
+endif
+ifdef CONFIG_BUILD_DOCSRC
+ $(Q)$(MAKE) $(build)=Documentation
+endif
+ +$(call if_changed,link-vmlinux)
+
+spl/u-boot:
+ $(Q)echo "SPL not yet supported"
+
+# The actual objects are generated when descending,
+# make sure no implicit rule kicks in
+$(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
+
+# Handle descending into subdirectories listed in $(vmlinux-dirs)
+# Preset locale variables to speed up the build process. Limit locale
+# tweaks to this spot to avoid wrong language settings when running
+# make menuconfig etc.
+# Error messages still appears in the original language
+
+PHONY += $(vmlinux-dirs)
+$(vmlinux-dirs): prepare scripts
+ $(Q)$(MAKE) $(build)=$@
+
+# Store (new) KERNELRELASE string in include/config/kernel.release
+include/config/kernel.release: include/config/auto.conf FORCE
+ $(Q)rm -f $@
+ $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@
+
+
+# Things we need to do before we recursively start building the kernel
+# or the modules are listed in "prepare".
+# A multi level approach is used. prepareN is processed before prepareN-1.
+# archprepare is used in arch Makefiles and when processed asm symlink,
+# version.h and scripts_basic is processed / created.
+
+# Listed in dependency order
+PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
+
+# prepare3 is used to check if we are building in a separate output directory,
+# and if so do:
+# 1) Check that make has not been executed in the kernel src $(srctree)
+prepare3: include/config/kernel.release
+ifneq ($(KBUILD_SRC),)
+ @$(kecho) ' Using $(srctree) as source for kernel'
+ $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
+ echo >&2 " $(srctree) is not clean, please run 'make mrproper'"; \
+ echo >&2 " in the '$(srctree)' directory.";\
+ /bin/false; \
+ fi;
+endif
+
+# prepare2 creates a makefile if using a separate output directory
+prepare2: prepare3 outputmakefile asm-generic
+
+prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
+ include/config/auto.conf
+ $(cmd_crmodverdir)
+
+archprepare: archheaders archscripts prepare1 scripts_basic
+
+prepare0: archprepare FORCE
+ $(Q)$(MAKE) $(build)=.
+
+# All the preparing..
+prepare: prepare0
+
+# Generate some files
+# ---------------------------------------------------------------------------
+
+# KERNELRELEASE can change from a few different places, meaning version.h
+# needs to be updated, so this check is forced on all builds
+
+uts_len := 64
+define filechk_utsrelease.h
+ if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
+ echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
+ exit 1; \
+ fi; \
+ (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
+endef
+
+define filechk_version.h
+ (echo \#define LINUX_VERSION_CODE $(shell \
+ expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \
+ echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
+endef
+
+$(version_h): $(MAKEFILE_NAME) FORCE
+ $(call filechk,version.h)
+
+include/generated/utsrelease.h: include/config/kernel.release FORCE
+ $(call filechk,utsrelease.h)
+
+PHONY += headerdep
+headerdep:
+ $(Q)find $(srctree)/include/ -name '*.h' | xargs --max-args 1 \
+ $(srctree)/scripts/headerdep.pl -I$(srctree)/include
+
+# ---------------------------------------------------------------------------
+
+PHONY += depend dep
+depend dep:
+ @echo '*** Warning: make $@ is unnecessary now.'
+
+# ---------------------------------------------------------------------------
+# Firmware install
+INSTALL_FW_PATH=$(INSTALL_MOD_PATH)/lib/firmware
+export INSTALL_FW_PATH
+
+PHONY += firmware_install
+firmware_install: FORCE
+ @mkdir -p $(objtree)/firmware
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install
+
+# ---------------------------------------------------------------------------
+# Kernel headers
+
+#Default location for installed headers
+export INSTALL_HDR_PATH = $(objtree)/usr
+
+hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
+
+# If we do an all arch process set dst to asm-$(hdr-arch)
+hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
+
+PHONY += archheaders
+archheaders:
+
+PHONY += archscripts
+archscripts:
+
+PHONY += __headers
+__headers: $(version_h) scripts_basic asm-generic archheaders archscripts FORCE
+ $(Q)$(MAKE) $(build)=scripts build_unifdef
+
+PHONY += headers_install_all
+headers_install_all:
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh install
+
+PHONY += headers_install
+headers_install: __headers
+ $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/uapi/asm/Kbuild),, \
+ $(error Headers not exportable for the $(SRCARCH) architecture))
+ $(Q)$(MAKE) $(hdr-inst)=include/uapi
+ $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst)
+
+PHONY += headers_check_all
+headers_check_all: headers_install_all
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh check
+
+PHONY += headers_check
+headers_check: headers_install
+ $(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1
+ $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) HDRCHECK=1
+
+# ---------------------------------------------------------------------------
+# Modules
+
+ifdef CONFIG_MODULES
+
+# By default, build modules as well
+
+all: modules
+
+# Build modules
+#
+# A module can be listed more than once in obj-m resulting in
+# duplicate lines in modules.order files. Those are removed
+# using awk while concatenating to the final file.
+
+PHONY += modules
+modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
+ $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
+ @$(kecho) ' Building modules, stage 2.';
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
+
+modules.builtin: $(vmlinux-dirs:%=%/modules.builtin)
+ $(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin
+
+%/modules.builtin: include/config/auto.conf
+ $(Q)$(MAKE) $(modbuiltin)=$*
+
+
+# Target to prepare building external modules
+PHONY += modules_prepare
+modules_prepare: prepare scripts
+
+# Target to install modules
+PHONY += modules_install
+modules_install: _modinst_ _modinst_post
+
+PHONY += _modinst_
+_modinst_:
+ @rm -rf $(MODLIB)/kernel
+ @rm -f $(MODLIB)/source
+ @mkdir -p $(MODLIB)/kernel
+ @ln -s $(srctree) $(MODLIB)/source
+ @if [ ! $(objtree) -ef $(MODLIB)/build ]; then \
+ rm -f $(MODLIB)/build ; \
+ ln -s $(objtree) $(MODLIB)/build ; \
+ fi
+ @cp -f $(objtree)/modules.order $(MODLIB)/
+ @cp -f $(objtree)/modules.builtin $(MODLIB)/
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
+
+# This depmod is only for convenience to give the initial
+# boot a modules.dep even before / is mounted read-write. However the
+# boot script depmod is the master version.
+PHONY += _modinst_post
+_modinst_post: _modinst_
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst
+ $(call cmd,depmod)
+
+ifeq ($(CONFIG_MODULE_SIG), y)
+PHONY += modules_sign
+modules_sign:
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modsign
+endif
+
+else # CONFIG_MODULES
+
+# Modules not configured
+# ---------------------------------------------------------------------------
+
+modules modules_install: FORCE
+ @echo >&2
+ @echo >&2 "The present kernel configuration has modules disabled."
+ @echo >&2 "Type 'make config' and enable loadable module support."
+ @echo >&2 "Then build a kernel with module support enabled."
+ @echo >&2
+ @exit 1
+
+endif # CONFIG_MODULES
+
+###
+# Cleaning is done on three levels.
+# make clean Delete most generated files
+# Leave enough to build external modules
+# make mrproper Delete the current configuration, and all generated files
+# make distclean Remove editor backup files, patch leftover files and the like
+
+# Directories & files removed with 'make clean'
+CLEAN_DIRS += $(MODVERDIR)
+
+# Directories & files removed with 'make mrproper'
+MRPROPER_DIRS += include/config usr/include include/generated \
+ arch/*/include/generated
+MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \
+ Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \
+ signing_key.priv signing_key.x509 x509.genkey \
+ extra_certificates signing_key.x509.keyid \
+ signing_key.x509.signer
+
+# clean - Delete most, but leave enough to build external modules
+#
+clean: rm-dirs := $(CLEAN_DIRS)
+clean: rm-files := $(CLEAN_FILES)
+clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs) doc)
+
+PHONY += $(clean-dirs) clean archclean vmlinuxclean
+$(clean-dirs):
+ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
+
+vmlinuxclean:
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean
+
+clean: archclean vmlinuxclean
+
+# mrproper - Delete all generated files, including .config
+#
+mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS))
+mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
+mrproper-dirs := $(addprefix _mrproper_,Documentation/DocBook scripts)
+
+PHONY += $(mrproper-dirs) mrproper archmrproper
+$(mrproper-dirs):
+ $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
+
+mrproper: clean archmrproper $(mrproper-dirs)
+ $(call cmd,rmdirs)
+ $(call cmd,rmfiles)
+
+# distclean
+#
+PHONY += distclean
+
+distclean: mrproper
+ @find $(srctree) $(RCS_FIND_IGNORE) \
+ \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
+ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
+ -o -name '.*.rej' \
+ -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
+ -type f -print | xargs rm -f
+
+
+# Packaging of the kernel to various formats
+# ---------------------------------------------------------------------------
+# rpm target kept for backward compatibility
+package-dir := $(srctree)/scripts/package
+
+%src-pkg: FORCE
+ $(Q)$(MAKE) $(build)=$(package-dir) $@
+%pkg: include/config/kernel.release FORCE
+ $(Q)$(MAKE) $(build)=$(package-dir) $@
+rpm: include/config/kernel.release FORCE
+ $(Q)$(MAKE) $(build)=$(package-dir) $@
+
+
+# Brief documentation of the typical targets used
+# ---------------------------------------------------------------------------
+
+boards := $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*_defconfig)
+boards := $(notdir $(boards))
+board-dirs := $(dir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*/*_defconfig))
+board-dirs := $(sort $(notdir $(board-dirs:/=)))
+
+help:
+ @echo 'Cleaning targets:'
+ @echo ' clean - Remove most generated files but keep the config and'
+ @echo ' enough build support to build external modules'
+ @echo ' mrproper - Remove all generated files + config + various backup files'
+ @echo ' distclean - mrproper + remove editor backup and patch files'
+ @echo ''
+ @echo 'Configuration targets:'
+ @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
+ @echo ''
+ @echo 'Other generic targets:'
+ @echo ' all - Build all targets marked with [*]'
+ @echo '* vmlinux - Build the bare kernel'
+ @echo '* modules - Build all modules'
+ @echo ' modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
+ @echo ' firmware_install- Install all firmware to INSTALL_FW_PATH'
+ @echo ' (default: $$(INSTALL_MOD_PATH)/lib/firmware)'
+ @echo ' dir/ - Build all files in dir and below'
+ @echo ' dir/file.[oisS] - Build specified target only'
+ @echo ' dir/file.lst - Build specified mixed source/assembly target only'
+ @echo ' (requires a recent binutils and recent build (System.map))'
+ @echo ' dir/file.ko - Build module including final link'
+ @echo ' modules_prepare - Set up for building external modules'
+ @echo ' tags/TAGS - Generate tags file for editors'
+ @echo ' cscope - Generate cscope index'
+ @echo ' gtags - Generate GNU GLOBAL index'
+ @echo ' kernelrelease - Output the release version string'
+ @echo ' kernelversion - Output the version stored in Makefile'
+ @echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
+ echo ' (default: $(INSTALL_HDR_PATH))'; \
+ echo ''
+ @echo 'Static analysers'
+ @echo ' checkstack - Generate a list of stack hogs'
+ @echo ' namespacecheck - Name space analysis on compiled kernel'
+ @echo ' versioncheck - Sanity check on version.h usage'
+ @echo ' includecheck - Check for duplicate included header files'
+ @echo ' export_report - List the usages of all exported symbols'
+ @echo ' headers_check - Sanity check on exported headers'
+ @echo ' headerdep - Detect inclusion cycles in headers'
+ @$(MAKE) -f $(srctree)/scripts/Makefile.help checker-help
+ @echo ''
+ @echo 'Kernel packaging:'
+ @$(MAKE) $(build)=$(package-dir) help
+ @echo ''
+ @echo 'Documentation targets:'
+ @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
+ @echo ''
+ @echo 'Architecture specific targets ($(SRCARCH)):'
+ @$(if $(archhelp),$(archhelp),\
+ echo ' No architecture specific help defined for $(SRCARCH)')
+ @echo ''
+ @$(if $(boards), \
+ $(foreach b, $(boards), \
+ printf " %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \
+ echo '')
+ @$(if $(board-dirs), \
+ $(foreach b, $(board-dirs), \
+ printf " %-16s - Show %s-specific targets\\n" help-$(b) $(b);) \
+ printf " %-16s - Show all of the above\\n" help-boards; \
+ echo '')
+
+ @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
+ @echo ' make V=2 [targets] 2 => give reason for rebuild of target'
+ @echo ' make O=dir [targets] Locate all output files in "dir", including .config'
+ @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)'
+ @echo ' make C=2 [targets] Force check of all c source with $$CHECK'
+ @echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections'
+ @echo ' make W=n [targets] Enable extra gcc checks, n=1,2,3 where'
+ @echo ' 1: warnings which may be relevant and do not occur too often'
+ @echo ' 2: warnings which occur quite often but may still be relevant'
+ @echo ' 3: more obscure warnings, can most likely be ignored'
+ @echo ' Multiple levels can be combined with W=12 or W=123'
+ @echo ''
+ @echo 'Execute "make" or "make all" to build all targets marked with [*] '
+ @echo 'For further info see the ./README file'
+
+
+help-board-dirs := $(addprefix help-,$(board-dirs))
+
+help-boards: $(help-board-dirs)
+
+boards-per-dir = $(notdir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/$*/*_defconfig))
+
+$(help-board-dirs): help-%:
+ @echo 'Architecture specific targets ($(SRCARCH) $*):'
+ @$(if $(boards-per-dir), \
+ $(foreach b, $(boards-per-dir), \
+ printf " %-24s - Build for %s\\n" $*/$(b) $(subst _defconfig,,$(b));) \
+ echo '')
+
+
+# Documentation targets
+# ---------------------------------------------------------------------------
+%docs: scripts_basic FORCE
+ $(Q)$(MAKE) $(build)=scripts build_docproc
+ $(Q)$(MAKE) $(build)=Documentation/DocBook $@
+
+else # KBUILD_EXTMOD
+
+###
+# External module support.
+# When building external modules the kernel used as basis is considered
+# read-only, and no consistency checks are made and the make
+# system is not used on the basis kernel. If updates are required
+# in the basis kernel ordinary make commands (without M=...) must
+# be used.
+#
+# The following are the only valid targets when building external
+# modules.
+# make M=dir clean Delete all automatically generated files
+# 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 built in the module directory
+# Assumes install directory is already created
+
+# We are always building modules
+KBUILD_MODULES := 1
+PHONY += crmodverdir
+crmodverdir:
+ $(cmd_crmodverdir)
+
+PHONY += $(objtree)/Module.symvers
+$(objtree)/Module.symvers:
+ @test -e $(objtree)/Module.symvers || ( \
+ echo; \
+ echo " WARNING: Symbol version dump $(objtree)/Module.symvers"; \
+ echo " is missing; modules will have no dependencies and modversions."; \
+ echo )
+
+module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
+PHONY += $(module-dirs) modules
+$(module-dirs): crmodverdir $(objtree)/Module.symvers
+ $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
+
+modules: $(module-dirs)
+ @$(kecho) ' Building modules, stage 2.';
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
+
+PHONY += modules_install
+modules_install: _emodinst_ _emodinst_post
+
+install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra)
+PHONY += _emodinst_
+_emodinst_:
+ $(Q)mkdir -p $(MODLIB)/$(install-dir)
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
+
+PHONY += _emodinst_post
+_emodinst_post: _emodinst_
+ $(call cmd,depmod)
+
+clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
+
+PHONY += $(clean-dirs) clean
+$(clean-dirs):
+ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
+
+clean: rm-dirs := $(MODVERDIR)
+clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers
+
+help:
+ @echo ' Building external modules.'
+ @echo ' Syntax: make -C path/to/kernel/src M=$$PWD target'
+ @echo ''
+ @echo ' modules - default target, build the module(s)'
+ @echo ' modules_install - install the module'
+ @echo ' clean - remove generated files in module directory only'
+ @echo ''
+
+# Dummies...
+PHONY += prepare scripts
+prepare: ;
+scripts: ;
+endif # KBUILD_EXTMOD
+
+clean: $(clean-dirs)
+ $(call cmd,rmdirs)
+ $(call cmd,rmfiles)
+ @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
+ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+ -o -name '*.ko.*' \
+ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
+ -o -name '*.symtypes' -o -name 'modules.order' \
+ -o -name modules.builtin -o -name '.tmp_*.o.*' \
+ -o -name '*.gcno' \) -type f -print | xargs rm -f
+
+# Generate tags for editors
+# ---------------------------------------------------------------------------
+quiet_cmd_tags = GEN $@
+ cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@
+
+tags TAGS cscope gtags: FORCE
+ $(call cmd,tags)
+
+# Scripts to check various things for consistency
+# ---------------------------------------------------------------------------
+
+PHONY += includecheck versioncheck coccicheck namespacecheck export_report
+
+includecheck:
+ find $(srctree)/* $(RCS_FIND_IGNORE) \
+ -name '*.[hcS]' -type f -print | sort \
+ | xargs $(PERL) -w $(srctree)/scripts/checkincludes.pl
+
+versioncheck:
+ find $(srctree)/* $(RCS_FIND_IGNORE) \
+ -name '*.[hcS]' -type f -print | sort \
+ | xargs $(PERL) -w $(srctree)/scripts/checkversion.pl
+
+coccicheck:
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@
+
+namespacecheck:
+ $(PERL) $(srctree)/scripts/namespace.pl
+
+export_report:
+ $(PERL) $(srctree)/scripts/export_report.pl
+
+endif #ifeq ($(config-targets),1)
+endif #ifeq ($(mixed-targets),1)
+
+PHONY += checkstack kernelrelease kernelversion
+
+# UML needs a little special treatment here. It wants to use the host
+# toolchain, so needs $(SUBARCH) passed to checkstack.pl. Everyone
+# else wants $(ARCH), including people doing cross-builds, which means
+# that $(SUBARCH) doesn't work here.
+ifeq ($(ARCH), um)
+CHECKSTACK_ARCH := $(SUBARCH)
+else
+CHECKSTACK_ARCH := $(ARCH)
+endif
+checkstack:
+ $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
+ $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH)
+
+kernelrelease:
+ @echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))"
+
+kernelversion:
+ @echo $(KERNELVERSION)
+
+# Clear a bunch of variables before executing the submake
+tools/: FORCE
+ $(Q)mkdir -p $(objtree)/tools
+ $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/
+
+tools/%: FORCE
+ $(Q)mkdir -p $(objtree)/tools
+ $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/ $*
+
+# Single targets
+# ---------------------------------------------------------------------------
+# Single targets are compatible with:
+# - build with mixed source and output
+# - build with separate output dir 'make O=...'
+# - external modules
+#
+# target-dir => where to store outputfile
+# build-dir => directory in kernel source tree to use
+
+ifeq ($(KBUILD_EXTMOD),)
+ build-dir = $(patsubst %/,%,$(dir $@))
+ target-dir = $(dir $@)
+else
+ zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
+ build-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
+ target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
+endif
+
+%.s: %.c prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.i: %.c prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.o: %.c prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.lst: %.c prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.s: %.S prepare scripts FORCE
+ $(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
+ $(cmd_crmodverdir)
+ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+ $(build)=$(build-dir)
+%/: prepare scripts FORCE
+ $(cmd_crmodverdir)
+ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+ $(build)=$(build-dir)
+%.ko: prepare scripts FORCE
+ $(cmd_crmodverdir)
+ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+ $(build)=$(build-dir) $(@:.ko=.o)
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
+
+# FIXME Should go into a make.lib or something
+# ===========================================================================
+
+quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN $(wildcard $(rm-dirs)))
+ cmd_rmdirs = rm -rf $(rm-dirs)
+
+quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)))
+ cmd_rmfiles = rm -f $(rm-files)
+
+# Run depmod only if we have System.map and depmod is executable
+quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
+ cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \
+ $(KERNELRELEASE)
+
+# Create temporary dir for module support files
+# clean it up only when building all modules
+cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \
+ $(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*)
+
+# read all saved command lines
+
+targets := $(wildcard $(sort $(targets)))
+cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
+
+ifneq ($(cmd_files),)
+ $(cmd_files): ; # Do not try to update included dependency files
+ include $(cmd_files)
+endif
+
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
+# Usage:
+# $(Q)$(MAKE) $(clean)=dir
+clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
+
+endif # skip-makefile
+
+PHONY += FORCE
+FORCE:
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable so we can use it in if_changed and friends.
+.PHONY: $(PHONY)
diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h
new file mode 100644
index 0000000..be342b9
--- /dev/null
+++ b/include/linux/kconfig.h
@@ -0,0 +1,46 @@
+#ifndef __LINUX_KCONFIG_H
+#define __LINUX_KCONFIG_H
+
+#include <generated/autoconf.h>
+
+/*
+ * Helper macros to use CONFIG_ options in C/CPP expressions. Note that
+ * these only work with boolean and tristate options.
+ */
+
+/*
+ * Getting something that works in C and CPP for an arg that may or may
+ * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1"
+ * we match on the placeholder define, insert the "0," for arg1 and generate
+ * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one).
+ * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
+ * the last step cherry picks the 2nd arg, we get a zero.
+ */
+#define __ARG_PLACEHOLDER_1 0,
+#define config_enabled(cfg) _config_enabled(cfg)
+#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
+#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0)
+#define ___config_enabled(__ignored, val, ...) val
+
+/*
+ * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
+ * 0 otherwise.
+ *
+ */
+#define IS_ENABLED(option) \
+ (config_enabled(option) || config_enabled(option##_MODULE))
+
+/*
+ * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
+ * otherwise. For boolean options, this is equivalent to
+ * IS_ENABLED(CONFIG_FOO).
+ */
+#define IS_BUILTIN(option) config_enabled(option)
+
+/*
+ * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0
+ * otherwise.
+ */
+#define IS_MODULE(option) config_enabled(option##_MODULE)
+
+#endif /* __LINUX_KCONFIG_H */
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
new file mode 100644
index 0000000..978416d
--- /dev/null
+++ b/scripts/Kbuild.include
@@ -0,0 +1,278 @@
+####
+# kbuild: Generic definitions
+
+# Convenient variables
+comma := ,
+squote := '
+empty :=
+space := $(empty) $(empty)
+
+###
+# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
+dot-target = $(dir $@).$(notdir $@)
+
+###
+# The temporary file to save gcc -MD generated dependencies must not
+# contain a comma
+depfile = $(subst $(comma),_,$(dot-target).d)
+
+###
+# filename of target with directory and extension stripped
+basetarget = $(basename $(notdir $@))
+
+###
+# filename of first prerequisite with directory and extension stripped
+baseprereq = $(basename $(notdir $<))
+
+###
+# Escape single quote for use in echo statements
+escsq = $(subst $(squote),'\$(squote)',$1)
+
+###
+# Easy method for doing a status message
+ kecho := :
+ quiet_kecho := echo
+silent_kecho := :
+kecho := $($(quiet)kecho)
+
+###
+# filechk is used to check if the content of a generated file is updated.
+# Sample usage:
+# define filechk_sample
+# echo $KERNELRELEASE
+# endef
+# version.h : Makefile
+# $(call filechk,sample)
+# The rule defined shall write to stdout the content of the new file.
+# The existing file will be compared with the new one.
+# - If no file exist it is created
+# - If the content differ the new file is used
+# - If they are equal no change, and no timestamp update
+# - stdin is piped in from the first prerequisite ($<) so one has
+# to specify a valid file as first prerequisite (often the kbuild file)
+define filechk
+ $(Q)set -e; \
+ $(kecho) ' CHK $@'; \
+ mkdir -p $(dir $@); \
+ $(filechk_$(1)) < $< > $@.tmp; \
+ if [ -r $@ ] && cmp -s $@ $@.tmp; then \
+ rm -f $@.tmp; \
+ else \
+ $(kecho) ' UPD $@'; \
+ mv -f $@.tmp $@; \
+ fi
+endef
+
+######
+# gcc support functions
+# See documentation in Documentation/kbuild/makefiles.txt
+
+# cc-cross-prefix
+# Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-)
+# Return first prefix where a prefix$(CC) is found in PATH.
+# If no $(CC) found in PATH with listed prefixes return nothing
+cc-cross-prefix = \
+ $(word 1, $(foreach c,$(1), \
+ $(shell set -e; \
+ if (which $(strip $(c))$(CC)) > /dev/null 2>&1 ; then \
+ echo $(c); \
+ fi)))
+
+# output directory for tests below
+TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
+
+# try-run
+# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
+# Exit code chooses option. "$$TMP" is can be used as temporary file and
+# is automatically cleaned up.
+try-run = $(shell set -e; \
+ TMP="$(TMPOUT).$$$$.tmp"; \
+ TMPO="$(TMPOUT).$$$$.o"; \
+ if ($(1)) >/dev/null 2>&1; \
+ then echo "$(2)"; \
+ else echo "$(3)"; \
+ fi; \
+ rm -f "$$TMP" "$$TMPO")
+
+# as-option
+# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
+
+as-option = $(call try-run,\
+ $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
+
+# as-instr
+# Usage: cflags-y += $(call as-instr,instr,option1,option2)
+
+as-instr = $(call try-run,\
+ printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
+
+# cc-option
+# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
+
+cc-option = $(call try-run,\
+ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
+
+# cc-option-yn
+# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
+cc-option-yn = $(call try-run,\
+ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
+
+# cc-option-align
+# Prefix align with either -falign or -malign
+cc-option-align = $(subst -functions=0,,\
+ $(call cc-option,-falign-functions=0,-malign-functions=0))
+
+# cc-disable-warning
+# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
+cc-disable-warning = $(call try-run,\
+ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
+
+# cc-version
+# Usage gcc-ver := $(call cc-version)
+cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
+
+# cc-fullversion
+# Usage gcc-ver := $(call cc-fullversion)
+cc-fullversion = $(shell $(CONFIG_SHELL) \
+ $(srctree)/scripts/gcc-version.sh -p $(CC))
+
+# cc-ifversion
+# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
+cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
+
+# cc-ldoption
+# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
+cc-ldoption = $(call try-run,\
+ $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
+
+# ld-option
+# Usage: LDFLAGS += $(call ld-option, -X)
+ld-option = $(call try-run,\
+ $(CC) /dev/null -c -o "$$TMPO" ; $(LD) $(1) "$$TMPO" -o "$$TMP",$(1),$(2))
+
+# ar-option
+# Usage: KBUILD_ARFLAGS := $(call ar-option,D)
+# Important: no spaces around options
+ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
+
+######
+
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
+# Usage:
+# $(Q)$(MAKE) $(build)=dir
+build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
+
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
+# Usage:
+# $(Q)$(MAKE) $(modbuiltin)=dir
+modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj
+
+# Prefix -I with $(srctree) if it is not an absolute path.
+# skip if -I has no parameter
+addtree = $(if $(patsubst -I%,%,$(1)), \
+$(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1))
+
+# Find all -I options and call addtree
+flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
+
+# echo command.
+# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
+echo-cmd = $(if $($(quiet)cmd_$(1)),\
+ echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
+
+# printing commands
+cmd = @$(echo-cmd) $(cmd_$(1))
+
+# Add $(obj)/ for paths that are not absolute
+objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
+
+###
+# if_changed - execute command if any prerequisite is newer than
+# target, or command line has changed
+# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies
+# including used config symbols
+# if_changed_rule - as if_changed but execute rule instead
+# See Documentation/kbuild/makefiles.txt for more info
+
+ifneq ($(KBUILD_NOCMDDEP),1)
+# Check if both arguments has same arguments. Result is empty string if equal.
+# User may override this check using make KBUILD_NOCMDDEP=1
+arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
+ $(filter-out $(cmd_$@), $(cmd_$(1))) )
+else
+arg-check = $(if $(strip $(cmd_$@)),,1)
+endif
+
+# >'< substitution is for echo to work,
+# >$< substitution to preserve $ when reloading .cmd file
+# note: when using inline perl scripts [perl -e '...$$t=1;...']
+# in $(cmd_xxx) double $$ your perl vars
+make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))))
+
+# Find any prerequisites that is newer than target or that does not exist.
+# PHONY targets skipped in both cases.
+any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
+
+# Execute command if command has changed or prerequisite(s) are updated.
+#
+if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
+ @set -e; \
+ $(echo-cmd) $(cmd_$(1)); \
+ echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
+
+# Execute the command and also postprocess generated .d dependencies file.
+if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \
+ @set -e; \
+ $(echo-cmd) $(cmd_$(1)); \
+ scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\
+ rm -f $(depfile); \
+ mv -f $(dot-target).tmp $(dot-target).cmd)
+
+# Usage: $(call if_changed_rule,foo)
+# Will check if $(cmd_foo) or any of the prerequisites changed,
+# and if so will execute $(rule_foo).
+if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \
+ @set -e; \
+ $(rule_$(1)))
+
+###
+# why - tell why a a target got build
+# enabled by make V=2
+# Output (listed in the order they are checked):
+# (1) - due to target is PHONY
+# (2) - due to target missing
+# (3) - due to: file1.h file2.h
+# (4) - due to command line change
+# (5) - due to missing .cmd file
+# (6) - due to target not in $(targets)
+# (1) PHONY targets are always build
+# (2) No target, so we better build it
+# (3) Prerequisite is newer than target
+# (4) The command line stored in the file named dir/.target.cmd
+# differed from actual command line. This happens when compiler
+# options changes
+# (5) No dir/.target.cmd file (used to store command line)
+# (6) No dir/.target.cmd file and target not listed in $(targets)
+# This is a good hint that there is a bug in the kbuild file
+ifeq ($(KBUILD_VERBOSE),2)
+why = \
+ $(if $(filter $@, $(PHONY)),- due to target is PHONY, \
+ $(if $(wildcard $@), \
+ $(if $(strip $(any-prereq)),- due to: $(any-prereq), \
+ $(if $(arg-check), \
+ $(if $(cmd_$@),- due to command line change, \
+ $(if $(filter $@, $(targets)), \
+ - due to missing .cmd file, \
+ - due to $(notdir $@) not in $$(targets) \
+ ) \
+ ) \
+ ) \
+ ), \
+ - due to target missing \
+ ) \
+ )
+
+echo-why = $(call escsq, $(strip $(why)))
+endif
diff --git a/scripts/Makefile b/scripts/Makefile
new file mode 100644
index 0000000..01e7adb
--- /dev/null
+++ b/scripts/Makefile
@@ -0,0 +1,42 @@
+###
+# scripts contains sources for various helper programs used throughout
+# the kernel for the build process.
+# ---------------------------------------------------------------------------
+# kallsyms: Find all symbols in vmlinux
+# pnmttologo: Convert pnm files to logo files
+# conmakehash: Create chartable
+# conmakehash: Create arrays for initializing the kernel console tables
+# docproc: Used in Documentation/DocBook
+
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include
+
+hostprogs-$(CONFIG_KALLSYMS) += kallsyms
+hostprogs-$(CONFIG_LOGO) += pnmtologo
+hostprogs-$(CONFIG_VT) += conmakehash
+hostprogs-$(CONFIG_IKCONFIG) += bin2c
+hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
+hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
+hostprogs-$(CONFIG_ASN1) += asn1_compiler
+
+HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
+HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
+
+always := $(hostprogs-y) $(hostprogs-m)
+
+# The following hostprogs-y programs are only build on demand
+hostprogs-y += unifdef docproc
+
+# These targets are used internally to avoid "is up to date" messages
+PHONY += build_unifdef
+build_unifdef: scripts/unifdef FORCE
+ @:
+build_docproc: scripts/docproc FORCE
+ @:
+
+subdir-$(CONFIG_MODVERSIONS) += genksyms
+subdir-y += mod
+subdir-$(CONFIG_SECURITY_SELINUX) += selinux
+subdir-$(CONFIG_DTC) += dtc
+
+# Let clean descend into subdirs
+subdir- += basic kconfig package selinux
diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic
new file mode 100644
index 0000000..d17e0ea
--- /dev/null
+++ b/scripts/Makefile.asm-generic
@@ -0,0 +1,24 @@
+# include/asm-generic contains a lot of files that are used
+# verbatim by several architectures.
+#
+# This Makefile reads the file arch/$(SRCARCH)/include/asm/Kbuild
+# and for each file listed in this file with generic-y creates
+# a small wrapper file in $(obj) (arch/$(SRCARCH)/include/generated/asm)
+
+kbuild-file := $(srctree)/arch/$(SRCARCH)/include/$(src)/Kbuild
+-include $(kbuild-file)
+
+include scripts/Kbuild.include
+
+# Create output directory if not already present
+_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
+
+quiet_cmd_wrap = WRAP $@
+cmd_wrap = echo "\#include <asm-generic/$*.h>" >$@
+
+all: $(patsubst %, $(obj)/%, $(generic-y))
+ @:
+
+$(obj)/%.h:
+ $(call cmd,wrap)
+
diff --git a/scripts/Makefile.autoconf b/scripts/Makefile.autoconf
new file mode 100644
index 0000000..ed78859
--- /dev/null
+++ b/scripts/Makefile.autoconf
@@ -0,0 +1,68 @@
+
+
+# Make include/config/autoconf.mk
+
+include $(objtree)/include/config.mk
+SRCARCH = $(ARCH)
+include $(srctree)/arch/$(SRCARCH)/config.mk
+
+all: $(objtree)/include/config/autoconf.mk.dep \
+ $(objtree)/include/config/autoconf.mk \
+ $(objtree)/include/generated/generic-asm-offsets.h \
+ $(objtree)/include/generated/asm-offsets.h
+
+
+CFLAGS := $(KBUILD_CFLAGS) $(KBUILD_CPPFLAGS) $(PLATFORM_CPPFLAGS)
+
+#
+# Auto-generate the autoconf.mk file (which is included by all makefiles)
+#
+# This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
+# the dep file is only include in this top level makefile to determine when
+# to regenerate the autoconf.mk file.
+$(objtree)/include/config/autoconf.mk.dep: $(objtree)/include/config.h include/common.h
+ $(Q)set -e ; \
+ : Generate the dependancies ; \
+ $(CC) -x c -DDO_DEPS_ONLY -M $(CFLAGS) $(CPPFLAGS) \
+ -Iinclude \
+ -MQ $(objtree)/include/config/autoconf.mk include/common.h > $@
+
+$(objtree)/include/config/autoconf.mk: $(objtree)/include/config.h
+ $(Q)set -e ; \
+ : Extract the config macros ; \
+ $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h \
+ -Iinclude | \
+ sed -n -f tools/scripts/define2mk.sed > $@.tmp && \
+ mv $@.tmp $@
+
+CPUDIR = arch/$(ARCH)/cpu/$(CPU)
+ifneq ($(SRCTREE)/$(CPUDIR),$(wildcard $(SRCTREE)/$(CPUDIR)))
+CPUDIR = arch/$(ARCH)/cpu
+endif
+
+$(objtree)/include/generated/generic-asm-offsets.h: $(objtree)/include/config/autoconf.mk.dep \
+ $(objtree)/lib/asm-offsets.s
+ $(Q)tools/scripts/make-asm-offsets $(objtree)/lib/asm-offsets.s $@
+
+$(objtree)/lib/asm-offsets.s: $(objtree)/include/config/autoconf.mk.dep \
+ $(src)lib/asm-offsets.c
+ $(Q)@mkdir -p $(objtree)/lib
+ $(Q)$(CC) -DDO_DEPS_ONLY \
+ $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR)) \
+ -Iinclude \
+ -o $@ $(src)lib/asm-offsets.c -c -S
+
+$(objtree)/include/generated/asm-offsets.h: $(objtree)/include/config/autoconf.mk.dep \
+ $(objtree)/$(CPUDIR)/$(SOC)/asm-offsets.s
+ $(Q)tools/scripts/make-asm-offsets $(objtree)/$(CPUDIR)/$(SOC)/asm-offsets.s $@
+
+$(objtree)/$(CPUDIR)/$(SOC)/asm-offsets.s: $(objtree)/include/config/autoconf.mk.dep
+ $(Q)mkdir -p $(objtree)/$(CPUDIR)/$(SOC)
+ $(Q)if [ -f $(src)$(CPUDIR)/$(SOC)/asm-offsets.c ];then \
+ $(CC) -DDO_DEPS_ONLY \
+ $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR)) \
+ -Iinclude \
+ -o $@ $(src)$(CPUDIR)/$(SOC)/asm-offsets.c -c -S; \
+ else \
+ touch $@; \
+ fi
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
new file mode 100644
index 0000000..0e801c3
--- /dev/null
+++ b/scripts/Makefile.build
@@ -0,0 +1,478 @@
+# ==========================================================================
+# Building
+# ==========================================================================
+
+src := $(obj)
+
+PHONY := __build
+__build:
+
+# Init all relevant variables used in kbuild files so
+# 1) they have correct type
+# 2) they do not inherit any value from the environment
+obj-y :=
+obj-m :=
+lib-y :=
+lib-m :=
+always :=
+targets :=
+subdir-y :=
+subdir-m :=
+EXTRA_AFLAGS :=
+EXTRA_CFLAGS :=
+EXTRA_CPPFLAGS :=
+EXTRA_LDFLAGS :=
+asflags-y :=
+ccflags-y :=
+cppflags-y :=
+ldflags-y :=
+
+subdir-asflags-y :=
+subdir-ccflags-y :=
+
+# Read auto.conf if it exists, otherwise ignore
+-include include/config/auto.conf
+
+include scripts/Kbuild.include
+
+# For backward compatibility check that these variables do not change
+save-cflags := $(CFLAGS)
+
+# The filename Kbuild has precedence over Makefile
+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
+include $(kbuild-file)
+
+# If the save-* variables changed error out
+ifeq ($(KBUILD_NOPEDANTIC),)
+ ifneq ("$(save-cflags)","$(CFLAGS)")
+ $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use ccflags-y)
+ endif
+endif
+
+#
+# make W=... settings
+#
+# W=1 - warnings that may be relevant and does not occur too often
+# W=2 - warnings that occur quite often but may still be relevant
+# W=3 - the more obscure warnings, can most likely be ignored
+#
+# $(call cc-option, -W...) handles gcc -W.. options which
+# are not supported by all versions of the compiler
+ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS
+warning- := $(empty)
+
+warning-1 := -Wextra -Wunused -Wno-unused-parameter
+warning-1 += -Wmissing-declarations
+warning-1 += -Wmissing-format-attribute
+warning-1 += -Wmissing-prototypes
+warning-1 += -Wold-style-definition
+warning-1 += $(call cc-option, -Wmissing-include-dirs)
+warning-1 += $(call cc-option, -Wunused-but-set-variable)
+warning-1 += $(call cc-disable-warning, missing-field-initializers)
+
+warning-2 := -Waggregate-return
+warning-2 += -Wcast-align
+warning-2 += -Wdisabled-optimization
+warning-2 += -Wnested-externs
+warning-2 += -Wshadow
+warning-2 += $(call cc-option, -Wlogical-op)
+warning-2 += $(call cc-option, -Wmissing-field-initializers)
+
+warning-3 := -Wbad-function-cast
+warning-3 += -Wcast-qual
+warning-3 += -Wconversion
+warning-3 += -Wpacked
+warning-3 += -Wpadded
+warning-3 += -Wpointer-arith
+warning-3 += -Wredundant-decls
+warning-3 += -Wswitch-default
+warning-3 += $(call cc-option, -Wpacked-bitfield-compat)
+warning-3 += $(call cc-option, -Wvla)
+
+warning := $(warning-$(findstring 1, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
+warning += $(warning-$(findstring 2, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
+warning += $(warning-$(findstring 3, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
+
+ifeq ("$(strip $(warning))","")
+ $(error W=$(KBUILD_ENABLE_EXTRA_GCC_CHECKS) is unknown)
+endif
+
+KBUILD_CFLAGS += $(warning)
+endif
+
+include scripts/Makefile.lib
+
+ifdef host-progs
+ifneq ($(hostprogs-y),$(host-progs))
+$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!)
+hostprogs-y += $(host-progs)
+endif
+endif
+
+# Do not include host rules unless needed
+ifneq ($(hostprogs-y)$(hostprogs-m),)
+include scripts/Makefile.host
+endif
+
+ifneq ($(KBUILD_SRC),)
+# Create output directory if not already present
+_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
+
+# Create directories for object files if directory does not exist
+# Needed when obj-y := dir/file.o syntax is used
+_dummy := $(foreach d,$(obj-dirs), $(shell [ -d $(d) ] || mkdir -p $(d)))
+endif
+
+ifndef obj
+$(warning kbuild: Makefile.build is included improperly)
+endif
+
+# ===========================================================================
+
+ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
+lib-target := $(obj)/lib.a
+endif
+
+ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(subdir-m) $(lib-target)),)
+builtin-target := $(obj)/built-in.o
+endif
+
+modorder-target := $(obj)/modules.order
+
+# We keep a list of all modules in $(MODVERDIR)
+
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+ $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
+ $(subdir-ym) $(always)
+ @:
+
+# Linus' kernel sanity checking tool
+ifneq ($(KBUILD_CHECKSRC),0)
+ ifeq ($(KBUILD_CHECKSRC),2)
+ quiet_cmd_force_checksrc = CHECK $<
+ cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
+ else
+ quiet_cmd_checksrc = CHECK $<
+ cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
+ endif
+endif
+
+# Do section mismatch analysis for each module/built-in.o
+ifdef CONFIG_DEBUG_SECTION_MISMATCH
+ cmd_secanalysis = ; scripts/mod/modpost $@
+endif
+
+# Compile C sources (.c)
+# ---------------------------------------------------------------------------
+
+# Default is built-in, unless we know otherwise
+modkern_cflags = \
+ $(if $(part-of-module), \
+ $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
+ $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL))
+quiet_modtag := $(empty) $(empty)
+
+$(real-objs-m) : part-of-module := y
+$(real-objs-m:.o=.i) : part-of-module := y
+$(real-objs-m:.o=.s) : part-of-module := y
+$(real-objs-m:.o=.lst): part-of-module := y
+
+$(real-objs-m) : quiet_modtag := [M]
+$(real-objs-m:.o=.i) : quiet_modtag := [M]
+$(real-objs-m:.o=.s) : quiet_modtag := [M]
+$(real-objs-m:.o=.lst): quiet_modtag := [M]
+
+$(obj-m) : quiet_modtag := [M]
+
+# Default for not multi-part modules
+modname = $(basetarget)
+
+$(multi-objs-m) : modname = $(modname-multi)
+$(multi-objs-m:.o=.i) : modname = $(modname-multi)
+$(multi-objs-m:.o=.s) : modname = $(modname-multi)
+$(multi-objs-m:.o=.lst) : modname = $(modname-multi)
+$(multi-objs-y) : modname = $(modname-multi)
+$(multi-objs-y:.o=.i) : modname = $(modname-multi)
+$(multi-objs-y:.o=.s) : modname = $(modname-multi)
+$(multi-objs-y:.o=.lst) : modname = $(modname-multi)
+
+quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
+cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
+
+$(obj)/%.s: $(src)/%.c FORCE
+ $(call if_changed_dep,cc_s_c)
+
+quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@
+cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $<
+
+$(obj)/%.i: $(src)/%.c FORCE
+ $(call if_changed_dep,cc_i_c)
+
+cmd_gensymtypes = \
+ $(CPP) -D__GENKSYMS__ $(c_flags) $< | \
+ $(GENKSYMS) $(if $(1), -T $(2)) -a $(ARCH) \
+ $(if $(KBUILD_PRESERVE),-p) \
+ -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
+
+quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
+cmd_cc_symtypes_c = \
+ set -e; \
+ $(call cmd_gensymtypes,true,$@) >/dev/null; \
+ test -s $@ || rm -f $@
+
+$(obj)/%.symtypes : $(src)/%.c FORCE
+ $(call cmd,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)
+
+quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
+
+ifndef CONFIG_MODVERSIONS
+cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
+
+else
+# When module versioning is enabled the following steps are executed:
+# o compile a .tmp_<file>.o from <file>.c
+# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
+# not export symbols, we just rename .tmp_<file>.o to <file>.o and
+# are done.
+# o otherwise, we calculate symbol versions using the good old
+# genksyms on the preprocessed source and postprocess them in a way
+# that they are usable as a linker script
+# o generate <file>.o from .tmp_<file>.o using the linker to
+# replace the unresolved symbols __crc_exported_symbol with
+# the actual value of the checksum generated by genksyms
+
+cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
+cmd_modversions = \
+ if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
+ $(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
+ > $(@D)/.tmp_$(@F:.o=.ver); \
+ \
+ $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
+ -T $(@D)/.tmp_$(@F:.o=.ver); \
+ rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
+ else \
+ mv -f $(@D)/.tmp_$(@F) $@; \
+ fi;
+endif
+
+ifdef CONFIG_FTRACE_MCOUNT_RECORD
+ifdef BUILD_C_RECORDMCOUNT
+ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
+ RECORDMCOUNT_FLAGS = -w
+endif
+# Due to recursion, we must skip empty.o.
+# The empty.o file is created in the make process in order to determine
+# the target endianness and word size. It is made before all other C
+# files, including recordmcount.
+sub_cmd_record_mcount = \
+ if [ $(@) != "scripts/mod/empty.o" ]; then \
+ $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \
+ fi;
+recordmcount_source := $(srctree)/scripts/recordmcount.c \
+ $(srctree)/scripts/recordmcount.h
+else
+sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
+ "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
+ "$(if $(CONFIG_64BIT),64,32)" \
+ "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
+ "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
+ "$(if $(part-of-module),1,0)" "$(@)";
+recordmcount_source := $(srctree)/scripts/recordmcount.pl
+endif
+cmd_record_mcount = \
+ if [ "$(findstring -pg,$(_c_flags))" = "-pg" ]; then \
+ $(sub_cmd_record_mcount) \
+ fi;
+endif
+
+define rule_cc_o_c
+ $(call echo-cmd,checksrc) $(cmd_checksrc) \
+ $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \
+ $(cmd_modversions) \
+ $(call echo-cmd,record_mcount) \
+ $(cmd_record_mcount) \
+ scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \
+ $(dot-target).tmp; \
+ rm -f $(depfile); \
+ mv -f $(dot-target).tmp $(dot-target).cmd
+endef
+
+# Built-in and composite module parts
+$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
+ $(call cmd,force_checksrc)
+ $(call if_changed_rule,cc_o_c)
+
+# Single-part modules are special since we need to mark them in $(MODVERDIR)
+
+$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
+ $(call cmd,force_checksrc)
+ $(call if_changed_rule,cc_o_c)
+ @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
+
+quiet_cmd_cc_lst_c = MKLST $@
+ cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
+ $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
+ System.map $(OBJDUMP) > $@
+
+$(obj)/%.lst: $(src)/%.c FORCE
+ $(call if_changed_dep,cc_lst_c)
+
+# Compile assembler sources (.S)
+# ---------------------------------------------------------------------------
+
+modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL)
+
+$(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
+$(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
+
+quiet_cmd_as_s_S = CPP $(quiet_modtag) $@
+cmd_as_s_S = $(CPP) $(a_flags) -o $@ $<
+
+$(obj)/%.s: $(src)/%.S FORCE
+ $(call if_changed_dep,as_s_S)
+
+quiet_cmd_as_o_S = AS $(quiet_modtag) $@
+cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
+
+$(obj)/%.o: $(src)/%.S FORCE
+ $(call if_changed_dep,as_o_S)
+
+targets += $(real-objs-y) $(real-objs-m) $(lib-y)
+targets += $(extra-y) $(MAKECMDGOALS) $(always)
+
+# Linker scripts preprocessor (.lds.S -> .lds)
+# ---------------------------------------------------------------------------
+quiet_cmd_cpp_lds_S = LDS $@
+ cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -C -U$(ARCH) \
+ -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+$(obj)/%.lds: $(src)/%.lds.S FORCE
+ $(call if_changed_dep,cpp_lds_S)
+
+# ASN.1 grammar
+# ---------------------------------------------------------------------------
+quiet_cmd_asn1_compiler = ASN.1 $@
+ cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
+ $(subst .h,.c,$@) $(subst .c,.h,$@)
+
+.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h
+
+$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
+ $(call cmd,asn1_compiler)
+
+# Build the compiled-in targets
+# ---------------------------------------------------------------------------
+
+# To build objects in subdirs, we need to descend into the directories
+$(sort $(subdir-obj-y)): $(subdir-ym) ;
+
+#
+# Rule to compile a set of .o files into one .o file
+#
+ifdef builtin-target
+quiet_cmd_link_o_target = LD $@
+# If the list of objects to link is empty, just create an empty built-in.o
+cmd_link_o_target = $(if $(strip $(obj-y)),\
+ $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \
+ $(cmd_secanalysis),\
+ rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@)
+
+$(builtin-target): $(obj-y) FORCE
+ $(call if_changed,link_o_target)
+
+targets += $(builtin-target)
+endif # builtin-target
+
+#
+# Rule to create modules.order file
+#
+# Create commands to either record .ko file or cat modules.order from
+# a subdirectory
+modorder-cmds = \
+ $(foreach m, $(modorder), \
+ $(if $(filter %/modules.order, $m), \
+ cat $m;, echo kernel/$m;))
+
+$(modorder-target): $(subdir-ym) FORCE
+ $(Q)(cat /dev/null; $(modorder-cmds)) > $@
+
+#
+# Rule to compile a set of .o files into one .a file
+#
+ifdef lib-target
+quiet_cmd_link_l_target = AR $@
+cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y)
+
+$(lib-target): $(lib-y) FORCE
+ $(call if_changed,link_l_target)
+
+targets += $(lib-target)
+endif
+
+#
+# Rule to link composite objects
+#
+# Composite objects are specified in kbuild makefile as follows:
+# <composite-object>-objs := <list of .o files>
+# or
+# <composite-object>-y := <list of .o files>
+link_multi_deps = \
+$(filter $(addprefix $(obj)/, \
+$($(subst $(obj)/,,$(@:.o=-objs))) \
+$($(subst $(obj)/,,$(@:.o=-y)))), $^)
+
+quiet_cmd_link_multi-y = LD $@
+cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalysis)
+
+quiet_cmd_link_multi-m = LD [M] $@
+cmd_link_multi-m = $(cmd_link_multi-y)
+
+# We would rather have a list of rules like
+# foo.o: $(foo-objs)
+# but that's not so easy, so we rather make all composite objects depend
+# on the set of all their parts
+$(multi-used-y) : %.o: $(multi-objs-y) FORCE
+ $(call if_changed,link_multi-y)
+
+$(multi-used-m) : %.o: $(multi-objs-m) FORCE
+ $(call if_changed,link_multi-m)
+ @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
+
+targets += $(multi-used-y) $(multi-used-m)
+
+
+# Descending
+# ---------------------------------------------------------------------------
+
+PHONY += $(subdir-ym)
+$(subdir-ym):
+ $(Q)$(MAKE) $(build)=$@
+
+# Add FORCE to the prequisites of a target to force it to be always rebuilt.
+# ---------------------------------------------------------------------------
+
+PHONY += FORCE
+
+FORCE:
+
+# Read all saved command lines and dependencies for the $(targets) we
+# may be building above, using $(if_changed{,_dep}). As an
+# optimization, we don't need to read them if the target does not
+# exist, we will rebuild anyway in that case.
+
+targets := $(wildcard $(sort $(targets)))
+cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
+
+ifneq ($(cmd_files),)
+ include $(cmd_files)
+endif
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
new file mode 100644
index 0000000..686cb0d
--- /dev/null
+++ b/scripts/Makefile.clean
@@ -0,0 +1,104 @@
+# ==========================================================================
+# Cleaning up
+# ==========================================================================
+
+src := $(obj)
+
+PHONY := __clean
+__clean:
+
+# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir
+# Usage:
+# $(Q)$(MAKE) $(clean)=dir
+clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
+
+# The filename Kbuild has precedence over Makefile
+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
+
+# Figure out what we need to build from the various variables
+# ==========================================================================
+
+__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
+subdir-y += $(__subdir-y)
+__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
+subdir-m += $(__subdir-m)
+__subdir-n := $(patsubst %/,%,$(filter %/, $(obj-n)))
+subdir-n += $(__subdir-n)
+__subdir- := $(patsubst %/,%,$(filter %/, $(obj-)))
+subdir- += $(__subdir-)
+
+# Subdirectories we need to descend into
+
+subdir-ym := $(sort $(subdir-y) $(subdir-m))
+subdir-ymn := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
+
+# Add subdir path
+
+subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
+
+# build a list of files to remove, usually relative to the current
+# directory
+
+__clean-files := $(extra-y) $(always) \
+ $(targets) $(clean-files) \
+ $(host-progs) \
+ $(hostprogs-y) $(hostprogs-m) $(hostprogs-)
+
+__clean-files := $(filter-out $(no-clean-files), $(__clean-files))
+
+# as clean-files is given relative to the current directory, this adds
+# a $(obj) prefix, except for absolute paths
+
+__clean-files := $(wildcard \
+ $(addprefix $(obj)/, $(filter-out /%, $(__clean-files))) \
+ $(filter /%, $(__clean-files)))
+
+# as clean-dirs is given relative to the current directory, this adds
+# a $(obj) prefix, except for absolute paths
+
+__clean-dirs := $(wildcard \
+ $(addprefix $(obj)/, $(filter-out /%, $(clean-dirs))) \
+ $(filter /%, $(clean-dirs)))
+
+# ==========================================================================
+
+quiet_cmd_clean = CLEAN $(obj)
+ cmd_clean = rm -f $(__clean-files)
+quiet_cmd_cleandir = CLEAN $(__clean-dirs)
+ cmd_cleandir = rm -rf $(__clean-dirs)
+
+
+__clean: $(subdir-ymn)
+ifneq ($(strip $(__clean-files)),)
+ +$(call cmd,clean)
+endif
+ifneq ($(strip $(__clean-dirs)),)
+ +$(call cmd,cleandir)
+endif
+ifneq ($(strip $(clean-rule)),)
+ +$(clean-rule)
+endif
+ @:
+
+
+# ===========================================================================
+# Generic stuff
+# ===========================================================================
+
+# Descending
+# ---------------------------------------------------------------------------
+
+PHONY += $(subdir-ymn)
+$(subdir-ymn):
+ $(Q)$(MAKE) $(clean)=$@
+
+# If quiet is set, only print short version of command
+
+cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
+
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
new file mode 100644
index 0000000..1ac414f
--- /dev/null
+++ b/scripts/Makefile.host
@@ -0,0 +1,170 @@
+# ==========================================================================
+# Building binaries on the host system
+# Binaries are used during the compilation of the kernel, for example
+# to preprocess a data file.
+#
+# Both C and C++ are supported, but preferred language is C for such utilities.
+#
+# Sample syntax (see Documentation/kbuild/makefiles.txt for reference)
+# hostprogs-y := bin2hex
+# Will compile bin2hex.c and create an executable named bin2hex
+#
+# hostprogs-y := lxdialog
+# lxdialog-objs := checklist.o lxdialog.o
+# Will compile lxdialog.c and checklist.c, and then link the executable
+# lxdialog, based on checklist.o and lxdialog.o
+#
+# hostprogs-y := qconf
+# qconf-cxxobjs := qconf.o
+# qconf-objs := menu.o
+# Will compile qconf as a C++ program, and menu as a C program.
+# They are linked as C++ code to the executable qconf
+
+# hostprogs-y := conf
+# conf-objs := conf.o libkconfig.so
+# libkconfig-objs := expr.o type.o
+# Will create a shared library named libkconfig.so that consists of
+# expr.o and type.o (they are both compiled as C code and the object files
+# are made as position independent code).
+# conf.c is compiled as a C program, and conf.o is linked together with
+# libkconfig.so as the executable conf.
+# Note: Shared libraries consisting of C++ files are not supported
+
+__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
+
+# C code
+# Executables compiled from a single .c file
+host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m)))
+
+# C executables linked based on several .o files
+host-cmulti := $(foreach m,$(__hostprogs),\
+ $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
+
+# Object (.o) files compiled from .c files
+host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
+
+# C++ code
+# C++ executables compiled from at least on .cc file
+# and zero or more .c files
+host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m)))
+
+# C++ Object (.o) files compiled from .cc files
+host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
+
+# Shared libaries (only .c supported)
+# Shared libraries (.so) - all .so files referenced in "xxx-objs"
+host-cshlib := $(sort $(filter %.so, $(host-cobjs)))
+# Remove .so files from "xxx-objs"
+host-cobjs := $(filter-out %.so,$(host-cobjs))
+
+#Object (.o) files used by the shared libaries
+host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
+
+# output directory for programs/.o files
+# hostprogs-y := tools/build may have been specified. Retrieve directory
+host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
+# directory of .o files from prog-objs notation
+host-objdirs += $(foreach f,$(host-cmulti), \
+ $(foreach m,$($(f)-objs), \
+ $(if $(dir $(m)),$(dir $(m)))))
+# directory of .o files from prog-cxxobjs notation
+host-objdirs += $(foreach f,$(host-cxxmulti), \
+ $(foreach m,$($(f)-cxxobjs), \
+ $(if $(dir $(m)),$(dir $(m)))))
+
+host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs))))
+
+
+__hostprogs := $(addprefix $(obj)/,$(__hostprogs))
+host-csingle := $(addprefix $(obj)/,$(host-csingle))
+host-cmulti := $(addprefix $(obj)/,$(host-cmulti))
+host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
+host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
+host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
+host-cshlib := $(addprefix $(obj)/,$(host-cshlib))
+host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs))
+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_$(basetarget).o)
+_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
+ $(HOSTCXXFLAGS_$(basetarget).o)
+
+ifeq ($(KBUILD_SRC),)
+__hostc_flags = $(_hostc_flags)
+__hostcxx_flags = $(_hostcxx_flags)
+else
+__hostc_flags = -I$(obj) $(call flags,_hostc_flags)
+__hostcxx_flags = -I$(obj) $(call flags,_hostcxx_flags)
+endif
+
+hostc_flags = -Wp,-MD,$(depfile) $(__hostc_flags)
+hostcxx_flags = -Wp,-MD,$(depfile) $(__hostcxx_flags)
+
+#####
+# Compile programs on the host
+
+# Create executable from a single .c file
+# host-csingle -> Executable
+quiet_cmd_host-csingle = HOSTCC $@
+ cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \
+ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
+$(host-csingle): $(obj)/%: $(src)/%.c FORCE
+ $(call if_changed_dep,host-csingle)
+
+# Link an executable based on list of .o files, all plain c
+# host-cmulti -> executable
+quiet_cmd_host-cmulti = HOSTLD $@
+ cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
+ $(addprefix $(obj)/,$($(@F)-objs)) \
+ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
+$(host-cmulti): $(obj)/%: $(host-cobjs) $(host-cshlib) FORCE
+ $(call if_changed,host-cmulti)
+
+# Create .o file from a single .c file
+# host-cobjs -> .o
+quiet_cmd_host-cobjs = HOSTCC $@
+ cmd_host-cobjs = $(HOSTCC) $(hostc_flags) -c -o $@ $<
+$(host-cobjs): $(obj)/%.o: $(src)/%.c FORCE
+ $(call if_changed_dep,host-cobjs)
+
+# Link an executable based on list of .o files, a mixture of .c and .cc
+# host-cxxmulti -> executable
+quiet_cmd_host-cxxmulti = HOSTLD $@
+ cmd_host-cxxmulti = $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
+ $(foreach o,objs cxxobjs,\
+ $(addprefix $(obj)/,$($(@F)-$(o)))) \
+ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
+$(host-cxxmulti): $(obj)/%: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
+ $(call if_changed,host-cxxmulti)
+
+# Create .o file from a single .cc (C++) file
+quiet_cmd_host-cxxobjs = HOSTCXX $@
+ cmd_host-cxxobjs = $(HOSTCXX) $(hostcxx_flags) -c -o $@ $<
+$(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE
+ $(call if_changed_dep,host-cxxobjs)
+
+# Compile .c file, create position independent .o file
+# host-cshobjs -> .o
+quiet_cmd_host-cshobjs = HOSTCC -fPIC $@
+ cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
+$(host-cshobjs): $(obj)/%.o: $(src)/%.c FORCE
+ $(call if_changed_dep,host-cshobjs)
+
+# Link a shared library, based on position independent .o files
+# *.o -> .so shared library (host-cshlib)
+quiet_cmd_host-cshlib = HOSTLLD -shared $@
+ cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
+ $(addprefix $(obj)/,$($(@F:.so=-objs))) \
+ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
+$(host-cshlib): $(obj)/%: $(host-cshobjs) FORCE
+ $(call if_changed,host-cshlib)
+
+targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
+ $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs)
+
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
new file mode 100644
index 0000000..07125e6
--- /dev/null
+++ b/scripts/Makefile.lib
@@ -0,0 +1,378 @@
+# Backward compatibility
+asflags-y += $(EXTRA_AFLAGS)
+ccflags-y += $(EXTRA_CFLAGS)
+cppflags-y += $(EXTRA_CPPFLAGS)
+ldflags-y += $(EXTRA_LDFLAGS)
+
+#
+# flags that take effect in sub directories
+export KBUILD_SUBDIR_ASFLAGS := $(KBUILD_SUBDIR_ASFLAGS) $(subdir-asflags-y)
+export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
+
+# Figure out what we need to build from the various variables
+# ===========================================================================
+
+# When an object is listed to be built compiled-in and modular,
+# only build the compiled-in version
+
+obj-m := $(filter-out $(obj-y),$(obj-m))
+
+# Libraries are always collected in one lib file.
+# Filter out objects already built-in
+
+lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))
+
+
+# Handle objects in subdirs
+# ---------------------------------------------------------------------------
+# o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o
+# and add the directory to the list of dirs to descend into: $(subdir-y)
+# o if we encounter foo/ in $(obj-m), remove it from $(obj-m)
+# and add the directory to the list of dirs to descend into: $(subdir-m)
+
+# Determine modorder.
+# Unfortunately, we don't have information about ordering between -y
+# and -m subdirs. Just put -y's first.
+modorder := $(patsubst %/,%/modules.order, $(filter %/, $(obj-y)) $(obj-m:.o=.ko))
+
+__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
+subdir-y += $(__subdir-y)
+__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
+subdir-m += $(__subdir-m)
+obj-y := $(patsubst %/, %/built-in.o, $(obj-y))
+obj-m := $(filter-out %/, $(obj-m))
+
+# Subdirectories we need to descend into
+
+subdir-ym := $(sort $(subdir-y) $(subdir-m))
+
+# if $(foo-objs) exists, foo.o is a composite object
+multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
+multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
+multi-used := $(multi-used-y) $(multi-used-m)
+single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m)))
+
+# Build list of the parts of our composite objects, our composite
+# objects depend on those (obviously)
+multi-objs-y := $(foreach m, $(multi-used-y), $($(m:.o=-objs)) $($(m:.o=-y)))
+multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y)))
+multi-objs := $(multi-objs-y) $(multi-objs-m)
+
+# $(subdir-obj-y) is the list of objects in $(obj-y) which uses dir/ to
+# tell kbuild to descend
+subdir-obj-y := $(filter %/built-in.o, $(obj-y))
+
+# $(obj-dirs) is a list of directories that contain object files
+obj-dirs := $(dir $(multi-objs) $(subdir-obj-y))
+
+# Replace multi-part objects by their individual parts, look at local dir only
+real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y)
+real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
+
+# Add subdir path
+
+extra-y := $(addprefix $(obj)/,$(extra-y))
+always := $(addprefix $(obj)/,$(always))
+targets := $(addprefix $(obj)/,$(targets))
+modorder := $(addprefix $(obj)/,$(modorder))
+obj-y := $(addprefix $(obj)/,$(obj-y))
+obj-m := $(addprefix $(obj)/,$(obj-m))
+lib-y := $(addprefix $(obj)/,$(lib-y))
+subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y))
+real-objs-y := $(addprefix $(obj)/,$(real-objs-y))
+real-objs-m := $(addprefix $(obj)/,$(real-objs-m))
+single-used-m := $(addprefix $(obj)/,$(single-used-m))
+multi-used-y := $(addprefix $(obj)/,$(multi-used-y))
+multi-used-m := $(addprefix $(obj)/,$(multi-used-m))
+multi-objs-y := $(addprefix $(obj)/,$(multi-objs-y))
+multi-objs-m := $(addprefix $(obj)/,$(multi-objs-m))
+subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
+obj-dirs := $(addprefix $(obj)/,$(obj-dirs))
+
+# These flags are needed for modversions and compiling, so we define them here
+# already
+# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will
+# end up in (or would, if it gets compiled in)
+# Note: Files that end up in two or more modules are compiled without the
+# KBUILD_MODNAME definition. The reason is that any made-up name would
+# differ in different configs.
+name-fix = $(subst $(comma),_,$(subst -,_,$1))
+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)))")
+
+orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
+ $(ccflags-y) $(CFLAGS_$(basetarget).o)
+_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
+_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \
+ $(asflags-y) $(AFLAGS_$(basetarget).o)
+_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F))
+
+#
+# Enable gcov profiling flags for a file, directory or for all files depending
+# on variables GCOV_PROFILE_obj.o, GCOV_PROFILE and CONFIG_GCOV_PROFILE_ALL
+# (in this order)
+#
+ifeq ($(CONFIG_GCOV_KERNEL),y)
+_c_flags += $(if $(patsubst n%,, \
+ $(GCOV_PROFILE_$(basetarget).o)$(GCOV_PROFILE)$(CONFIG_GCOV_PROFILE_ALL)), \
+ $(CFLAGS_GCOV))
+endif
+
+ifdef CONFIG_SYMBOL_PREFIX
+_sym_flags = -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX))
+_cpp_flags += $(_sym_flags)
+_a_flags += $(_sym_flags)
+endif
+
+
+# If building the kernel in a separate objtree expand all occurrences
+# of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
+
+ifeq ($(KBUILD_SRC),)
+__c_flags = $(_c_flags)
+__a_flags = $(_a_flags)
+__cpp_flags = $(_cpp_flags)
+else
+
+# -I$(obj) locates generated .h files
+# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files
+# and locates generated .h files
+# FIXME: Replace both with specific CFLAGS* statements in the makefiles
+__c_flags = $(call addtree,-I$(obj)) $(call flags,_c_flags)
+__a_flags = $(call flags,_a_flags)
+__cpp_flags = $(call flags,_cpp_flags)
+endif
+
+c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
+ $(__c_flags) $(modkern_cflags) \
+ -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
+
+a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
+ $(__a_flags) $(modkern_aflags)
+
+cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
+ $(__cpp_flags)
+
+ld_flags = $(LDFLAGS) $(ldflags-y)
+
+dtc_cpp_flags = -Wp,-MD,$(depfile) -nostdinc \
+ -I$(srctree)/arch/$(SRCARCH)/boot/dts \
+ -I$(srctree)/arch/$(SRCARCH)/include/dts \
+ -undef -D__DTS__
+
+# Finds the multi-part object the current object will be linked into
+modname-multi = $(sort $(foreach m,$(multi-used),\
+ $(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=))))
+
+ifdef REGENERATE_PARSERS
+
+# GPERF
+# ---------------------------------------------------------------------------
+quiet_cmd_gperf = GPERF $@
+ cmd_gperf = gperf -t --output-file $@ -a -C -E -g -k 1,3,$$ -p -t $<
+
+.PRECIOUS: $(src)/%.hash.c_shipped
+$(src)/%.hash.c_shipped: $(src)/%.gperf
+ $(call cmd,gperf)
+
+# LEX
+# ---------------------------------------------------------------------------
+LEX_PREFIX = $(if $(LEX_PREFIX_${baseprereq}),$(LEX_PREFIX_${baseprereq}),yy)
+
+quiet_cmd_flex = LEX $@
+ cmd_flex = flex -o$@ -L -P $(LEX_PREFIX) $<
+
+.PRECIOUS: $(src)/%.lex.c_shipped
+$(src)/%.lex.c_shipped: $(src)/%.l
+ $(call cmd,flex)
+
+# YACC
+# ---------------------------------------------------------------------------
+YACC_PREFIX = $(if $(YACC_PREFIX_${baseprereq}),$(YACC_PREFIX_${baseprereq}),yy)
+
+quiet_cmd_bison = YACC $@
+ cmd_bison = bison -o$@ -t -l -p $(YACC_PREFIX) $<
+
+.PRECIOUS: $(src)/%.tab.c_shipped
+$(src)/%.tab.c_shipped: $(src)/%.y
+ $(call cmd,bison)
+
+quiet_cmd_bison_h = YACC $@
+ cmd_bison_h = bison -o/dev/null --defines=$@ -t -l -p $(YACC_PREFIX) $<
+
+.PRECIOUS: $(src)/%.tab.h_shipped
+$(src)/%.tab.h_shipped: $(src)/%.y
+ $(call cmd,bison_h)
+
+endif
+
+# Shipped files
+# ===========================================================================
+
+quiet_cmd_shipped = SHIPPED $@
+cmd_shipped = cat $< > $@
+
+$(obj)/%: $(src)/%_shipped
+ $(call cmd,shipped)
+
+# Commands useful for building a boot image
+# ===========================================================================
+#
+# Use as following:
+#
+# target: source(s) FORCE
+# $(if_changed,ld/objcopy/gzip)
+#
+# and add target to extra-y so that we know we have to
+# read in the saved command line
+
+# Linking
+# ---------------------------------------------------------------------------
+
+quiet_cmd_ld = LD $@
+cmd_ld = $(LD) $(LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) \
+ $(filter-out FORCE,$^) -o $@
+
+# Objcopy
+# ---------------------------------------------------------------------------
+
+quiet_cmd_objcopy = OBJCOPY $@
+cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
+
+# Gzip
+# ---------------------------------------------------------------------------
+
+quiet_cmd_gzip = GZIP $@
+cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
+ (rm -f $@ ; false)
+
+# DTC
+# ---------------------------------------------------------------------------
+
+# Generate an assembly file to wrap the output of the device tree compiler
+quiet_cmd_dt_S_dtb= DTB $@
+cmd_dt_S_dtb= \
+( \
+ echo '\#include <asm-generic/vmlinux.lds.h>'; \
+ echo '.section .dtb.init.rodata,"a"'; \
+ echo '.balign STRUCT_ALIGNMENT'; \
+ echo '.global __dtb_$(*F)_begin'; \
+ echo '__dtb_$(*F)_begin:'; \
+ echo '.incbin "$<" '; \
+ echo '__dtb_$(*F)_end:'; \
+ echo '.global __dtb_$(*F)_end'; \
+ echo '.balign STRUCT_ALIGNMENT'; \
+) > $@
+
+$(obj)/%.dtb.S: $(obj)/%.dtb
+ $(call cmd,dt_S_dtb)
+
+quiet_cmd_dtc = DTC $@
+cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile) $<
+
+$(obj)/%.dtb: $(src)/%.dts FORCE
+ $(call if_changed_dep,dtc)
+
+dtc-tmp = $(subst $(comma),_,$(dot-target).dts)
+
+quiet_cmd_dtc_cpp = DTC+CPP $@
+cmd_dtc_cpp = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
+ $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) $(dtc-tmp)
+
+$(obj)/%.dtb: $(src)/%.dtsp FORCE
+ $(call if_changed_dep,dtc_cpp)
+
+# Bzip2
+# ---------------------------------------------------------------------------
+
+# Bzip2 and LZMA do not include size in file... so we have to fake that;
+# append the size as a 32-bit littleendian number as gzip does.
+size_append = printf $(shell \
+dec_size=0; \
+for F in $1; do \
+ fsize=$$(stat -c "%s" $$F); \
+ dec_size=$$(expr $$dec_size + $$fsize); \
+done; \
+printf "%08x\n" $$dec_size | \
+ sed 's/\(..\)/\1 /g' | { \
+ read ch0 ch1 ch2 ch3; \
+ for ch in $$ch3 $$ch2 $$ch1 $$ch0; do \
+ printf '%s%03o' '\\' $$((0x$$ch)); \
+ done; \
+ } \
+)
+
+quiet_cmd_bzip2 = BZIP2 $@
+cmd_bzip2 = (cat $(filter-out FORCE,$^) | \
+ bzip2 -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ (rm -f $@ ; false)
+
+# Lzma
+# ---------------------------------------------------------------------------
+
+quiet_cmd_lzma = LZMA $@
+cmd_lzma = (cat $(filter-out FORCE,$^) | \
+ lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ (rm -f $@ ; false)
+
+quiet_cmd_lzo = LZO $@
+cmd_lzo = (cat $(filter-out FORCE,$^) | \
+ lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ (rm -f $@ ; false)
+
+# U-Boot mkimage
+# ---------------------------------------------------------------------------
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+# SRCARCH just happens to match slightly more than ARCH (on sparc), so reduces
+# the number of overrides in arch makefiles
+UIMAGE_ARCH ?= $(SRCARCH)
+UIMAGE_COMPRESSION ?= $(if $(2),$(2),none)
+UIMAGE_OPTS-y ?=
+UIMAGE_TYPE ?= kernel
+UIMAGE_LOADADDR ?= arch_must_set_this
+UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR)
+UIMAGE_NAME ?= 'Linux-$(KERNELRELEASE)'
+UIMAGE_IN ?= $<
+UIMAGE_OUT ?= $@
+
+quiet_cmd_uimage = UIMAGE $(UIMAGE_OUT)
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \
+ -C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \
+ -T $(UIMAGE_TYPE) \
+ -a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \
+ -n $(UIMAGE_NAME) -d $(UIMAGE_IN) $(UIMAGE_OUT)
+
+# XZ
+# ---------------------------------------------------------------------------
+# Use xzkern to compress the kernel image and xzmisc to compress other things.
+#
+# xzkern uses a big LZMA2 dictionary since it doesn't increase memory usage
+# of the kernel decompressor. A BCJ filter is used if it is available for
+# the target architecture. xzkern also appends uncompressed size of the data
+# using size_append. The .xz format has the size information available at
+# the end of the file too, but it's in more complex format and it's good to
+# avoid changing the part of the boot code that reads the uncompressed size.
+# Note that the bytes added by size_append will make the xz tool think that
+# the file is corrupt. This is expected.
+#
+# xzmisc doesn't use size_append, so it can be used to create normal .xz
+# files. xzmisc uses smaller LZMA2 dictionary than xzkern, because a very
+# big dictionary would increase the memory usage too much in the multi-call
+# decompression mode. A BCJ filter isn't used either.
+quiet_cmd_xzkern = XZKERN $@
+cmd_xzkern = (cat $(filter-out FORCE,$^) | \
+ sh $(srctree)/scripts/xz_wrap.sh && \
+ $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ (rm -f $@ ; false)
+
+quiet_cmd_xzmisc = XZMISC $@
+cmd_xzmisc = (cat $(filter-out FORCE,$^) | \
+ xz --check=crc32 --lzma2=dict=1MiB) > $@ || \
+ (rm -f $@ ; false)
+
+# misc stuff
+# ---------------------------------------------------------------------------
+quote:="
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
new file mode 100644
index 0000000..cf82c83
--- /dev/null
+++ b/scripts/Makefile.modpost
@@ -0,0 +1,148 @@
+# ===========================================================================
+# Module versions
+# ===========================================================================
+#
+# Stage one of module building created the following:
+# a) The individual .o files used for the module
+# b) A <module>.o file which is the .o files above linked together
+# c) A <module>.mod file in $(MODVERDIR)/, listing the name of the
+# the preliminary <module>.o file, plus all .o files
+
+# Stage 2 is handled by this file and does the following
+# 1) Find all modules from the files listed in $(MODVERDIR)/
+# 2) modpost is then used to
+# 3) create one <module>.mod.c file pr. module
+# 4) create one Module.symvers file with CRC for all exported symbols
+# 5) compile all <module>.mod.c files
+# 6) final link of the module to a <module.ko> file
+
+# Step 3 is used to place certain information in the module's ELF
+# section, including information such as:
+# Version magic (see include/linux/vermagic.h for full details)
+# - Kernel release
+# - SMP is CONFIG_SMP
+# - PREEMPT is CONFIG_PREEMPT
+# - GCC Version
+# Module info
+# - Module version (MODULE_VERSION)
+# - Module alias'es (MODULE_ALIAS)
+# - Module license (MODULE_LICENSE)
+# - See include/linux/module.h for more details
+
+# Step 4 is solely used to allow module versioning in external modules,
+# where the CRC of each module is retrieved from the Module.symvers file.
+
+# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
+# symbols in the final module linking stage
+# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
+# This is solely useful to speed up test compiles
+PHONY := _modpost
+_modpost: __modpost
+
+include include/config/auto.conf
+include scripts/Kbuild.include
+
+# When building external modules load the Kbuild file to retrieve EXTRA_SYMBOLS info
+ifneq ($(KBUILD_EXTMOD),)
+
+# set src + obj - they may be used when building the .mod.c file
+obj := $(KBUILD_EXTMOD)
+src := $(obj)
+
+# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
+include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
+ $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
+endif
+
+include scripts/Makefile.lib
+
+kernelsymfile := $(objtree)/Module.symvers
+modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
+
+# Step 1), find all modules listed in $(MODVERDIR)/
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
+
+# Stop after building .o files if NOFINAL is set. Makes compile tests quicker
+_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
+
+# Step 2), invoke modpost
+# Includes step 3,4
+modpost = scripts/mod/modpost \
+ $(if $(CONFIG_MODVERSIONS),-m) \
+ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \
+ $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
+ $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
+ $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
+ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
+ $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
+ $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
+
+quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
+ cmd_modpost = $(modpost) -s
+
+PHONY += __modpost
+__modpost: $(modules:.ko=.o) FORCE
+ $(call cmd,modpost) $(wildcard vmlinux) $(filter-out FORCE,$^)
+
+quiet_cmd_kernel-mod = MODPOST $@
+ cmd_kernel-mod = $(modpost) $@
+
+vmlinux.o: FORCE
+ $(call cmd,kernel-mod)
+
+# Declare generated files as targets for modpost
+$(symverfile): __modpost ;
+$(modules:.ko=.mod.c): __modpost ;
+
+
+# Step 5), compile all *.mod.c files
+
+# modname is set to make c_flags define KBUILD_MODNAME
+modname = $(notdir $(@:.mod.o=))
+
+quiet_cmd_cc_o_c = CC $@
+ cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \
+ -c -o $@ $<
+
+$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
+ $(call if_changed_dep,cc_o_c)
+
+targets += $(modules:.ko=.mod.o)
+
+# Step 6), final link of the modules
+quiet_cmd_ld_ko_o = LD [M] $@
+ cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \
+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+ -o $@ $(filter-out FORCE,$^)
+
+$(modules): %.ko :%.o %.mod.o FORCE
+ $(call if_changed,ld_ko_o)
+
+targets += $(modules)
+
+
+# Add FORCE to the prequisites of a target to force it to be always rebuilt.
+# ---------------------------------------------------------------------------
+
+PHONY += FORCE
+
+FORCE:
+
+# Read all saved command lines and dependencies for the $(targets) we
+# may be building above, using $(if_changed{,_dep}). As an
+# optimization, we don't need to read them if the target does not
+# exist, we will rebuild anyway in that case.
+
+targets := $(wildcard $(sort $(targets)))
+cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
+
+ifneq ($(cmd_files),)
+ include $(cmd_files)
+endif
+
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
diff --git a/scripts/basic/.gitignore b/scripts/basic/.gitignore
new file mode 100644
index 0000000..a776371
--- /dev/null
+++ b/scripts/basic/.gitignore
@@ -0,0 +1 @@
+fixdep
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
new file mode 100644
index 0000000..4fcef87
--- /dev/null
+++ b/scripts/basic/Makefile
@@ -0,0 +1,15 @@
+###
+# Makefile.basic lists the most basic programs used during the build process.
+# The programs listed herein are what are needed to do the basic stuff,
+# such as fix file dependencies.
+# 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
+
+hostprogs-y := fixdep
+always := $(hostprogs-y)
+
+# fixdep is needed to compile other host programs
+$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
new file mode 100644
index 0000000..7f6425e
--- /dev/null
+++ b/scripts/basic/fixdep.c
@@ -0,0 +1,433 @@
+/*
+ * "Optimize" a list of dependencies as spit out by gcc -MD
+ * for the kernel build
+ * ===========================================================================
+ *
+ * Author Kai Germaschewski
+ * Copyright 2002 by Kai Germaschewski <kai.germaschewski at gmx.de>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ *
+ * Introduction:
+ *
+ * gcc produces a very nice and correct list of dependencies which
+ * tells make when to remake a file.
+ *
+ * To use this list as-is however has the drawback that virtually
+ * every file in the kernel includes autoconf.h.
+ *
+ * If the user re-runs make *config, autoconf.h will be
+ * regenerated. make notices that and will rebuild every file which
+ * includes autoconf.h, i.e. basically all files. This is extremely
+ * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
+ *
+ * So we play the same trick that "mkdep" played before. We replace
+ * the dependency on autoconf.h by a dependency on every config
+ * option which is mentioned in any of the listed prequisites.
+ *
+ * kconfig populates a tree in include/config/ with an empty file
+ * for each config symbol and when the configuration is updated
+ * the files representing changed config options are touched
+ * which then let make pick up the changes and the files that use
+ * the config symbols are rebuilt.
+ *
+ * So if the user changes his CONFIG_HIS_DRIVER option, only the objects
+ * which depend on "include/linux/config/his/driver.h" will be rebuilt,
+ * so most likely only his driver ;-)
+ *
+ * The idea above dates, by the way, back to Michael E Chastain, AFAIK.
+ *
+ * So to get dependencies right, there are two issues:
+ * o if any of the files the compiler read changed, we need to rebuild
+ * o if the command line given to the compile the file changed, we
+ * better rebuild as well.
+ *
+ * The former is handled by using the -MD output, the later by saving
+ * the command line used to compile the old object and comparing it
+ * to the one we would now use.
+ *
+ * Again, also this idea is pretty old and has been discussed on
+ * kbuild-devel a long time ago. I don't have a sensibly working
+ * internet connection right now, so I rather don't mention names
+ * without double checking.
+ *
+ * This code here has been based partially based on mkdep.c, which
+ * says the following about its history:
+ *
+ * Copyright abandoned, Michael Chastain, <mailto:mec at shout.net>.
+ * This is a C version of syncdep.pl by Werner Almesberger.
+ *
+ *
+ * It is invoked as
+ *
+ * fixdep <depfile> <target> <cmdline>
+ *
+ * and will read the dependency file <depfile>
+ *
+ * The transformed dependency snipped is written to stdout.
+ *
+ * It first generates a line
+ *
+ * cmd_<target> = <cmdline>
+ *
+ * and then basically copies the .<target>.d file to stdout, in the
+ * process filtering out the dependency on autoconf.h and adding
+ * dependencies on include/config/my/option.h for every
+ * CONFIG_MY_OPTION encountered in any of the prequisites.
+ *
+ * It will also filter out all the dependencies on *.ver. We need
+ * to make sure that the generated version checksum are globally up
+ * to date before even starting the recursive build, so it's too late
+ * at this point anyway.
+ *
+ * The algorithm to grep for "CONFIG_..." is bit unusual, but should
+ * be fast ;-) We don't even try to really parse the header files, but
+ * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
+ * be picked up as well. It's not a problem with respect to
+ * correctness, since that can only give too many dependencies, thus
+ * we cannot miss a rebuild. Since people tend to not mention totally
+ * unrelated CONFIG_ options all over the place, it's not an
+ * efficiency problem either.
+ *
+ * (Note: it'd be easy to port over the complete mkdep state machine,
+ * but I don't think the added complexity is worth it)
+ */
+/*
+ * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto
+ * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not
+ * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as
+ * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h,
+ * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that
+ * those files will have correct dependencies.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <ctype.h>
+#include <arpa/inet.h>
+
+#define INT_CONF ntohl(0x434f4e46)
+#define INT_ONFI ntohl(0x4f4e4649)
+#define INT_NFIG ntohl(0x4e464947)
+#define INT_FIG_ ntohl(0x4649475f)
+
+char *target;
+char *depfile;
+char *cmdline;
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
+ exit(1);
+}
+
+/*
+ * Print out the commandline prefixed with cmd_<target filename> :=
+ */
+static void print_cmdline(void)
+{
+ printf("cmd_%s := %s\n\n", target, cmdline);
+}
+
+struct item {
+ struct item *next;
+ unsigned int len;
+ unsigned int hash;
+ char name[0];
+};
+
+#define HASHSZ 256
+static struct item *hashtab[HASHSZ];
+
+static unsigned int strhash(const char *str, unsigned int sz)
+{
+ /* fnv32 hash */
+ unsigned int i, hash = 2166136261U;
+
+ for (i = 0; i < sz; i++)
+ hash = (hash ^ str[i]) * 0x01000193;
+ return hash;
+}
+
+/*
+ * Lookup a value in the configuration string.
+ */
+static int is_defined_config(const char *name, int len, unsigned int hash)
+{
+ struct item *aux;
+
+ for (aux = hashtab[hash % HASHSZ]; aux; aux = aux->next) {
+ if (aux->hash == hash && aux->len == len &&
+ memcmp(aux->name, name, len) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Add a new value to the configuration string.
+ */
+static void define_config(const char *name, int len, unsigned int hash)
+{
+ struct item *aux = malloc(sizeof(*aux) + len);
+
+ if (!aux) {
+ perror("fixdep:malloc");
+ exit(1);
+ }
+ memcpy(aux->name, name, len);
+ aux->len = len;
+ aux->hash = hash;
+ aux->next = hashtab[hash % HASHSZ];
+ hashtab[hash % HASHSZ] = aux;
+}
+
+/*
+ * Clear the set of configuration strings.
+ */
+static void clear_config(void)
+{
+ struct item *aux, *next;
+ unsigned int i;
+
+ for (i = 0; i < HASHSZ; i++) {
+ for (aux = hashtab[i]; aux; aux = next) {
+ next = aux->next;
+ free(aux);
+ }
+ hashtab[i] = NULL;
+ }
+}
+
+/*
+ * Record the use of a CONFIG_* word.
+ */
+static void use_config(const char *m, int slen)
+{
+ unsigned int hash = strhash(m, slen);
+ int c, i;
+
+ if (is_defined_config(m, slen, hash))
+ return;
+
+ define_config(m, slen, hash);
+
+ printf(" $(wildcard include/config/");
+ for (i = 0; i < slen; i++) {
+ c = m[i];
+ if (c == '_')
+ c = '/';
+ else
+ c = tolower(c);
+ putchar(c);
+ }
+ printf(".h) \\\n");
+}
+
+static void parse_config_file(const char *map, size_t len)
+{
+ const int *end = (const int *) (map + len);
+ /* start at +1, so that p can never be < map */
+ const int *m = (const int *) map + 1;
+ const char *p, *q;
+
+ for (; m < end; m++) {
+ if (*m == INT_CONF) { p = (char *) m ; goto conf; }
+ if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
+ if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
+ if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
+ continue;
+ conf:
+ if (p > map + len - 7)
+ continue;
+ if (memcmp(p, "CONFIG_", 7))
+ continue;
+ for (q = p + 7; q < map + len; q++) {
+ if (!(isalnum(*q) || *q == '_'))
+ goto found;
+ }
+ continue;
+
+ found:
+ if (!memcmp(q - 7, "_MODULE", 7))
+ q -= 7;
+ if( (q-p-7) < 0 )
+ continue;
+ use_config(p+7, q-p-7);
+ }
+}
+
+/* test is s ends in sub */
+static int strrcmp(char *s, char *sub)
+{
+ int slen = strlen(s);
+ int sublen = strlen(sub);
+
+ if (sublen > slen)
+ return 1;
+
+ return memcmp(s + slen - sublen, sub, sublen);
+}
+
+static void do_config_file(const char *filename)
+{
+ struct stat st;
+ int fd;
+ void *map;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "fixdep: error opening config file: ");
+ perror(filename);
+ exit(2);
+ }
+ fstat(fd, &st);
+ if (st.st_size == 0) {
+ close(fd);
+ return;
+ }
+ map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if ((long) map == -1) {
+ perror("fixdep: mmap");
+ close(fd);
+ return;
+ }
+
+ parse_config_file(map, st.st_size);
+
+ munmap(map, st.st_size);
+
+ close(fd);
+}
+
+/*
+ * Important: The below generated source_foo.o and deps_foo.o variable
+ * assignments are parsed not only by make, but also by the rather simple
+ * parser in scripts/mod/sumversion.c.
+ */
+static void parse_dep_file(void *map, size_t len)
+{
+ char *m = map;
+ char *end = m + len;
+ char *p;
+ char s[PATH_MAX];
+ int first;
+
+ p = strchr(m, ':');
+ if (!p) {
+ fprintf(stderr, "fixdep: parse error\n");
+ exit(1);
+ }
+ memcpy(s, m, p-m); s[p-m] = 0;
+ m = p+1;
+
+ clear_config();
+
+ first = 1;
+ while (m < end) {
+ while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
+ m++;
+ p = m;
+ while (p < end && *p != ' ') p++;
+ if (p == end) {
+ do p--; while (!isalnum(*p));
+ p++;
+ }
+ memcpy(s, m, p-m); s[p-m] = 0;
+ if (strrcmp(s, "include/generated/autoconf.h") &&
+ strrcmp(s, "arch/um/include/uml-config.h") &&
+ strrcmp(s, "include/linux/kconfig.h") &&
+ strrcmp(s, ".ver")) {
+ /*
+ * Do not list the source file as dependency, so that
+ * kbuild is not confused if a .c file is rewritten
+ * into .S or vice versa. Storing it in source_* is
+ * needed for modpost to compute srcversions.
+ */
+ if (first) {
+ printf("source_%s := %s\n\n", target, s);
+ printf("deps_%s := \\\n", target);
+ } else
+ printf(" %s \\\n", s);
+ do_config_file(s);
+ }
+ first = 0;
+ m = p + 1;
+ }
+ printf("\n%s: $(deps_%s)\n\n", target, target);
+ printf("$(deps_%s):\n", target);
+}
+
+static void print_deps(void)
+{
+ struct stat st;
+ int fd;
+ void *map;
+
+ fd = open(depfile, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "fixdep: error opening depfile: ");
+ perror(depfile);
+ exit(2);
+ }
+ if (fstat(fd, &st) < 0) {
+ fprintf(stderr, "fixdep: error fstat'ing depfile: ");
+ perror(depfile);
+ exit(2);
+ }
+ if (st.st_size == 0) {
+ fprintf(stderr,"fixdep: %s is empty\n",depfile);
+ close(fd);
+ return;
+ }
+ map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if ((long) map == -1) {
+ perror("fixdep: mmap");
+ close(fd);
+ return;
+ }
+
+ parse_dep_file(map, st.st_size);
+
+ munmap(map, st.st_size);
+
+ close(fd);
+}
+
+static void traps(void)
+{
+ static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
+ int *p = (int *)test;
+
+ if (*p != INT_CONF) {
+ fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianness? %#x\n",
+ *p);
+ exit(2);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ traps();
+
+ if (argc != 4)
+ usage();
+
+ depfile = argv[1];
+ target = argv[2];
+ cmdline = argv[3];
+
+ print_cmdline();
+ print_deps();
+
+ return 0;
+}
diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh
new file mode 100644
index 0000000..a2af2e8
--- /dev/null
+++ b/scripts/gcc-goto.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+# Test for gcc 'asm goto' support
+# Copyright (C) 2010, Jason Baron <jbaron at redhat.com>
+
+cat << "END" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
+int main(void)
+{
+#ifdef __arm__
+ /*
+ * Not related to asm goto, but used by jump label
+ * and broken on some ARM GCC versions (see GCC Bug 48637).
+ */
+ static struct { int dummy; int state; } tp;
+ asm (".long %c0" :: "i" (&tp.state));
+#endif
+
+entry:
+ asm goto ("" :::: entry);
+ return 0;
+}
+END
diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
new file mode 100644
index 0000000..be603c4
--- /dev/null
+++ b/scripts/kconfig/.gitignore
@@ -0,0 +1,22 @@
+#
+# Generated files
+#
+config*
+*.lex.c
+*.tab.c
+*.tab.h
+zconf.hash.c
+*.moc
+gconf.glade.h
+*.pot
+*.mo
+
+#
+# configuration programs
+#
+conf
+mconf
+nconf
+qconf
+gconf
+kxgettext
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
new file mode 100644
index 0000000..bd9b673
--- /dev/null
+++ b/scripts/kconfig/Makefile
@@ -0,0 +1,325 @@
+# ===========================================================================
+# Kernel configuration targets
+# These targets are used from top-level makefile
+
+PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \
+ localmodconfig localyesconfig kvmconfig
+
+ifdef KBUILD_KCONFIG
+Kconfig := $(KBUILD_KCONFIG)
+else
+Kconfig := Kconfig
+endif
+
+# We need this, in case the user has it in its environment
+unexport CONFIG_
+
+xconfig: $(obj)/qconf
+ $< $(Kconfig)
+
+gconfig: $(obj)/gconf
+ $< $(Kconfig)
+
+menuconfig: $(obj)/mconf
+ $< $(Kconfig)
+
+config: $(obj)/conf
+ $< --oldaskconfig $(Kconfig)
+
+nconfig: $(obj)/nconf
+ $< $(Kconfig)
+
+oldconfig: $(obj)/conf
+ $< --$@ $(Kconfig)
+
+silentoldconfig: $(obj)/conf
+ $(Q)mkdir -p include/generated
+ $< --$@ $(Kconfig)
+
+kvmconfig:
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/config -e KVMTOOL_TEST_ENABLE
+ $(Q)yes "" | make oldconfig > /dev/null
+ @echo 'Kernel configuration modified to run as KVM guest.'
+
+localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
+ $(Q)mkdir -p include/generated
+ $(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
+ $(Q)if [ -f .config ]; then \
+ cmp -s .tmp.config .config || \
+ (mv -f .config .config.old.1; \
+ mv -f .tmp.config .config; \
+ $(obj)/conf --silentoldconfig $(Kconfig); \
+ mv -f .config.old.1 .config.old) \
+ else \
+ mv -f .tmp.config .config; \
+ $(obj)/conf --silentoldconfig $(Kconfig); \
+ fi
+ $(Q)rm -f .tmp.config
+
+# Create new linux.pot file
+# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files
+update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
+ $(Q)echo " GEN config.pot"
+ $(Q)xgettext --default-domain=linux \
+ --add-comments --keyword=_ --keyword=N_ \
+ --from-code=UTF-8 \
+ --files-from=$(srctree)/scripts/kconfig/POTFILES.in \
+ --directory=$(srctree) --directory=$(objtree) \
+ --output $(obj)/config.pot
+ $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot
+ $(Q)(for i in `ls $(srctree)/arch/*/Kconfig \
+ $(srctree)/arch/*/um/Kconfig`; \
+ do \
+ echo " GEN $$i"; \
+ $(obj)/kxgettext $$i \
+ >> $(obj)/config.pot; \
+ done )
+ $(Q)echo " GEN linux.pot"
+ $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \
+ --output $(obj)/linux.pot
+ $(Q)rm -f $(obj)/config.pot
+
+PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
+
+allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
+ $< --$@ $(Kconfig)
+
+PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig
+
+listnewconfig olddefconfig: $(obj)/conf
+ $< --$@ $(Kconfig)
+
+# oldnoconfig is an alias of olddefconfig, because people already are dependent
+# on its behavior(sets new symbols to their default value but not 'n') with the
+# counter-intuitive name.
+oldnoconfig: $(obj)/conf
+ $< --olddefconfig $(Kconfig)
+
+savedefconfig: $(obj)/conf
+ $< --$@=defconfig $(Kconfig)
+
+defconfig: $(obj)/conf
+ifeq ($(KBUILD_DEFCONFIG),)
+ $< --defconfig $(Kconfig)
+else
+ @echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
+ $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
+endif
+
+%_defconfig: $(obj)/conf
+ $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
+
+# Help text used by make help
+help:
+ @echo ' config - Update current config utilising a line-oriented program'
+ @echo ' nconfig - Update current config utilising a ncurses menu based program'
+ @echo ' menuconfig - Update current config utilising a menu based program'
+ @echo ' xconfig - Update current config utilising a QT based front-end'
+ @echo ' gconfig - Update current config utilising a GTK based front-end'
+ @echo ' oldconfig - Update current config utilising a provided .config as base'
+ @echo ' localmodconfig - Update current config disabling modules not loaded'
+ @echo ' localyesconfig - Update current config converting local mods to core'
+ @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps'
+ @echo ' defconfig - New config with default from ARCH supplied defconfig'
+ @echo ' savedefconfig - Save current config as ./defconfig (minimal config)'
+ @echo ' allnoconfig - New config where all options are answered with no'
+ @echo ' allyesconfig - New config where all options are accepted with yes'
+ @echo ' allmodconfig - New config selecting modules when possible'
+ @echo ' alldefconfig - New config with all symbols set to default'
+ @echo ' randconfig - New config with random answer to all options'
+ @echo ' listnewconfig - List new options'
+ @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value'
+
+# lxdialog stuff
+check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
+
+# Use recursively expanded variables so we do not call gcc unless
+# we really need to do so. (Do not call gcc as part of make mrproper)
+HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
+ -DLOCALE
+
+# ===========================================================================
+# Shared Makefile for the various kconfig executables:
+# conf: Used for defconfig, oldconfig and related targets
+# nconf: Used for the nconfig target.
+# Utilizes ncurses
+# mconf: Used for the menuconfig target
+# Utilizes the lxdialog package
+# qconf: Used for the xconfig target
+# Based on QT which needs to be installed to compile it
+# gconf: Used for the gconfig target
+# Based on GTK which needs to be installed to compile it
+# object files used by all kconfig flavours
+
+lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
+lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
+
+conf-objs := conf.o zconf.tab.o
+mconf-objs := mconf.o zconf.tab.o $(lxdialog)
+nconf-objs := nconf.o zconf.tab.o nconf.gui.o
+kxgettext-objs := kxgettext.o zconf.tab.o
+qconf-cxxobjs := qconf.o
+qconf-objs := zconf.tab.o
+gconf-objs := gconf.o zconf.tab.o
+
+hostprogs-y := conf
+
+ifeq ($(MAKECMDGOALS),nconfig)
+ hostprogs-y += nconf
+endif
+
+ifeq ($(MAKECMDGOALS),menuconfig)
+ hostprogs-y += mconf
+endif
+
+ifeq ($(MAKECMDGOALS),update-po-config)
+ hostprogs-y += kxgettext
+endif
+
+ifeq ($(MAKECMDGOALS),xconfig)
+ qconf-target := 1
+endif
+ifeq ($(MAKECMDGOALS),gconfig)
+ gconf-target := 1
+endif
+
+
+ifeq ($(qconf-target),1)
+ hostprogs-y += qconf
+endif
+
+ifeq ($(gconf-target),1)
+ hostprogs-y += gconf
+endif
+
+clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck
+clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h
+clean-files += mconf qconf gconf nconf
+clean-files += config.pot linux.pot
+
+# Check that we have the required ncurses stuff installed for lxdialog (menuconfig)
+PHONY += $(obj)/dochecklxdialog
+$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog
+$(obj)/dochecklxdialog:
+ $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf)
+
+always := dochecklxdialog
+
+# Add environment specific flags
+HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS))
+
+# generated files seem to need this to find local include files
+HOSTCFLAGS_zconf.lex.o := -I$(src)
+HOSTCFLAGS_zconf.tab.o := -I$(src)
+
+LEX_PREFIX_zconf := zconf
+YACC_PREFIX_zconf := zconf
+
+HOSTLOADLIBES_qconf = $(KC_QT_LIBS)
+HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS)
+
+HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
+HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
+ -Wno-missing-prototypes
+
+HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
+
+HOSTLOADLIBES_nconf = -lmenu -lpanel -lncurses
+$(obj)/qconf.o: $(obj)/.tmp_qtcheck
+
+ifeq ($(qconf-target),1)
+$(obj)/.tmp_qtcheck: $(src)/Makefile
+-include $(obj)/.tmp_qtcheck
+
+# QT needs some extra effort...
+$(obj)/.tmp_qtcheck:
+ @set -e; echo " CHECK qt"; dir=""; pkg=""; \
+ if ! pkg-config --exists QtCore 2> /dev/null; then \
+ echo "* Unable to find the QT4 tool qmake. Trying to use QT3"; \
+ pkg-config --exists qt 2> /dev/null && pkg=qt; \
+ pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \
+ if [ -n "$$pkg" ]; then \
+ cflags="\$$(shell pkg-config $$pkg --cflags)"; \
+ libs="\$$(shell pkg-config $$pkg --libs)"; \
+ moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \
+ dir="$$(pkg-config $$pkg --variable=prefix)"; \
+ else \
+ for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \
+ if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
+ done; \
+ if [ -z "$$dir" ]; then \
+ echo >&2 "*"; \
+ echo >&2 "* Unable to find any QT installation. Please make sure that"; \
+ echo >&2 "* the QT4 or QT3 development package is correctly installed and"; \
+ echo >&2 "* either qmake can be found or install pkg-config or set"; \
+ echo >&2 "* the QTDIR environment variable to the correct location."; \
+ echo >&2 "*"; \
+ false; \
+ fi; \
+ libpath=$$dir/lib; lib=qt; osdir=""; \
+ $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \
+ osdir=x$$($(HOSTCXX) -print-multi-os-directory); \
+ test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \
+ test -f $$libpath/libqt-mt.so && lib=qt-mt; \
+ cflags="-I$$dir/include"; \
+ libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \
+ moc="$$dir/bin/moc"; \
+ fi; \
+ if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \
+ echo "*"; \
+ echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \
+ echo "*"; \
+ moc="/usr/bin/moc"; \
+ fi; \
+ else \
+ cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \
+ libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \
+ moc="\$$(shell pkg-config QtCore --variable=moc_location)"; \
+ [ -n "$$moc" ] || moc="\$$(shell pkg-config QtCore --variable=prefix)/bin/moc"; \
+ fi; \
+ echo "KC_QT_CFLAGS=$$cflags" > $@; \
+ echo "KC_QT_LIBS=$$libs" >> $@; \
+ echo "KC_QT_MOC=$$moc" >> $@
+endif
+
+$(obj)/gconf.o: $(obj)/.tmp_gtkcheck
+
+ifeq ($(gconf-target),1)
+-include $(obj)/.tmp_gtkcheck
+
+# GTK needs some extra effort, too...
+$(obj)/.tmp_gtkcheck:
+ @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \
+ if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \
+ touch $@; \
+ else \
+ echo >&2 "*"; \
+ echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \
+ echo >&2 "*"; \
+ false; \
+ fi \
+ else \
+ echo >&2 "*"; \
+ echo >&2 "* Unable to find the GTK+ installation. Please make sure that"; \
+ echo >&2 "* the GTK+ 2.0 development package is correctly installed..."; \
+ echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \
+ echo >&2 "*"; \
+ false; \
+ fi
+endif
+
+$(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c
+
+$(obj)/qconf.o: $(obj)/qconf.moc
+
+quiet_cmd_moc = MOC $@
+ cmd_moc = $(KC_QT_MOC) -i $< -o $@
+
+$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck
+ $(call cmd,moc)
+
+# Extract gconf menu items for I18N support
+$(obj)/gconf.glade.h: $(obj)/gconf.glade
+ $(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \
+ $(obj)/gconf.glade
+
diff --git a/scripts/kconfig/POTFILES.in b/scripts/kconfig/POTFILES.in
new file mode 100644
index 0000000..9674573
--- /dev/null
+++ b/scripts/kconfig/POTFILES.in
@@ -0,0 +1,12 @@
+scripts/kconfig/lxdialog/checklist.c
+scripts/kconfig/lxdialog/inputbox.c
+scripts/kconfig/lxdialog/menubox.c
+scripts/kconfig/lxdialog/textbox.c
+scripts/kconfig/lxdialog/util.c
+scripts/kconfig/lxdialog/yesno.c
+scripts/kconfig/mconf.c
+scripts/kconfig/conf.c
+scripts/kconfig/confdata.c
+scripts/kconfig/gconf.c
+scripts/kconfig/gconf.glade.h
+scripts/kconfig/qconf.cc
diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh
new file mode 100755
index 0000000..854d9c7
--- /dev/null
+++ b/scripts/kconfig/check.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Needed for systems without gettext
+$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
+#include <libintl.h>
+int main()
+{
+ gettext("");
+ return 0;
+}
+EOF
+if [ ! "$?" -eq "0" ]; then
+ echo -DKBUILD_NO_NLS;
+fi
+
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
new file mode 100644
index 0000000..4da3b4a
--- /dev/null
+++ b/scripts/kconfig/conf.c
@@ -0,0 +1,701 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <locale.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include "lkc.h"
+
+static void conf(struct menu *menu);
+static void check_conf(struct menu *menu);
+static void xfgets(char *str, int size, FILE *in);
+
+enum input_mode {
+ oldaskconfig,
+ silentoldconfig,
+ oldconfig,
+ allnoconfig,
+ allyesconfig,
+ allmodconfig,
+ alldefconfig,
+ randconfig,
+ defconfig,
+ savedefconfig,
+ listnewconfig,
+ olddefconfig,
+} input_mode = oldaskconfig;
+
+static int indent = 1;
+static int valid_stdin = 1;
+static int sync_kconfig;
+static int conf_cnt;
+static char line[128];
+static struct menu *rootEntry;
+
+static void print_help(struct menu *menu)
+{
+ struct gstr help = str_new();
+
+ menu_get_ext_help(menu, &help);
+
+ printf("\n%s\n", str_get(&help));
+ str_free(&help);
+}
+
+static void strip(char *str)
+{
+ char *p = str;
+ int l;
+
+ while ((isspace(*p)))
+ p++;
+ l = strlen(p);
+ if (p != str)
+ memmove(str, p, l + 1);
+ if (!l)
+ return;
+ p = str + l - 1;
+ while ((isspace(*p)))
+ *p-- = 0;
+}
+
+static void check_stdin(void)
+{
+ if (!valid_stdin) {
+ printf(_("aborted!\n\n"));
+ printf(_("Console input/output is redirected. "));
+ printf(_("Run 'make oldconfig' to update configuration.\n\n"));
+ exit(1);
+ }
+}
+
+static int conf_askvalue(struct symbol *sym, const char *def)
+{
+ enum symbol_type type = sym_get_type(sym);
+
+ if (!sym_has_value(sym))
+ printf(_("(NEW) "));
+
+ line[0] = '\n';
+ line[1] = 0;
+
+ if (!sym_is_changable(sym)) {
+ printf("%s\n", def);
+ line[0] = '\n';
+ line[1] = 0;
+ return 0;
+ }
+
+ switch (input_mode) {
+ case oldconfig:
+ case silentoldconfig:
+ if (sym_has_value(sym)) {
+ printf("%s\n", def);
+ return 0;
+ }
+ check_stdin();
+ /* fall through */
+ case oldaskconfig:
+ fflush(stdout);
+ xfgets(line, 128, stdin);
+ return 1;
+ default:
+ break;
+ }
+
+ switch (type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ printf("%s\n", def);
+ return 1;
+ default:
+ ;
+ }
+ printf("%s", line);
+ return 1;
+}
+
+static int conf_string(struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ const char *def;
+
+ while (1) {
+ printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
+ printf("(%s) ", sym->name);
+ def = sym_get_string_value(sym);
+ if (sym_get_string_value(sym))
+ printf("[%s] ", def);
+ if (!conf_askvalue(sym, def))
+ return 0;
+ switch (line[0]) {
+ case '\n':
+ break;
+ case '?':
+ /* print help */
+ if (line[1] == '\n') {
+ print_help(menu);
+ def = NULL;
+ break;
+ }
+ /* fall through */
+ default:
+ line[strlen(line)-1] = 0;
+ def = line;
+ }
+ if (def && sym_set_string_value(sym, def))
+ return 0;
+ }
+}
+
+static int conf_sym(struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ tristate oldval, newval;
+
+ while (1) {
+ printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
+ if (sym->name)
+ printf("(%s) ", sym->name);
+ putchar('[');
+ oldval = sym_get_tristate_value(sym);
+ switch (oldval) {
+ case no:
+ putchar('N');
+ break;
+ case mod:
+ putchar('M');
+ break;
+ case yes:
+ putchar('Y');
+ break;
+ }
+ if (oldval != no && sym_tristate_within_range(sym, no))
+ printf("/n");
+ if (oldval != mod && sym_tristate_within_range(sym, mod))
+ printf("/m");
+ if (oldval != yes && sym_tristate_within_range(sym, yes))
+ printf("/y");
+ if (menu_has_help(menu))
+ printf("/?");
+ printf("] ");
+ if (!conf_askvalue(sym, sym_get_string_value(sym)))
+ return 0;
+ strip(line);
+
+ switch (line[0]) {
+ case 'n':
+ case 'N':
+ newval = no;
+ if (!line[1] || !strcmp(&line[1], "o"))
+ break;
+ continue;
+ case 'm':
+ case 'M':
+ newval = mod;
+ if (!line[1])
+ break;
+ continue;
+ case 'y':
+ case 'Y':
+ newval = yes;
+ if (!line[1] || !strcmp(&line[1], "es"))
+ break;
+ continue;
+ case 0:
+ newval = oldval;
+ break;
+ case '?':
+ goto help;
+ default:
+ continue;
+ }
+ if (sym_set_tristate_value(sym, newval))
+ return 0;
+help:
+ print_help(menu);
+ }
+}
+
+static int conf_choice(struct menu *menu)
+{
+ struct symbol *sym, *def_sym;
+ struct menu *child;
+ bool is_new;
+
+ sym = menu->sym;
+ is_new = !sym_has_value(sym);
+ if (sym_is_changable(sym)) {
+ conf_sym(menu);
+ sym_calc_value(sym);
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ return 1;
+ case mod:
+ return 0;
+ case yes:
+ break;
+ }
+ } else {
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ return 1;
+ case mod:
+ printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
+ return 0;
+ case yes:
+ break;
+ }
+ }
+
+ while (1) {
+ int cnt, def;
+
+ printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
+ def_sym = sym_get_choice_value(sym);
+ cnt = def = 0;
+ line[0] = 0;
+ for (child = menu->list; child; child = child->next) {
+ if (!menu_is_visible(child))
+ continue;
+ if (!child->sym) {
+ printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
+ continue;
+ }
+ cnt++;
+ if (child->sym == def_sym) {
+ def = cnt;
+ printf("%*c", indent, '>');
+ } else
+ printf("%*c", indent, ' ');
+ printf(" %d. %s", cnt, _(menu_get_prompt(child)));
+ if (child->sym->name)
+ printf(" (%s)", child->sym->name);
+ if (!sym_has_value(child->sym))
+ printf(_(" (NEW)"));
+ printf("\n");
+ }
+ printf(_("%*schoice"), indent - 1, "");
+ if (cnt == 1) {
+ printf("[1]: 1\n");
+ goto conf_childs;
+ }
+ printf("[1-%d", cnt);
+ if (menu_has_help(menu))
+ printf("?");
+ printf("]: ");
+ switch (input_mode) {
+ case oldconfig:
+ case silentoldconfig:
+ if (!is_new) {
+ cnt = def;
+ printf("%d\n", cnt);
+ break;
+ }
+ check_stdin();
+ /* fall through */
+ case oldaskconfig:
+ fflush(stdout);
+ xfgets(line, 128, stdin);
+ strip(line);
+ if (line[0] == '?') {
+ print_help(menu);
+ continue;
+ }
+ if (!line[0])
+ cnt = def;
+ else if (isdigit(line[0]))
+ cnt = atoi(line);
+ else
+ continue;
+ break;
+ default:
+ break;
+ }
+
+ conf_childs:
+ for (child = menu->list; child; child = child->next) {
+ if (!child->sym || !menu_is_visible(child))
+ continue;
+ if (!--cnt)
+ break;
+ }
+ if (!child)
+ continue;
+ if (line[0] && line[strlen(line) - 1] == '?') {
+ print_help(child);
+ continue;
+ }
+ sym_set_choice_value(sym, child->sym);
+ for (child = child->list; child; child = child->next) {
+ indent += 2;
+ conf(child);
+ indent -= 2;
+ }
+ return 1;
+ }
+}
+
+static void conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (prop) {
+ const char *prompt;
+
+ switch (prop->type) {
+ case P_MENU:
+ if ((input_mode == silentoldconfig ||
+ input_mode == listnewconfig ||
+ input_mode == olddefconfig) &&
+ rootEntry != menu) {
+ check_conf(menu);
+ return;
+ }
+ /* fall through */
+ case P_COMMENT:
+ prompt = menu_get_prompt(menu);
+ if (prompt)
+ printf("%*c\n%*c %s\n%*c\n",
+ indent, '*',
+ indent, '*', _(prompt),
+ indent, '*');
+ default:
+ ;
+ }
+ }
+
+ if (!sym)
+ goto conf_childs;
+
+ if (sym_is_choice(sym)) {
+ conf_choice(menu);
+ if (sym->curr.tri != mod)
+ return;
+ goto conf_childs;
+ }
+
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ conf_string(menu);
+ break;
+ default:
+ conf_sym(menu);
+ break;
+ }
+
+conf_childs:
+ if (sym)
+ indent += 2;
+ for (child = menu->list; child; child = child->next)
+ conf(child);
+ if (sym)
+ indent -= 2;
+}
+
+static void check_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct menu *child;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ if (sym && !sym_has_value(sym)) {
+ if (sym_is_changable(sym) ||
+ (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
+ if (input_mode == listnewconfig) {
+ if (sym->name && !sym_is_choice_value(sym)) {
+ printf("%s%s\n", CONFIG_, sym->name);
+ }
+ } else if (input_mode != olddefconfig) {
+ if (!conf_cnt++)
+ printf(_("*\n* Restart config...\n*\n"));
+ rootEntry = menu_get_parent_menu(menu);
+ conf(rootEntry);
+ }
+ }
+ }
+
+ for (child = menu->list; child; child = child->next)
+ check_conf(child);
+}
+
+static struct option long_opts[] = {
+ {"oldaskconfig", no_argument, NULL, oldaskconfig},
+ {"oldconfig", no_argument, NULL, oldconfig},
+ {"silentoldconfig", no_argument, NULL, silentoldconfig},
+ {"defconfig", optional_argument, NULL, defconfig},
+ {"savedefconfig", required_argument, NULL, savedefconfig},
+ {"allnoconfig", no_argument, NULL, allnoconfig},
+ {"allyesconfig", no_argument, NULL, allyesconfig},
+ {"allmodconfig", no_argument, NULL, allmodconfig},
+ {"alldefconfig", no_argument, NULL, alldefconfig},
+ {"randconfig", no_argument, NULL, randconfig},
+ {"listnewconfig", no_argument, NULL, listnewconfig},
+ {"olddefconfig", no_argument, NULL, olddefconfig},
+ /*
+ * oldnoconfig is an alias of olddefconfig, because people already
+ * are dependent on its behavior(sets new symbols to their default
+ * value but not 'n') with the counter-intuitive name.
+ */
+ {"oldnoconfig", no_argument, NULL, olddefconfig},
+ {NULL, 0, NULL, 0}
+};
+
+static void conf_usage(const char *progname)
+{
+
+ printf("Usage: %s [option] <kconfig-file>\n", progname);
+ printf("[option] is _one_ of the following:\n");
+ printf(" --listnewconfig List new options\n");
+ printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
+ printf(" --oldconfig Update a configuration using a provided .config as base\n");
+ printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n");
+ printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n");
+ printf(" --oldnoconfig An alias of olddefconfig\n");
+ printf(" --defconfig <file> New config with default defined in <file>\n");
+ printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
+ printf(" --allnoconfig New config where all options are answered with no\n");
+ printf(" --allyesconfig New config where all options are answered with yes\n");
+ printf(" --allmodconfig New config where all options are answered with mod\n");
+ printf(" --alldefconfig New config with all symbols set to default\n");
+ printf(" --randconfig New config with random answer to all options\n");
+}
+
+int main(int ac, char **av)
+{
+ const char *progname = av[0];
+ int opt;
+ const char *name, *defconfig_file = NULL /* gcc uninit */;
+ struct stat tmpstat;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
+ input_mode = (enum input_mode)opt;
+ switch (opt) {
+ case silentoldconfig:
+ sync_kconfig = 1;
+ break;
+ case defconfig:
+ case savedefconfig:
+ defconfig_file = optarg;
+ break;
+ case randconfig:
+ {
+ struct timeval now;
+ unsigned int seed;
+
+ /*
+ * Use microseconds derived seed,
+ * compensate for systems where it may be zero
+ */
+ gettimeofday(&now, NULL);
+
+ seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
+ srand(seed);
+ break;
+ }
+ case oldaskconfig:
+ case oldconfig:
+ case allnoconfig:
+ case allyesconfig:
+ case allmodconfig:
+ case alldefconfig:
+ case listnewconfig:
+ case olddefconfig:
+ break;
+ case '?':
+ conf_usage(progname);
+ exit(1);
+ break;
+ }
+ }
+ if (ac == optind) {
+ printf(_("%s: Kconfig file missing\n"), av[0]);
+ conf_usage(progname);
+ exit(1);
+ }
+ name = av[optind];
+ conf_parse(name);
+ //zconfdump(stdout);
+ if (sync_kconfig) {
+ name = conf_get_configname();
+ if (stat(name, &tmpstat)) {
+ fprintf(stderr, _("***\n"
+ "*** Configuration file \"%s\" not found!\n"
+ "***\n"
+ "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
+ "*** \"make menuconfig\" or \"make xconfig\").\n"
+ "***\n"), name);
+ exit(1);
+ }
+ }
+
+ switch (input_mode) {
+ case defconfig:
+ if (!defconfig_file)
+ defconfig_file = conf_get_default_confname();
+ if (conf_read(defconfig_file)) {
+ printf(_("***\n"
+ "*** Can't find default configuration \"%s\"!\n"
+ "***\n"), defconfig_file);
+ exit(1);
+ }
+ break;
+ case savedefconfig:
+ case silentoldconfig:
+ case oldaskconfig:
+ case oldconfig:
+ case listnewconfig:
+ case olddefconfig:
+ conf_read(NULL);
+ break;
+ case allnoconfig:
+ case allyesconfig:
+ case allmodconfig:
+ case alldefconfig:
+ case randconfig:
+ name = getenv("KCONFIG_ALLCONFIG");
+ if (!name)
+ break;
+ if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
+ if (conf_read_simple(name, S_DEF_USER)) {
+ fprintf(stderr,
+ _("*** Can't read seed configuration \"%s\"!\n"),
+ name);
+ exit(1);
+ }
+ break;
+ }
+ switch (input_mode) {
+ case allnoconfig: name = "allno.config"; break;
+ case allyesconfig: name = "allyes.config"; break;
+ case allmodconfig: name = "allmod.config"; break;
+ case alldefconfig: name = "alldef.config"; break;
+ case randconfig: name = "allrandom.config"; break;
+ default: break;
+ }
+ if (conf_read_simple(name, S_DEF_USER) &&
+ conf_read_simple("all.config", S_DEF_USER)) {
+ fprintf(stderr,
+ _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
+ name);
+ exit(1);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (sync_kconfig) {
+ if (conf_get_changed()) {
+ name = getenv("KCONFIG_NOSILENTUPDATE");
+ if (name && *name) {
+ fprintf(stderr,
+ _("\n*** The configuration requires explicit update.\n\n"));
+ return 1;
+ }
+ }
+ valid_stdin = isatty(0) && isatty(1) && isatty(2);
+ }
+
+ switch (input_mode) {
+ case allnoconfig:
+ conf_set_all_new_symbols(def_no);
+ break;
+ case allyesconfig:
+ conf_set_all_new_symbols(def_yes);
+ break;
+ case allmodconfig:
+ conf_set_all_new_symbols(def_mod);
+ break;
+ case alldefconfig:
+ conf_set_all_new_symbols(def_default);
+ break;
+ case randconfig:
+ conf_set_all_new_symbols(def_random);
+ break;
+ case defconfig:
+ conf_set_all_new_symbols(def_default);
+ break;
+ case savedefconfig:
+ break;
+ case oldaskconfig:
+ rootEntry = &rootmenu;
+ conf(&rootmenu);
+ input_mode = silentoldconfig;
+ /* fall through */
+ case oldconfig:
+ case listnewconfig:
+ case olddefconfig:
+ case silentoldconfig:
+ /* Update until a loop caused no more changes */
+ do {
+ conf_cnt = 0;
+ check_conf(&rootmenu);
+ } while (conf_cnt &&
+ (input_mode != listnewconfig &&
+ input_mode != olddefconfig));
+ break;
+ }
+
+ if (sync_kconfig) {
+ /* silentoldconfig is used during the build so we shall update autoconf.
+ * All other commands are only used to generate a config.
+ */
+ if (conf_get_changed() && conf_write(NULL)) {
+ fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
+ exit(1);
+ }
+ if (conf_write_autoconf()) {
+ fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
+ return 1;
+ }
+ } else if (input_mode == savedefconfig) {
+ if (conf_write_defconfig(defconfig_file)) {
+ fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
+ defconfig_file);
+ return 1;
+ }
+ } else if (input_mode != listnewconfig) {
+ if (conf_write(NULL)) {
+ fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
+ exit(1);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Helper function to facilitate fgets() by Jean Sacren.
+ */
+void xfgets(char *str, int size, FILE *in)
+{
+ if (fgets(str, size, in) == NULL)
+ fprintf(stderr, "\nError in reading or end of file.\n");
+}
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
new file mode 100644
index 0000000..13ddf11
--- /dev/null
+++ b/scripts/kconfig/confdata.c
@@ -0,0 +1,1164 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <sys/stat.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "lkc.h"
+
+static void conf_warning(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+static void conf_message(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+static const char *conf_filename;
+static int conf_lineno, conf_warnings, conf_unsaved;
+
+const char conf_defname[] = "arch/$ARCH/defconfig";
+
+static void conf_warning(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ conf_warnings++;
+}
+
+static void conf_default_message_callback(const char *fmt, va_list ap)
+{
+ printf("#\n# ");
+ vprintf(fmt, ap);
+ printf("\n#\n");
+}
+
+static void (*conf_message_callback) (const char *fmt, va_list ap) =
+ conf_default_message_callback;
+void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
+{
+ conf_message_callback = fn;
+}
+
+static void conf_message(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (conf_message_callback)
+ conf_message_callback(fmt, ap);
+}
+
+const char *conf_get_configname(void)
+{
+ char *name = getenv("KCONFIG_CONFIG");
+
+ return name ? name : ".config";
+}
+
+const char *conf_get_autoconfig_name(void)
+{
+ char *name = getenv("KCONFIG_AUTOCONFIG");
+
+ return name ? name : "include/config/auto.conf";
+}
+
+static char *conf_expand_value(const char *in)
+{
+ struct symbol *sym;
+ const char *src;
+ static char res_value[SYMBOL_MAXLENGTH];
+ char *dst, name[SYMBOL_MAXLENGTH];
+
+ res_value[0] = 0;
+ dst = name;
+ while ((src = strchr(in, '$'))) {
+ strncat(res_value, in, src - in);
+ src++;
+ dst = name;
+ while (isalnum(*src) || *src == '_')
+ *dst++ = *src++;
+ *dst = 0;
+ sym = sym_lookup(name, 0);
+ sym_calc_value(sym);
+ strcat(res_value, sym_get_string_value(sym));
+ in = src;
+ }
+ strcat(res_value, in);
+
+ return res_value;
+}
+
+char *conf_get_default_confname(void)
+{
+ struct stat buf;
+ static char fullname[PATH_MAX+1];
+ char *env, *name;
+
+ name = conf_expand_value(conf_defname);
+ env = getenv(SRCTREE);
+ if (env) {
+ sprintf(fullname, "%s/%s", env, name);
+ if (!stat(fullname, &buf))
+ return fullname;
+ }
+ return name;
+}
+
+static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
+{
+ char *p2;
+
+ switch (sym->type) {
+ case S_TRISTATE:
+ if (p[0] == 'm') {
+ sym->def[def].tri = mod;
+ sym->flags |= def_flags;
+ break;
+ }
+ /* fall through */
+ case S_BOOLEAN:
+ if (p[0] == 'y') {
+ sym->def[def].tri = yes;
+ sym->flags |= def_flags;
+ break;
+ }
+ if (p[0] == 'n') {
+ sym->def[def].tri = no;
+ sym->flags |= def_flags;
+ break;
+ }
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ return 1;
+ case S_OTHER:
+ if (*p != '"') {
+ for (p2 = p; *p2 && !isspace(*p2); p2++)
+ ;
+ sym->type = S_STRING;
+ goto done;
+ }
+ /* fall through */
+ case S_STRING:
+ if (*p++ != '"')
+ break;
+ for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
+ if (*p2 == '"') {
+ *p2 = 0;
+ break;
+ }
+ memmove(p2, p2 + 1, strlen(p2));
+ }
+ if (!p2) {
+ conf_warning("invalid string found");
+ return 1;
+ }
+ /* fall through */
+ case S_INT:
+ case S_HEX:
+ done:
+ if (sym_string_valid(sym, p)) {
+ sym->def[def].val = strdup(p);
+ sym->flags |= def_flags;
+ } else {
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ return 1;
+ }
+ break;
+ default:
+ ;
+ }
+ return 0;
+}
+
+#define LINE_GROWTH 16
+static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
+{
+ char *nline;
+ size_t new_size = slen + 1;
+ if (new_size > *n) {
+ new_size += LINE_GROWTH - 1;
+ new_size *= 2;
+ nline = realloc(*lineptr, new_size);
+ if (!nline)
+ return -1;
+
+ *lineptr = nline;
+ *n = new_size;
+ }
+
+ (*lineptr)[slen] = c;
+
+ return 0;
+}
+
+static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
+{
+ char *line = *lineptr;
+ size_t slen = 0;
+
+ for (;;) {
+ int c = getc(stream);
+
+ switch (c) {
+ case '\n':
+ if (add_byte(c, &line, slen, n) < 0)
+ goto e_out;
+ slen++;
+ /* fall through */
+ case EOF:
+ if (add_byte('\0', &line, slen, n) < 0)
+ goto e_out;
+ *lineptr = line;
+ if (slen == 0)
+ return -1;
+ return slen;
+ default:
+ if (add_byte(c, &line, slen, n) < 0)
+ goto e_out;
+ slen++;
+ }
+ }
+
+e_out:
+ line[slen-1] = '\0';
+ *lineptr = line;
+ return -1;
+}
+
+int conf_read_simple(const char *name, int def)
+{
+ FILE *in = NULL;
+ char *line = NULL;
+ size_t line_asize = 0;
+ char *p, *p2;
+ struct symbol *sym;
+ int i, def_flags;
+
+ if (name) {
+ in = zconf_fopen(name);
+ } else {
+ struct property *prop;
+
+ name = conf_get_configname();
+ in = zconf_fopen(name);
+ if (in)
+ goto load;
+ sym_add_change_count(1);
+ if (!sym_defconfig_list) {
+ if (modules_sym)
+ sym_calc_value(modules_sym);
+ 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) {
+ conf_message(_("using defaults found in %s"),
+ 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_CHANGED;
+ sym->flags &= ~(def_flags|SYMBOL_VALID);
+ if (sym_is_choice(sym))
+ sym->flags |= def_flags;
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ if (sym->def[def].val)
+ free(sym->def[def].val);
+ /* fall through */
+ default:
+ sym->def[def].val = NULL;
+ sym->def[def].tri = no;
+ }
+ }
+
+ while (compat_getline(&line, &line_asize, in) != -1) {
+ conf_lineno++;
+ sym = NULL;
+ if (line[0] == '#') {
+ if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
+ continue;
+ p = strchr(line + 2 + strlen(CONFIG_), ' ');
+ if (!p)
+ continue;
+ *p++ = 0;
+ if (strncmp(p, "is not set", 10))
+ continue;
+ if (def == S_DEF_USER) {
+ sym = sym_find(line + 2 + strlen(CONFIG_));
+ if (!sym) {
+ sym_add_change_count(1);
+ goto setsym;
+ }
+ } else {
+ sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
+ if (sym->type == S_UNKNOWN)
+ sym->type = S_BOOLEAN;
+ }
+ if (sym->flags & def_flags) {
+ conf_warning("override: reassigning to symbol %s", sym->name);
+ }
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ sym->def[def].tri = no;
+ sym->flags |= def_flags;
+ break;
+ default:
+ ;
+ }
+ } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
+ p = strchr(line + strlen(CONFIG_), '=');
+ if (!p)
+ continue;
+ *p++ = 0;
+ p2 = strchr(p, '\n');
+ if (p2) {
+ *p2-- = 0;
+ if (*p2 == '\r')
+ *p2 = 0;
+ }
+ if (def == S_DEF_USER) {
+ sym = sym_find(line + strlen(CONFIG_));
+ if (!sym) {
+ sym_add_change_count(1);
+ goto setsym;
+ }
+ } else {
+ sym = sym_lookup(line + strlen(CONFIG_), 0);
+ if (sym->type == S_UNKNOWN)
+ sym->type = S_OTHER;
+ }
+ if (sym->flags & def_flags) {
+ conf_warning("override: reassigning to symbol %s", sym->name);
+ }
+ if (conf_set_sym_val(sym, def, def_flags, p))
+ continue;
+ } else {
+ if (line[0] != '\r' && line[0] != '\n')
+ conf_warning("unexpected data");
+ continue;
+ }
+setsym:
+ if (sym && sym_is_choice_value(sym)) {
+ struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
+ switch (sym->def[def].tri) {
+ case no:
+ break;
+ case mod:
+ if (cs->def[def].tri == yes) {
+ conf_warning("%s creates inconsistent choice state", sym->name);
+ cs->flags &= ~def_flags;
+ }
+ break;
+ case yes:
+ if (cs->def[def].tri != no)
+ conf_warning("override: %s changes choice state", sym->name);
+ cs->def[def].val = sym;
+ break;
+ }
+ cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
+ }
+ }
+ free(line);
+ fclose(in);
+
+ if (modules_sym)
+ sym_calc_value(modules_sym);
+ return 0;
+}
+
+int conf_read(const char *name)
+{
+ struct symbol *sym;
+ int i;
+
+ sym_set_change_count(0);
+
+ if (conf_read_simple(name, S_DEF_USER))
+ return 1;
+
+ for_all_symbols(i, sym) {
+ sym_calc_value(sym);
+ if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
+ continue;
+ if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
+ /* check that calculated value agrees with saved value */
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
+ break;
+ if (!sym_is_choice(sym))
+ continue;
+ /* fall through */
+ default:
+ if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
+ continue;
+ break;
+ }
+ } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
+ /* no previous value and not saved */
+ continue;
+ conf_unsaved++;
+ /* maybe print value in verbose mode... */
+ }
+
+ for_all_symbols(i, sym) {
+ if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
+ /* Reset values of generates values, so they'll appear
+ * as new, if they should become visible, but that
+ * doesn't quite work if the Kconfig and the saved
+ * configuration disagree.
+ */
+ if (sym->visible == no && !conf_unsaved)
+ sym->flags &= ~SYMBOL_DEF_USER;
+ switch (sym->type) {
+ case S_STRING:
+ case S_INT:
+ case S_HEX:
+ /* Reset a string value if it's out of range */
+ if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
+ break;
+ sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
+ conf_unsaved++;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ sym_add_change_count(conf_warnings || conf_unsaved);
+
+ return 0;
+}
+
+/*
+ * Kconfig configuration printer
+ *
+ * This printer is used when generating the resulting configuration after
+ * kconfig invocation and `defconfig' files. Unset symbol might be omitted by
+ * passing a non-NULL argument to the printer.
+ *
+ */
+static void
+kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (*value == 'n') {
+ bool skip_unset = (arg != NULL);
+
+ if (!skip_unset)
+ fprintf(fp, "# %s%s is not set\n",
+ CONFIG_, sym->name);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
+}
+
+static void
+kconfig_print_comment(FILE *fp, const char *value, void *arg)
+{
+ const char *p = value;
+ size_t l;
+
+ for (;;) {
+ l = strcspn(p, "\n");
+ fprintf(fp, "#");
+ if (l) {
+ fprintf(fp, " ");
+ xfwrite(p, l, 1, fp);
+ p += l;
+ }
+ fprintf(fp, "\n");
+ if (*p++ == '\0')
+ break;
+ }
+}
+
+static struct conf_printer kconfig_printer_cb =
+{
+ .print_symbol = kconfig_print_symbol,
+ .print_comment = kconfig_print_comment,
+};
+
+/*
+ * Header printer
+ *
+ * This printer is used when generating the `include/generated/autoconf.h' file.
+ */
+static void
+header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE: {
+ const char *suffix = "";
+
+ switch (*value) {
+ case 'n':
+ break;
+ case 'm':
+ suffix = "_MODULE";
+ /* fall through */
+ default:
+ fprintf(fp, "#define %s%s%s 1\n",
+ CONFIG_, sym->name, suffix);
+ }
+ break;
+ }
+ case S_HEX: {
+ const char *prefix = "";
+
+ if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
+ prefix = "0x";
+ fprintf(fp, "#define %s%s %s%s\n",
+ CONFIG_, sym->name, prefix, value);
+ break;
+ }
+ case S_STRING:
+ case S_INT:
+ fprintf(fp, "#define %s%s %s\n",
+ CONFIG_, sym->name, value);
+ break;
+ default:
+ break;
+ }
+
+}
+
+static void
+header_print_comment(FILE *fp, const char *value, void *arg)
+{
+ const char *p = value;
+ size_t l;
+
+ fprintf(fp, "/*\n");
+ for (;;) {
+ l = strcspn(p, "\n");
+ fprintf(fp, " *");
+ if (l) {
+ fprintf(fp, " ");
+ xfwrite(p, l, 1, fp);
+ p += l;
+ }
+ fprintf(fp, "\n");
+ if (*p++ == '\0')
+ break;
+ }
+ fprintf(fp, " */\n");
+}
+
+static struct conf_printer header_printer_cb =
+{
+ .print_symbol = header_print_symbol,
+ .print_comment = header_print_comment,
+};
+
+/*
+ * Tristate printer
+ *
+ * This printer is used when generating the `include/config/tristate.conf' file.
+ */
+static void
+tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+ if (sym->type == S_TRISTATE && *value != 'n')
+ fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
+}
+
+static struct conf_printer tristate_printer_cb =
+{
+ .print_symbol = tristate_print_symbol,
+ .print_comment = kconfig_print_comment,
+};
+
+static void conf_write_symbol(FILE *fp, struct symbol *sym,
+ struct conf_printer *printer, void *printer_arg)
+{
+ const char *str;
+
+ switch (sym->type) {
+ case S_OTHER:
+ case S_UNKNOWN:
+ break;
+ case S_STRING:
+ str = sym_get_string_value(sym);
+ str = sym_escape_string_value(str);
+ printer->print_symbol(fp, sym, str, printer_arg);
+ free((void *)str);
+ break;
+ default:
+ str = sym_get_string_value(sym);
+ printer->print_symbol(fp, sym, str, printer_arg);
+ }
+}
+
+static void
+conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
+{
+ char buf[256];
+
+ snprintf(buf, sizeof(buf),
+ "\n"
+ "Automatically generated file; DO NOT EDIT.\n"
+ "%s\n",
+ rootmenu.prompt->text);
+
+ printer->print_comment(fp, buf, printer_arg);
+}
+
+/*
+ * Write out a minimal config.
+ * All values that has default values are skipped as this is redundant.
+ */
+int conf_write_defconfig(const char *filename)
+{
+ struct symbol *sym;
+ struct menu *menu;
+ FILE *out;
+
+ out = fopen(filename, "w");
+ if (!out)
+ return 1;
+
+ sym_clear_all_valid();
+
+ /* Traverse all menus to find all relevant symbols */
+ menu = rootmenu.list;
+
+ while (menu != NULL)
+ {
+ sym = menu->sym;
+ if (sym == NULL) {
+ if (!menu_is_visible(menu))
+ goto next_menu;
+ } else if (!sym_is_choice(sym)) {
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ goto next_menu;
+ sym->flags &= ~SYMBOL_WRITE;
+ /* If we cannot change the symbol - skip */
+ if (!sym_is_changable(sym))
+ goto next_menu;
+ /* If symbol equals to default value - skip */
+ if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
+ goto next_menu;
+
+ /*
+ * If symbol is a choice value and equals to the
+ * default for a choice - skip.
+ * But only if value is bool and equal to "y" and
+ * choice is not "optional".
+ * (If choice is "optional" then all values can be "n")
+ */
+ if (sym_is_choice_value(sym)) {
+ struct symbol *cs;
+ struct symbol *ds;
+
+ cs = prop_get_symbol(sym_get_choice_prop(sym));
+ ds = sym_choice_default(cs);
+ if (!sym_is_optional(cs) && sym == ds) {
+ if ((sym->type == S_BOOLEAN) &&
+ sym_get_tristate_value(sym) == yes)
+ goto next_menu;
+ }
+ }
+ conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
+ }
+next_menu:
+ if (menu->list != NULL) {
+ menu = menu->list;
+ }
+ else if (menu->next != NULL) {
+ menu = menu->next;
+ } else {
+ while ((menu = menu->parent)) {
+ if (menu->next != NULL) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+ }
+ fclose(out);
+ return 0;
+}
+
+int conf_write(const char *name)
+{
+ FILE *out;
+ struct symbol *sym;
+ struct menu *menu;
+ const char *basename;
+ const char *str;
+ char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
+ char *env;
+
+ dirname[0] = 0;
+ if (name && name[0]) {
+ struct stat st;
+ char *slash;
+
+ if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
+ strcpy(dirname, name);
+ strcat(dirname, "/");
+ basename = conf_get_configname();
+ } else if ((slash = strrchr(name, '/'))) {
+ int size = slash - name + 1;
+ memcpy(dirname, name, size);
+ dirname[size] = 0;
+ if (slash[1])
+ basename = slash + 1;
+ else
+ basename = conf_get_configname();
+ } else
+ basename = name;
+ } else
+ basename = conf_get_configname();
+
+ 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;
+
+ conf_write_heading(out, &kconfig_printer_cb, NULL);
+
+ if (!conf_get_changed())
+ sym_clear_all_valid();
+
+ menu = rootmenu.list;
+ while (menu) {
+ sym = menu->sym;
+ if (!sym) {
+ if (!menu_is_visible(menu))
+ goto next;
+ str = menu_get_prompt(menu);
+ fprintf(out, "\n"
+ "#\n"
+ "# %s\n"
+ "#\n", str);
+ } else if (!(sym->flags & SYMBOL_CHOICE)) {
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ goto next;
+ sym->flags &= ~SYMBOL_WRITE;
+
+ conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
+ }
+
+next:
+ if (menu->list) {
+ menu = menu->list;
+ continue;
+ }
+ if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+ fclose(out);
+
+ if (*tmpname) {
+ strcat(dirname, basename);
+ strcat(dirname, ".old");
+ rename(newname, dirname);
+ if (rename(tmpname, newname))
+ return 1;
+ }
+
+ conf_message(_("configuration written to %s"), newname);
+
+ sym_set_change_count(0);
+
+ return 0;
+}
+
+static int conf_split_config(void)
+{
+ const char *name;
+ char path[PATH_MAX+1];
+ char *s, *d, c;
+ struct symbol *sym;
+ struct stat sb;
+ int res, i, fd;
+
+ name = conf_get_autoconfig_name();
+ 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);
+ }
+out:
+ if (chdir("../.."))
+ return 1;
+
+ return res;
+}
+
+int conf_write_autoconf(void)
+{
+ struct symbol *sym;
+ const char *name;
+ FILE *out, *tristate, *out_h;
+ int i;
+
+ 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;
+
+ tristate = fopen(".tmpconfig_tristate", "w");
+ if (!tristate) {
+ fclose(out);
+ return 1;
+ }
+
+ out_h = fopen(".tmpconfig.h", "w");
+ if (!out_h) {
+ fclose(out);
+ fclose(tristate);
+ return 1;
+ }
+
+ conf_write_heading(out, &kconfig_printer_cb, NULL);
+
+ conf_write_heading(tristate, &tristate_printer_cb, NULL);
+
+ conf_write_heading(out_h, &header_printer_cb, NULL);
+
+ for_all_symbols(i, sym) {
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
+ continue;
+
+ /* write symbol to auto.conf, tristate and header files */
+ conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
+
+ conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
+
+ conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
+ }
+ fclose(out);
+ fclose(tristate);
+ fclose(out_h);
+
+ name = getenv("KCONFIG_AUTOHEADER");
+ if (!name)
+ name = "include/generated/autoconf.h";
+ if (rename(".tmpconfig.h", name))
+ return 1;
+ name = getenv("KCONFIG_TRISTATE");
+ if (!name)
+ name = "include/config/tristate.conf";
+ if (rename(".tmpconfig_tristate", name))
+ return 1;
+ name = conf_get_autoconfig_name();
+ /*
+ * This must be the last step, kbuild has a dependency on auto.conf
+ * and this marks the successful completion of the previous steps.
+ */
+ if (rename(".tmpconfig", name))
+ return 1;
+
+ return 0;
+}
+
+static int sym_change_count;
+static void (*conf_changed_callback)(void);
+
+void sym_set_change_count(int count)
+{
+ int _sym_change_count = sym_change_count;
+ sym_change_count = count;
+ if (conf_changed_callback &&
+ (bool)_sym_change_count != (bool)count)
+ conf_changed_callback();
+}
+
+void sym_add_change_count(int count)
+{
+ sym_set_change_count(count + sym_change_count);
+}
+
+bool conf_get_changed(void)
+{
+ return sym_change_count;
+}
+
+void conf_set_changed_callback(void (*fn)(void))
+{
+ conf_changed_callback = fn;
+}
+
+static void randomize_choice_values(struct symbol *csym)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct expr *e;
+ int cnt, def;
+
+ /*
+ * If choice is mod then we may have more items selected
+ * and if no then no-one.
+ * In both cases stop.
+ */
+ if (csym->curr.tri != yes)
+ return;
+
+ prop = sym_get_choice_prop(csym);
+
+ /* count entries in choice block */
+ cnt = 0;
+ expr_list_for_each_sym(prop->expr, e, sym)
+ cnt++;
+
+ /*
+ * find a random value and set it to yes,
+ * set the rest to no so we have only one set
+ */
+ def = (rand() % cnt);
+
+ cnt = 0;
+ expr_list_for_each_sym(prop->expr, e, sym) {
+ if (def == cnt++) {
+ sym->def[S_DEF_USER].tri = yes;
+ csym->def[S_DEF_USER].val = sym;
+ }
+ else {
+ sym->def[S_DEF_USER].tri = no;
+ }
+ }
+ csym->flags |= SYMBOL_DEF_USER;
+ /* clear VALID to get value calculated */
+ csym->flags &= ~(SYMBOL_VALID);
+}
+
+static void set_all_choice_values(struct symbol *csym)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct expr *e;
+
+ prop = sym_get_choice_prop(csym);
+
+ /*
+ * Set all non-assinged choice values to no
+ */
+ expr_list_for_each_sym(prop->expr, e, sym) {
+ if (!sym_has_value(sym))
+ sym->def[S_DEF_USER].tri = no;
+ }
+ csym->flags |= SYMBOL_DEF_USER;
+ /* clear VALID to get value calculated */
+ csym->flags &= ~(SYMBOL_VALID);
+}
+
+void conf_set_all_new_symbols(enum conf_def_mode mode)
+{
+ struct symbol *sym, *csym;
+ int i, cnt;
+
+ for_all_symbols(i, sym) {
+ if (sym_has_value(sym))
+ continue;
+ switch (sym_get_type(sym)) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (mode) {
+ case def_yes:
+ sym->def[S_DEF_USER].tri = yes;
+ break;
+ case def_mod:
+ sym->def[S_DEF_USER].tri = mod;
+ break;
+ case def_no:
+ sym->def[S_DEF_USER].tri = no;
+ break;
+ case def_random:
+ cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
+ sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
+ break;
+ default:
+ continue;
+ }
+ if (!(sym_is_choice(sym) && mode == def_random))
+ sym->flags |= SYMBOL_DEF_USER;
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ sym_clear_all_valid();
+
+ /*
+ * We have different type of choice blocks.
+ * If curr.tri equals to mod then we can select several
+ * choice symbols in one block.
+ * In this case we do nothing.
+ * If curr.tri equals yes then only one symbol can be
+ * selected in a choice block and we set it to yes,
+ * and the rest to no.
+ */
+ for_all_symbols(i, csym) {
+ if (sym_has_value(csym) || !sym_is_choice(csym))
+ continue;
+
+ sym_calc_value(csym);
+ if (mode == def_random)
+ randomize_choice_values(csym);
+ else
+ set_all_choice_values(csym);
+ }
+}
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
new file mode 100644
index 0000000..d662652
--- /dev/null
+++ b/scripts/kconfig/expr.c
@@ -0,0 +1,1168 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lkc.h"
+
+#define DEBUG_EXPR 0
+
+struct expr *expr_alloc_symbol(struct symbol *sym)
+{
+ struct expr *e = xcalloc(1, sizeof(*e));
+ e->type = E_SYMBOL;
+ e->left.sym = sym;
+ return e;
+}
+
+struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
+{
+ struct expr *e = xcalloc(1, sizeof(*e));
+ e->type = type;
+ e->left.expr = ce;
+ return e;
+}
+
+struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
+{
+ struct expr *e = xcalloc(1, sizeof(*e));
+ e->type = type;
+ e->left.expr = e1;
+ e->right.expr = e2;
+ return e;
+}
+
+struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
+{
+ struct expr *e = xcalloc(1, sizeof(*e));
+ e->type = type;
+ e->left.sym = s1;
+ e->right.sym = s2;
+ return e;
+}
+
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
+{
+ if (!e1)
+ return e2;
+ return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
+}
+
+struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
+{
+ if (!e1)
+ return e2;
+ return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
+}
+
+struct expr *expr_copy(const struct expr *org)
+{
+ struct expr *e;
+
+ if (!org)
+ return NULL;
+
+ e = xmalloc(sizeof(*org));
+ memcpy(e, org, sizeof(*org));
+ switch (org->type) {
+ case E_SYMBOL:
+ e->left = org->left;
+ break;
+ case E_NOT:
+ e->left.expr = expr_copy(org->left.expr);
+ break;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ e->left.sym = org->left.sym;
+ e->right.sym = org->right.sym;
+ break;
+ case E_AND:
+ case E_OR:
+ case E_LIST:
+ e->left.expr = expr_copy(org->left.expr);
+ e->right.expr = expr_copy(org->right.expr);
+ break;
+ default:
+ printf("can't copy type %d\n", e->type);
+ free(e);
+ e = NULL;
+ break;
+ }
+
+ return e;
+}
+
+void expr_free(struct expr *e)
+{
+ if (!e)
+ return;
+
+ switch (e->type) {
+ case E_SYMBOL:
+ break;
+ case E_NOT:
+ expr_free(e->left.expr);
+ return;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ break;
+ case E_OR:
+ case E_AND:
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ break;
+ default:
+ printf("how to free type %d?\n", e->type);
+ break;
+ }
+ free(e);
+}
+
+static int trans_count;
+
+#define e1 (*ep1)
+#define e2 (*ep2)
+
+static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+ if (e1->type == type) {
+ __expr_eliminate_eq(type, &e1->left.expr, &e2);
+ __expr_eliminate_eq(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ __expr_eliminate_eq(type, &e1, &e2->left.expr);
+ __expr_eliminate_eq(type, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+ e1->left.sym == e2->left.sym &&
+ (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
+ return;
+ if (!expr_eq(e1, e2))
+ return;
+ trans_count++;
+ expr_free(e1); expr_free(e2);
+ switch (type) {
+ case E_OR:
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ break;
+ case E_AND:
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ break;
+ default:
+ ;
+ }
+}
+
+void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
+{
+ if (!e1 || !e2)
+ return;
+ switch (e1->type) {
+ case E_OR:
+ case E_AND:
+ __expr_eliminate_eq(e1->type, ep1, ep2);
+ default:
+ ;
+ }
+ if (e1->type != e2->type) switch (e2->type) {
+ case E_OR:
+ case E_AND:
+ __expr_eliminate_eq(e2->type, ep1, ep2);
+ default:
+ ;
+ }
+ e1 = expr_eliminate_yn(e1);
+ e2 = expr_eliminate_yn(e2);
+}
+
+#undef e1
+#undef e2
+
+int expr_eq(struct expr *e1, struct expr *e2)
+{
+ int res, old_count;
+
+ if (e1->type != e2->type)
+ return 0;
+ switch (e1->type) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
+ case E_SYMBOL:
+ return e1->left.sym == e2->left.sym;
+ case E_NOT:
+ return expr_eq(e1->left.expr, e2->left.expr);
+ case E_AND:
+ case E_OR:
+ e1 = expr_copy(e1);
+ e2 = expr_copy(e2);
+ old_count = trans_count;
+ expr_eliminate_eq(&e1, &e2);
+ res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+ e1->left.sym == e2->left.sym);
+ expr_free(e1);
+ expr_free(e2);
+ trans_count = old_count;
+ return res;
+ case E_LIST:
+ case E_RANGE:
+ case E_NONE:
+ /* panic */;
+ }
+
+ if (DEBUG_EXPR) {
+ expr_fprint(e1, stdout);
+ printf(" = ");
+ expr_fprint(e2, stdout);
+ printf(" ?\n");
+ }
+
+ return 0;
+}
+
+struct expr *expr_eliminate_yn(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (e) switch (e->type) {
+ case E_AND:
+ e->left.expr = expr_eliminate_yn(e->left.expr);
+ e->right.expr = expr_eliminate_yn(e->right.expr);
+ if (e->left.expr->type == E_SYMBOL) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ if (e->right.expr->type == E_SYMBOL) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ break;
+ case E_OR:
+ e->left.expr = expr_eliminate_yn(e->left.expr);
+ e->right.expr = expr_eliminate_yn(e->right.expr);
+ if (e->left.expr->type == E_SYMBOL) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ if (e->right.expr->type == E_SYMBOL) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+/*
+ * bool FOO!=n => FOO
+ */
+struct expr *expr_trans_bool(struct expr *e)
+{
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_AND:
+ case E_OR:
+ case E_NOT:
+ e->left.expr = expr_trans_bool(e->left.expr);
+ e->right.expr = expr_trans_bool(e->right.expr);
+ break;
+ case E_UNEQUAL:
+ // FOO!=n -> FOO
+ if (e->left.sym->type == S_TRISTATE) {
+ if (e->right.sym == &symbol_no) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+/*
+ * e1 || e2 -> ?
+ */
+static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+ return NULL;
+ if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+ return NULL;
+ if (e1->type == E_NOT) {
+ tmp = e1->left.expr;
+ if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->type == E_NOT) {
+ if (e2->left.expr->type != E_SYMBOL)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+ return NULL;
+ if (sym1->type == S_TRISTATE) {
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='m') -> (a!='n')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
+ }
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='n') -> (a!='m')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
+ }
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
+ // (a='m') || (a='n') -> (a!='y')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
+ }
+ }
+ if (sym1->type == S_BOOLEAN && sym1 == sym2) {
+ if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
+ (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
+ return expr_alloc_symbol(&symbol_yes);
+ }
+
+ if (DEBUG_EXPR) {
+ printf("optimize (");
+ expr_fprint(e1, stdout);
+ printf(") || (");
+ expr_fprint(e2, stdout);
+ printf(")?\n");
+ }
+ return NULL;
+}
+
+static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+ return NULL;
+ if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+ return NULL;
+ if (e1->type == E_NOT) {
+ tmp = e1->left.expr;
+ if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->type == E_NOT) {
+ if (e2->left.expr->type != E_SYMBOL)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+ return NULL;
+
+ if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
+ (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
+ // (a) && (a='y') -> (a='y')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
+ // (a) && (a!='n') -> (a)
+ return expr_alloc_symbol(sym1);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
+ // (a) && (a!='m') -> (a='y')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if (sym1->type == S_TRISTATE) {
+ if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e1->right.sym;
+ if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e2->right.sym;
+ if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='n') -> (a='m')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
+
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='m') -> (a='n')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
+
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
+ // (a!='m') && (a!='n') -> (a='m')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
+ (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
+ (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
+ return NULL;
+ }
+
+ if (DEBUG_EXPR) {
+ printf("optimize (");
+ expr_fprint(e1, stdout);
+ printf(") && (");
+ expr_fprint(e2, stdout);
+ printf(")?\n");
+ }
+ return NULL;
+}
+
+static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp;
+
+ if (e1->type == type) {
+ expr_eliminate_dups1(type, &e1->left.expr, &e2);
+ expr_eliminate_dups1(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_eliminate_dups1(type, &e1, &e2->left.expr);
+ expr_eliminate_dups1(type, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->type) {
+ case E_OR: case E_AND:
+ expr_eliminate_dups1(e1->type, &e1, &e1);
+ default:
+ ;
+ }
+
+ switch (type) {
+ case E_OR:
+ tmp = expr_join_or(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ case E_AND:
+ tmp = expr_join_and(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ default:
+ ;
+ }
+#undef e1
+#undef e2
+}
+
+static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp, *tmp1, *tmp2;
+
+ if (e1->type == type) {
+ expr_eliminate_dups2(type, &e1->left.expr, &e2);
+ expr_eliminate_dups2(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_eliminate_dups2(type, &e1, &e2->left.expr);
+ expr_eliminate_dups2(type, &e1, &e2->right.expr);
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->type) {
+ case E_OR:
+ expr_eliminate_dups2(e1->type, &e1, &e1);
+ // (FOO || BAR) && (!FOO && !BAR) -> n
+ tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = expr_extract_eq_and(&tmp1, &tmp2);
+ if (expr_is_yes(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_no);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ case E_AND:
+ expr_eliminate_dups2(e1->type, &e1, &e1);
+ // (FOO && BAR) || (!FOO || !BAR) -> y
+ tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = expr_extract_eq_or(&tmp1, &tmp2);
+ if (expr_is_no(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ default:
+ ;
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *expr_eliminate_dups(struct expr *e)
+{
+ int oldcount;
+ if (!e)
+ return e;
+
+ oldcount = trans_count;
+ while (1) {
+ trans_count = 0;
+ switch (e->type) {
+ case E_OR: case E_AND:
+ expr_eliminate_dups1(e->type, &e, &e);
+ expr_eliminate_dups2(e->type, &e, &e);
+ default:
+ ;
+ }
+ if (!trans_count)
+ break;
+ e = expr_eliminate_yn(e);
+ }
+ trans_count = oldcount;
+ return e;
+}
+
+struct expr *expr_transform(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ case E_SYMBOL:
+ case E_LIST:
+ break;
+ default:
+ e->left.expr = expr_transform(e->left.expr);
+ e->right.expr = expr_transform(e->right.expr);
+ }
+
+ switch (e->type) {
+ case E_EQUAL:
+ if (e->left.sym->type != S_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ e->type = E_NOT;
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ break;
+ }
+ break;
+ case E_UNEQUAL:
+ if (e->left.sym->type != S_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ e->type = E_NOT;
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ break;
+ }
+ break;
+ case E_NOT:
+ switch (e->left.expr->type) {
+ case E_NOT:
+ // !!a -> a
+ tmp = e->left.expr->left.expr;
+ free(e->left.expr);
+ free(e);
+ e = tmp;
+ e = expr_transform(e);
+ break;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ // !a='x' -> a!='x'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
+ break;
+ case E_OR:
+ // !(a || b) -> !a && !b
+ tmp = e->left.expr;
+ e->type = E_AND;
+ e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+ tmp->type = E_NOT;
+ tmp->right.expr = NULL;
+ e = expr_transform(e);
+ break;
+ case E_AND:
+ // !(a && b) -> !a || !b
+ tmp = e->left.expr;
+ e->type = E_OR;
+ e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+ tmp->type = E_NOT;
+ tmp->right.expr = NULL;
+ e = expr_transform(e);
+ break;
+ case E_SYMBOL:
+ if (e->left.expr->left.sym == &symbol_yes) {
+ // !'y' -> 'n'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ break;
+ }
+ if (e->left.expr->left.sym == &symbol_mod) {
+ // !'m' -> 'm'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_mod;
+ break;
+ }
+ if (e->left.expr->left.sym == &symbol_no) {
+ // !'n' -> 'y'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ break;
+ }
+ break;
+ default:
+ ;
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+int expr_contains_symbol(struct expr *dep, struct symbol *sym)
+{
+ if (!dep)
+ return 0;
+
+ switch (dep->type) {
+ case E_AND:
+ case E_OR:
+ return expr_contains_symbol(dep->left.expr, sym) ||
+ expr_contains_symbol(dep->right.expr, sym);
+ case E_SYMBOL:
+ return dep->left.sym == sym;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ return dep->left.sym == sym ||
+ dep->right.sym == sym;
+ case E_NOT:
+ return expr_contains_symbol(dep->left.expr, sym);
+ default:
+ ;
+ }
+ return 0;
+}
+
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
+{
+ if (!dep)
+ return false;
+
+ switch (dep->type) {
+ case E_AND:
+ return expr_depends_symbol(dep->left.expr, sym) ||
+ expr_depends_symbol(dep->right.expr, sym);
+ case E_SYMBOL:
+ return dep->left.sym == sym;
+ case E_EQUAL:
+ if (dep->left.sym == sym) {
+ if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
+ return true;
+ }
+ break;
+ case E_UNEQUAL:
+ if (dep->left.sym == sym) {
+ if (dep->right.sym == &symbol_no)
+ return true;
+ }
+ break;
+ default:
+ ;
+ }
+ return false;
+}
+
+struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ expr_extract_eq(E_AND, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ expr_extract_eq(E_OR, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ if (e1->type == type) {
+ expr_extract_eq(type, ep, &e1->left.expr, &e2);
+ expr_extract_eq(type, ep, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_extract_eq(type, ep, ep1, &e2->left.expr);
+ expr_extract_eq(type, ep, ep1, &e2->right.expr);
+ return;
+ }
+ if (expr_eq(e1, e2)) {
+ *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
+ expr_free(e2);
+ if (type == E_AND) {
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ } else if (type == E_OR) {
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ }
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
+{
+ struct expr *e1, *e2;
+
+ if (!e) {
+ e = expr_alloc_symbol(sym);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ }
+ switch (e->type) {
+ case E_AND:
+ e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+ e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(E_AND, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(E_OR, e1, e2);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ case E_OR:
+ e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+ e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(E_OR, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(E_AND, e1, e2);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ case E_NOT:
+ return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
+ case E_UNEQUAL:
+ case E_EQUAL:
+ if (type == E_EQUAL) {
+ if (sym == &symbol_yes)
+ return expr_copy(e);
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_no);
+ if (sym == &symbol_no)
+ return expr_alloc_one(E_NOT, expr_copy(e));
+ } else {
+ if (sym == &symbol_yes)
+ return expr_alloc_one(E_NOT, expr_copy(e));
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_yes);
+ if (sym == &symbol_no)
+ return expr_copy(e);
+ }
+ break;
+ case E_SYMBOL:
+ return expr_alloc_comp(type, e->left.sym, sym);
+ case E_LIST:
+ case E_RANGE:
+ case E_NONE:
+ /* panic */;
+ }
+ return NULL;
+}
+
+tristate expr_calc_value(struct expr *e)
+{
+ tristate val1, val2;
+ const char *str1, *str2;
+
+ if (!e)
+ return yes;
+
+ switch (e->type) {
+ case E_SYMBOL:
+ sym_calc_value(e->left.sym);
+ return e->left.sym->curr.tri;
+ case E_AND:
+ val1 = expr_calc_value(e->left.expr);
+ val2 = expr_calc_value(e->right.expr);
+ return EXPR_AND(val1, val2);
+ case E_OR:
+ val1 = expr_calc_value(e->left.expr);
+ val2 = expr_calc_value(e->right.expr);
+ return EXPR_OR(val1, val2);
+ case E_NOT:
+ val1 = expr_calc_value(e->left.expr);
+ return EXPR_NOT(val1);
+ case E_EQUAL:
+ sym_calc_value(e->left.sym);
+ sym_calc_value(e->right.sym);
+ str1 = sym_get_string_value(e->left.sym);
+ str2 = sym_get_string_value(e->right.sym);
+ return !strcmp(str1, str2) ? yes : no;
+ case E_UNEQUAL:
+ sym_calc_value(e->left.sym);
+ sym_calc_value(e->right.sym);
+ str1 = sym_get_string_value(e->left.sym);
+ str2 = sym_get_string_value(e->right.sym);
+ return !strcmp(str1, str2) ? no : yes;
+ default:
+ printf("expr_calc_value: %d?\n", e->type);
+ return no;
+ }
+}
+
+int expr_compare_type(enum expr_type t1, enum expr_type t2)
+{
+#if 0
+ return 1;
+#else
+ if (t1 == t2)
+ return 0;
+ switch (t1) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ if (t2 == E_NOT)
+ return 1;
+ case E_NOT:
+ if (t2 == E_AND)
+ return 1;
+ case E_AND:
+ if (t2 == E_OR)
+ return 1;
+ case E_OR:
+ if (t2 == E_LIST)
+ return 1;
+ case E_LIST:
+ if (t2 == 0)
+ return 1;
+ default:
+ return -1;
+ }
+ printf("[%dgt%d?]", t1, t2);
+ return 0;
+#endif
+}
+
+static inline struct expr *
+expr_get_leftmost_symbol(const struct expr *e)
+{
+
+ if (e == NULL)
+ return NULL;
+
+ while (e->type != E_SYMBOL)
+ e = e->left.expr;
+
+ return expr_copy(e);
+}
+
+/*
+ * Given expression `e1' and `e2', returns the leaf of the longest
+ * sub-expression of `e1' not containing 'e2.
+ */
+struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
+{
+ struct expr *ret;
+
+ switch (e1->type) {
+ case E_OR:
+ return expr_alloc_and(
+ expr_simplify_unmet_dep(e1->left.expr, e2),
+ expr_simplify_unmet_dep(e1->right.expr, e2));
+ case E_AND: {
+ struct expr *e;
+ e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
+ e = expr_eliminate_dups(e);
+ ret = (!expr_eq(e, e1)) ? e1 : NULL;
+ expr_free(e);
+ break;
+ }
+ default:
+ ret = e1;
+ break;
+ }
+
+ return expr_get_leftmost_symbol(ret);
+}
+
+void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
+{
+ if (!e) {
+ fn(data, NULL, "y");
+ return;
+ }
+
+ if (expr_compare_type(prevtoken, e->type) > 0)
+ fn(data, NULL, "(");
+ switch (e->type) {
+ case E_SYMBOL:
+ if (e->left.sym->name)
+ fn(data, e->left.sym, e->left.sym->name);
+ else
+ fn(data, NULL, "<choice>");
+ break;
+ case E_NOT:
+ fn(data, NULL, "!");
+ expr_print(e->left.expr, fn, data, E_NOT);
+ break;
+ case E_EQUAL:
+ if (e->left.sym->name)
+ fn(data, e->left.sym, e->left.sym->name);
+ else
+ fn(data, NULL, "<choice>");
+ fn(data, NULL, "=");
+ fn(data, e->right.sym, e->right.sym->name);
+ break;
+ case E_UNEQUAL:
+ if (e->left.sym->name)
+ fn(data, e->left.sym, e->left.sym->name);
+ else
+ fn(data, NULL, "<choice>");
+ 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, 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, NULL, " && ");
+ expr_print(e->right.expr, fn, data, E_AND);
+ break;
+ case E_LIST:
+ fn(data, e->right.sym, e->right.sym->name);
+ if (e->left.expr) {
+ fn(data, NULL, " ^ ");
+ expr_print(e->left.expr, fn, data, E_LIST);
+ }
+ break;
+ case E_RANGE:
+ 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, NULL, buf);
+ break;
+ }
+ }
+ if (expr_compare_type(prevtoken, e->type) > 0)
+ fn(data, NULL, ")");
+}
+
+static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
+{
+ xfwrite(str, strlen(str), 1, data);
+}
+
+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, struct symbol *sym, const char *str)
+{
+ struct gstr *gs = (struct gstr*)data;
+ const char *sym_str = NULL;
+
+ if (sym)
+ sym_str = sym_get_string_value(sym);
+
+ if (gs->max_width) {
+ unsigned extra_length = strlen(str);
+ const char *last_cr = strrchr(gs->s, '\n');
+ unsigned last_line_length;
+
+ if (sym_str)
+ extra_length += 4 + strlen(sym_str);
+
+ if (!last_cr)
+ last_cr = gs->s;
+
+ last_line_length = strlen(gs->s) - (last_cr - gs->s);
+
+ if ((last_line_length + extra_length) > gs->max_width)
+ str_append(gs, "\\\n");
+ }
+
+ str_append(gs, str);
+ if (sym && sym->type != S_UNKNOWN)
+ str_printf(gs, " [=%s]", sym_str);
+}
+
+void expr_gstr_print(struct expr *e, struct gstr *gs)
+{
+ expr_print(e, expr_print_gstr_helper, gs, E_NONE);
+}
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
new file mode 100644
index 0000000..cdd4860
--- /dev/null
+++ b/scripts/kconfig/expr.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef EXPR_H
+#define EXPR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include "list.h"
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+struct file {
+ struct file *next;
+ struct file *parent;
+ const char *name;
+ int lineno;
+};
+
+typedef enum tristate {
+ no, mod, yes
+} tristate;
+
+enum expr_type {
+ E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE
+};
+
+union expr_data {
+ struct expr *expr;
+ struct symbol *sym;
+};
+
+struct expr {
+ enum expr_type type;
+ union expr_data left, right;
+};
+
+#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
+#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
+#define EXPR_NOT(dep) (2-(dep))
+
+#define expr_list_for_each_sym(l, e, s) \
+ for (e = (l); e && (s = e->right.sym); e = e->left.expr)
+
+struct expr_value {
+ struct expr *expr;
+ tristate tri;
+};
+
+struct symbol_value {
+ void *val;
+ tristate tri;
+};
+
+enum symbol_type {
+ S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
+};
+
+/* enum values are used as index to symbol.def[] */
+enum {
+ S_DEF_USER, /* main user value */
+ S_DEF_AUTO, /* values read from auto.conf */
+ S_DEF_DEF3, /* Reserved for UI usage */
+ S_DEF_DEF4, /* Reserved for UI usage */
+ S_DEF_COUNT
+};
+
+struct symbol {
+ struct symbol *next;
+ char *name;
+ enum symbol_type type;
+ struct symbol_value curr;
+ struct symbol_value def[S_DEF_COUNT];
+ tristate visible;
+ int flags;
+ struct property *prop;
+ struct expr_value dir_dep;
+ struct expr_value rev_dep;
+};
+
+#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
+
+#define SYMBOL_CONST 0x0001 /* symbol is const */
+#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
+#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */
+#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */
+#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
+#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
+#define SYMBOL_WRITE 0x0200 /* ? */
+#define SYMBOL_CHANGED 0x0400 /* ? */
+#define SYMBOL_AUTO 0x1000 /* value from environment variable */
+#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
+#define SYMBOL_WARNED 0x8000 /* warning has been issued */
+
+/* Set when symbol.def[] is used */
+#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */
+#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */
+#define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */
+#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */
+#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */
+
+#define SYMBOL_MAXLENGTH 256
+#define SYMBOL_HASHSIZE 9973
+
+/* A property represent the config options that can be associated
+ * with a config "symbol".
+ * Sample:
+ * config FOO
+ * default y
+ * prompt "foo prompt"
+ * select BAR
+ * config BAZ
+ * int "BAZ Value"
+ * range 1..255
+ */
+enum prop_type {
+ P_UNKNOWN,
+ P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */
+ P_COMMENT, /* text associated with a comment */
+ P_MENU, /* prompt associated with a menuconfig option */
+ P_DEFAULT, /* default y */
+ P_CHOICE, /* choice value */
+ P_SELECT, /* select BAR */
+ P_RANGE, /* range 7..100 (for a symbol) */
+ P_ENV, /* value from environment variable */
+ P_SYMBOL, /* where a symbol is defined */
+};
+
+struct property {
+ struct property *next; /* next property - null if last */
+ struct symbol *sym; /* the symbol for which the property is associated */
+ enum prop_type type; /* type of property */
+ const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
+ struct expr_value visible;
+ struct expr *expr; /* the optional conditional part of the property */
+ struct menu *menu; /* the menu the property are associated with
+ * valid for: P_SELECT, P_RANGE, P_CHOICE,
+ * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */
+ struct file *file; /* what file was this property defined */
+ int lineno; /* what lineno was this property defined */
+};
+
+#define for_all_properties(sym, st, tok) \
+ for (st = sym->prop; st; st = st->next) \
+ if (st->type == (tok))
+#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
+#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
+#define for_all_prompts(sym, st) \
+ for (st = sym->prop; st; st = st->next) \
+ if (st->text)
+
+struct menu {
+ struct menu *next;
+ struct menu *parent;
+ struct menu *list;
+ struct symbol *sym;
+ struct property *prompt;
+ struct expr *visibility;
+ struct expr *dep;
+ unsigned int flags;
+ char *help;
+ struct file *file;
+ int lineno;
+ void *data;
+};
+
+#define MENU_CHANGED 0x0001
+#define MENU_ROOT 0x0002
+
+struct jump_key {
+ struct list_head entries;
+ size_t offset;
+ struct menu *target;
+ int index;
+};
+
+#define JUMP_NB 9
+
+extern struct file *file_list;
+extern struct file *current_file;
+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);
+struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
+struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
+struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
+struct expr *expr_copy(const struct expr *org);
+void expr_free(struct expr *e);
+int expr_eq(struct expr *e1, struct expr *e2);
+void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
+tristate expr_calc_value(struct expr *e);
+struct expr *expr_eliminate_yn(struct expr *e);
+struct expr *expr_trans_bool(struct expr *e);
+struct expr *expr_eliminate_dups(struct expr *e);
+struct expr *expr_transform(struct expr *e);
+int expr_contains_symbol(struct expr *dep, struct symbol *sym);
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
+struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
+struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
+void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
+struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
+struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2);
+
+void expr_fprint(struct expr *e, FILE *out);
+struct gstr; /* forward */
+void expr_gstr_print(struct expr *e, struct gstr *gs);
+
+static inline int expr_is_yes(struct expr *e)
+{
+ return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
+}
+
+static inline int expr_is_no(struct expr *e)
+{
+ return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EXPR_H */
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
new file mode 100644
index 0000000..f2bee70
--- /dev/null
+++ b/scripts/kconfig/gconf.c
@@ -0,0 +1,1542 @@
+/* Hey EMACS -*- linux-c -*- */
+/*
+ *
+ * Copyright (C) 2002-2003 Romain Lievin <roms at tilp.info>
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include "lkc.h"
+#include "images.c"
+
+#include <glade/glade.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+//#define DEBUG
+
+enum {
+ SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
+};
+
+enum {
+ OPT_NORMAL, OPT_ALL, OPT_PROMPT
+};
+
+static gint view_mode = FULL_VIEW;
+static gboolean show_name = TRUE;
+static gboolean show_range = TRUE;
+static gboolean show_value = TRUE;
+static gboolean resizeable = FALSE;
+static int opt_mode = OPT_NORMAL;
+
+GtkWidget *main_wnd = NULL;
+GtkWidget *tree1_w = NULL; // left frame
+GtkWidget *tree2_w = NULL; // right frame
+GtkWidget *text_w = NULL;
+GtkWidget *hpaned = NULL;
+GtkWidget *vpaned = NULL;
+GtkWidget *back_btn = NULL;
+GtkWidget *save_btn = NULL;
+GtkWidget *save_menu_item = NULL;
+
+GtkTextTag *tag1, *tag2;
+GdkColor color;
+
+GtkTreeStore *tree1, *tree2, *tree;
+GtkTreeModel *model1, *model2;
+static GtkTreeIter *parents[256];
+static gint indent;
+
+static struct menu *current; // current node for SINGLE view
+static struct menu *browsed; // browsed node for SPLIT view
+
+enum {
+ COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
+ COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
+ COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
+ COL_NUMBER
+};
+
+static void display_list(void);
+static void display_tree(struct menu *menu);
+static void display_tree_part(void);
+static void update_tree(struct menu *src, GtkTreeIter * dst);
+static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
+static gchar **fill_row(struct menu *menu);
+static void conf_changed(void);
+
+/* Helping/Debugging Functions */
+
+const char *dbg_sym_flags(int val)
+{
+ static char buf[256];
+
+ bzero(buf, 256);
+
+ if (val & SYMBOL_CONST)
+ strcat(buf, "const/");
+ if (val & SYMBOL_CHECK)
+ strcat(buf, "check/");
+ if (val & SYMBOL_CHOICE)
+ strcat(buf, "choice/");
+ if (val & SYMBOL_CHOICEVAL)
+ strcat(buf, "choiceval/");
+ if (val & SYMBOL_VALID)
+ strcat(buf, "valid/");
+ if (val & SYMBOL_OPTIONAL)
+ strcat(buf, "optional/");
+ if (val & SYMBOL_WRITE)
+ strcat(buf, "write/");
+ if (val & SYMBOL_CHANGED)
+ strcat(buf, "changed/");
+ if (val & SYMBOL_AUTO)
+ strcat(buf, "auto/");
+
+ buf[strlen(buf) - 1] = '\0';
+
+ return buf;
+}
+
+void replace_button_icon(GladeXML * xml, GdkDrawable * window,
+ GtkStyle * style, gchar * btn_name, gchar ** xpm)
+{
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+ GtkToolButton *button;
+ GtkWidget *image;
+
+ pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
+ &style->bg[GTK_STATE_NORMAL],
+ xpm);
+
+ button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
+ image = gtk_image_new_from_pixmap(pixmap, mask);
+ gtk_widget_show(image);
+ gtk_tool_button_set_icon_widget(button, image);
+}
+
+/* Main Window Initialization */
+void init_main_window(const gchar * glade_file)
+{
+ GladeXML *xml;
+ GtkWidget *widget;
+ GtkTextBuffer *txtbuf;
+ GtkStyle *style;
+
+ xml = glade_xml_new(glade_file, "window1", NULL);
+ if (!xml)
+ g_error(_("GUI loading failed !\n"));
+ glade_xml_signal_autoconnect(xml);
+
+ main_wnd = glade_xml_get_widget(xml, "window1");
+ hpaned = glade_xml_get_widget(xml, "hpaned1");
+ vpaned = glade_xml_get_widget(xml, "vpaned1");
+ tree1_w = glade_xml_get_widget(xml, "treeview1");
+ tree2_w = glade_xml_get_widget(xml, "treeview2");
+ text_w = glade_xml_get_widget(xml, "textview3");
+
+ back_btn = glade_xml_get_widget(xml, "button1");
+ gtk_widget_set_sensitive(back_btn, FALSE);
+
+ widget = glade_xml_get_widget(xml, "show_name1");
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_name);
+
+ widget = glade_xml_get_widget(xml, "show_range1");
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_range);
+
+ widget = glade_xml_get_widget(xml, "show_data1");
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_value);
+
+ save_btn = glade_xml_get_widget(xml, "button3");
+ save_menu_item = glade_xml_get_widget(xml, "save1");
+ conf_set_changed_callback(conf_changed);
+
+ style = gtk_widget_get_style(main_wnd);
+ widget = glade_xml_get_widget(xml, "toolbar1");
+
+#if 0 /* Use stock Gtk icons instead */
+ replace_button_icon(xml, main_wnd->window, style,
+ "button1", (gchar **) xpm_back);
+ replace_button_icon(xml, main_wnd->window, style,
+ "button2", (gchar **) xpm_load);
+ replace_button_icon(xml, main_wnd->window, style,
+ "button3", (gchar **) xpm_save);
+#endif
+ replace_button_icon(xml, main_wnd->window, style,
+ "button4", (gchar **) xpm_single_view);
+ replace_button_icon(xml, main_wnd->window, style,
+ "button5", (gchar **) xpm_split_view);
+ replace_button_icon(xml, main_wnd->window, style,
+ "button6", (gchar **) xpm_tree_view);
+
+#if 0
+ switch (view_mode) {
+ case SINGLE_VIEW:
+ widget = glade_xml_get_widget(xml, "button4");
+ g_signal_emit_by_name(widget, "clicked");
+ break;
+ case SPLIT_VIEW:
+ widget = glade_xml_get_widget(xml, "button5");
+ g_signal_emit_by_name(widget, "clicked");
+ break;
+ case FULL_VIEW:
+ widget = glade_xml_get_widget(xml, "button6");
+ g_signal_emit_by_name(widget, "clicked");
+ break;
+ }
+#endif
+ txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+ tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
+ "foreground", "red",
+ "weight", PANGO_WEIGHT_BOLD,
+ NULL);
+ tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
+ /*"style", PANGO_STYLE_OBLIQUE, */
+ NULL);
+
+ gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
+
+ gtk_widget_show(main_wnd);
+}
+
+void init_tree_model(void)
+{
+ gint i;
+
+ tree = tree2 = gtk_tree_store_new(COL_NUMBER,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_POINTER, GDK_TYPE_COLOR,
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
+ model2 = GTK_TREE_MODEL(tree2);
+
+ for (parents[0] = NULL, i = 1; i < 256; i++)
+ parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
+
+ tree1 = gtk_tree_store_new(COL_NUMBER,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_POINTER, GDK_TYPE_COLOR,
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
+ model1 = GTK_TREE_MODEL(tree1);
+}
+
+void init_left_tree(void)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *sel;
+ GtkTreeViewColumn *column;
+
+ gtk_tree_view_set_model(view, model1);
+ gtk_tree_view_set_headers_visible(view, TRUE);
+ gtk_tree_view_set_rules_hint(view, TRUE);
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(view, column);
+ gtk_tree_view_column_set_title(column, _("Options"));
+
+ renderer = gtk_cell_renderer_toggle_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "active", COL_BTNACT,
+ "inconsistent", COL_BTNINC,
+ "visible", COL_BTNVIS,
+ "radio", COL_BTNRAD, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "text", COL_OPTION,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+
+ sel = gtk_tree_view_get_selection(view);
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+ gtk_widget_realize(tree1_w);
+}
+
+static void renderer_edited(GtkCellRendererText * cell,
+ const gchar * path_string,
+ const gchar * new_text, gpointer user_data);
+
+void init_right_tree(void)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *sel;
+ GtkTreeViewColumn *column;
+ gint i;
+
+ gtk_tree_view_set_model(view, model2);
+ gtk_tree_view_set_headers_visible(view, TRUE);
+ gtk_tree_view_set_rules_hint(view, TRUE);
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(view, column);
+ gtk_tree_view_column_set_title(column, _("Options"));
+
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "pixbuf", COL_PIXBUF,
+ "visible", COL_PIXVIS, NULL);
+ renderer = gtk_cell_renderer_toggle_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "active", COL_BTNACT,
+ "inconsistent", COL_BTNINC,
+ "visible", COL_BTNVIS,
+ "radio", COL_BTNRAD, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "text", COL_OPTION,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ _("Name"), renderer,
+ "text", COL_NAME,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "N", renderer,
+ "text", COL_NO,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "M", renderer,
+ "text", COL_MOD,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "Y", renderer,
+ "text", COL_YES,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ _("Value"), renderer,
+ "text", COL_VALUE,
+ "editable",
+ COL_EDIT,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ g_signal_connect(G_OBJECT(renderer), "edited",
+ G_CALLBACK(renderer_edited), NULL);
+
+ column = gtk_tree_view_get_column(view, COL_NAME);
+ gtk_tree_view_column_set_visible(column, show_name);
+ column = gtk_tree_view_get_column(view, COL_NO);
+ gtk_tree_view_column_set_visible(column, show_range);
+ column = gtk_tree_view_get_column(view, COL_MOD);
+ gtk_tree_view_column_set_visible(column, show_range);
+ column = gtk_tree_view_get_column(view, COL_YES);
+ gtk_tree_view_column_set_visible(column, show_range);
+ column = gtk_tree_view_get_column(view, COL_VALUE);
+ gtk_tree_view_column_set_visible(column, show_value);
+
+ if (resizeable) {
+ for (i = 0; i < COL_VALUE; i++) {
+ column = gtk_tree_view_get_column(view, i);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ }
+ }
+
+ sel = gtk_tree_view_get_selection(view);
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+}
+
+
+/* Utility Functions */
+
+
+static void text_insert_help(struct menu *menu)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ const char *prompt = _(menu_get_prompt(menu));
+ struct gstr help = str_new();
+
+ menu_get_ext_help(menu, &help);
+
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gtk_text_buffer_delete(buffer, &start, &end);
+ gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
+ NULL);
+ gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
+ NULL);
+ str_free(&help);
+}
+
+
+static void text_insert_msg(const char *title, const char *message)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ const char *msg = message;
+
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gtk_text_buffer_delete(buffer, &start, &end);
+ gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
+ NULL);
+ gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
+ NULL);
+}
+
+
+/* Main Windows Callbacks */
+
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
+gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
+ gpointer user_data)
+{
+ GtkWidget *dialog, *label;
+ gint result;
+
+ if (!conf_get_changed())
+ return FALSE;
+
+ dialog = gtk_dialog_new_with_buttons(_("Warning !"),
+ GTK_WINDOW(main_wnd),
+ (GtkDialogFlags)
+ (GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT),
+ GTK_STOCK_OK,
+ GTK_RESPONSE_YES,
+ GTK_STOCK_NO,
+ GTK_RESPONSE_NO,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_CANCEL);
+
+ label = gtk_label_new(_("\nSave configuration ?\n"));
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+ gtk_widget_show(label);
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_YES:
+ on_save_activate(NULL, NULL);
+ return FALSE;
+ case GTK_RESPONSE_NO:
+ return FALSE;
+ case GTK_RESPONSE_CANCEL:
+ case GTK_RESPONSE_DELETE_EVENT:
+ default:
+ gtk_widget_destroy(dialog);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+void on_window1_destroy(GtkObject * object, gpointer user_data)
+{
+ gtk_main_quit();
+}
+
+
+void
+on_window1_size_request(GtkWidget * widget,
+ GtkRequisition * requisition, gpointer user_data)
+{
+ static gint old_h;
+ gint w, h;
+
+ if (widget->window == NULL)
+ gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
+ else
+ gdk_window_get_size(widget->window, &w, &h);
+
+ if (h == old_h)
+ return;
+ old_h = h;
+
+ gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
+}
+
+
+/* Menu & Toolbar Callbacks */
+
+
+static void
+load_filename(GtkFileSelection * file_selector, gpointer user_data)
+{
+ const gchar *fn;
+
+ fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
+ (user_data));
+
+ if (conf_read(fn))
+ text_insert_msg(_("Error"), _("Unable to load configuration !"));
+ else
+ display_tree(&rootmenu);
+}
+
+void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *fs;
+
+ fs = gtk_file_selection_new(_("Load file..."));
+ g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
+ "clicked",
+ G_CALLBACK(load_filename), (gpointer) fs);
+ g_signal_connect_swapped(GTK_OBJECT
+ (GTK_FILE_SELECTION(fs)->ok_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ (gpointer) fs);
+ g_signal_connect_swapped(GTK_OBJECT
+ (GTK_FILE_SELECTION(fs)->cancel_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ (gpointer) fs);
+ gtk_widget_show(fs);
+}
+
+
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ if (conf_write(NULL))
+ text_insert_msg(_("Error"), _("Unable to save configuration !"));
+}
+
+
+static void
+store_filename(GtkFileSelection * file_selector, gpointer user_data)
+{
+ const gchar *fn;
+
+ fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
+ (user_data));
+
+ if (conf_write(fn))
+ text_insert_msg(_("Error"), _("Unable to save configuration !"));
+
+ gtk_widget_destroy(GTK_WIDGET(user_data));
+}
+
+void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *fs;
+
+ fs = gtk_file_selection_new(_("Save file as..."));
+ g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
+ "clicked",
+ G_CALLBACK(store_filename), (gpointer) fs);
+ g_signal_connect_swapped(GTK_OBJECT
+ (GTK_FILE_SELECTION(fs)->ok_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ (gpointer) fs);
+ g_signal_connect_swapped(GTK_OBJECT
+ (GTK_FILE_SELECTION(fs)->cancel_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ (gpointer) fs);
+ gtk_widget_show(fs);
+}
+
+
+void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ if (!on_window1_delete_event(NULL, NULL, NULL))
+ gtk_widget_destroy(GTK_WIDGET(main_wnd));
+}
+
+
+void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkTreeViewColumn *col;
+
+ show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_name);
+}
+
+
+void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkTreeViewColumn *col;
+
+ show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_range);
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_range);
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_range);
+
+}
+
+
+void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkTreeViewColumn *col;
+
+ show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_value);
+}
+
+
+void
+on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+ opt_mode = OPT_NORMAL;
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
+}
+
+
+void
+on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+ opt_mode = OPT_ALL;
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
+}
+
+
+void
+on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+ opt_mode = OPT_PROMPT;
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
+}
+
+
+void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *dialog;
+ const gchar *intro_text = _(
+ "Welcome to gkc, the GTK+ graphical configuration tool\n"
+ "For each option, a blank box indicates the feature is disabled, a\n"
+ "check indicates it is enabled, and a dot indicates that it is to\n"
+ "be compiled as a module. Clicking on the box will cycle through the three states.\n"
+ "\n"
+ "If you do not see an option (e.g., a device driver) that you\n"
+ "believe should be present, try turning on Show All Options\n"
+ "under the Options menu.\n"
+ "Although there is no cross reference yet to help you figure out\n"
+ "what other options must be enabled to support the option you\n"
+ "are interested in, you can still view the help of a grayed-out\n"
+ "option.\n"
+ "\n"
+ "Toggling Show Debug Info under the Options menu will show \n"
+ "the dependencies, which you can then match by examining other options.");
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE, "%s", intro_text);
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+ gtk_widget_show_all(dialog);
+}
+
+
+void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *dialog;
+ const gchar *about_text =
+ _("gkc is copyright (c) 2002 Romain Lievin <roms at lpg.ticalc.org>.\n"
+ "Based on the source code from Roman Zippel.\n");
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE, "%s", about_text);
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+ gtk_widget_show_all(dialog);
+}
+
+
+void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *dialog;
+ const gchar *license_text =
+ _("gkc is released under the terms of the GNU GPL v2.\n"
+ "For more information, please see the source code or\n"
+ "visit http://www.fsf.org/licenses/licenses.html\n");
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE, "%s", license_text);
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+ gtk_widget_show_all(dialog);
+}
+
+
+void on_back_clicked(GtkButton * button, gpointer user_data)
+{
+ enum prop_type ptype;
+
+ current = current->parent;
+ ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
+ if (ptype != P_MENU)
+ current = current->parent;
+ display_tree_part();
+
+ if (current == &rootmenu)
+ gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_load_clicked(GtkButton * button, gpointer user_data)
+{
+ on_load1_activate(NULL, user_data);
+}
+
+
+void on_single_clicked(GtkButton * button, gpointer user_data)
+{
+ view_mode = SINGLE_VIEW;
+ gtk_widget_hide(tree1_w);
+ current = &rootmenu;
+ display_tree_part();
+}
+
+
+void on_split_clicked(GtkButton * button, gpointer user_data)
+{
+ gint w, h;
+ view_mode = SPLIT_VIEW;
+ gtk_widget_show(tree1_w);
+ gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
+ gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
+ if (tree2)
+ gtk_tree_store_clear(tree2);
+ display_list();
+
+ /* Disable back btn, like in full mode. */
+ gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_full_clicked(GtkButton * button, gpointer user_data)
+{
+ view_mode = FULL_VIEW;
+ gtk_widget_hide(tree1_w);
+ if (tree2)
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu);
+ gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_collapse_clicked(GtkButton * button, gpointer user_data)
+{
+ gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
+}
+
+
+void on_expand_clicked(GtkButton * button, gpointer user_data)
+{
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
+
+
+/* CTree Callbacks */
+
+/* Change hex/int/string value in the cell */
+static void renderer_edited(GtkCellRendererText * cell,
+ const gchar * path_string,
+ const gchar * new_text, gpointer user_data)
+{
+ GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
+ GtkTreeIter iter;
+ const char *old_def, *new_def;
+ struct menu *menu;
+ struct symbol *sym;
+
+ if (!gtk_tree_model_get_iter(model2, &iter, path))
+ return;
+
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ sym = menu->sym;
+
+ gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
+ new_def = new_text;
+
+ sym_set_string_value(sym, new_def);
+
+ update_tree(&rootmenu, NULL);
+
+ gtk_tree_path_free(path);
+}
+
+/* Change the value of a symbol and update the tree */
+static void change_sym_value(struct menu *menu, gint col)
+{
+ struct symbol *sym = menu->sym;
+ tristate newval;
+
+ if (!sym)
+ return;
+
+ if (col == COL_NO)
+ newval = no;
+ else if (col == COL_MOD)
+ newval = mod;
+ else if (col == COL_YES)
+ newval = yes;
+ else
+ return;
+
+ switch (sym_get_type(sym)) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (!sym_tristate_within_range(sym, newval))
+ newval = yes;
+ sym_set_tristate_value(sym, newval);
+ if (view_mode == FULL_VIEW)
+ update_tree(&rootmenu, NULL);
+ else if (view_mode == SPLIT_VIEW) {
+ update_tree(browsed, NULL);
+ display_list();
+ }
+ else if (view_mode == SINGLE_VIEW)
+ display_tree_part(); //fixme: keep exp/coll
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ default:
+ break;
+ }
+}
+
+static void toggle_sym_value(struct menu *menu)
+{
+ if (!menu->sym)
+ return;
+
+ sym_toggle_tristate_value(menu->sym);
+ if (view_mode == FULL_VIEW)
+ update_tree(&rootmenu, NULL);
+ else if (view_mode == SPLIT_VIEW) {
+ update_tree(browsed, NULL);
+ display_list();
+ }
+ else if (view_mode == SINGLE_VIEW)
+ display_tree_part(); //fixme: keep exp/coll
+}
+
+static gint column2index(GtkTreeViewColumn * column)
+{
+ gint i;
+
+ for (i = 0; i < COL_NUMBER; i++) {
+ GtkTreeViewColumn *col;
+
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
+ if (col == column)
+ return i;
+ }
+
+ return -1;
+}
+
+
+/* User click: update choice (full) or goes down (single) */
+gboolean
+on_treeview2_button_press_event(GtkWidget * widget,
+ GdkEventButton * event, gpointer user_data)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ GtkTreeIter iter;
+ struct menu *menu;
+ gint col;
+
+#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
+ gint tx = (gint) event->x;
+ gint ty = (gint) event->y;
+ gint cx, cy;
+
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
+ &cy);
+#else
+ gtk_tree_view_get_cursor(view, &path, &column);
+#endif
+ if (path == NULL)
+ return FALSE;
+
+ if (!gtk_tree_model_get_iter(model2, &iter, path))
+ return FALSE;
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+
+ col = column2index(column);
+ if (event->type == GDK_2BUTTON_PRESS) {
+ enum prop_type ptype;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+
+ if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
+ // goes down into menu
+ current = menu;
+ display_tree_part();
+ gtk_widget_set_sensitive(back_btn, TRUE);
+ } else if ((col == COL_OPTION)) {
+ toggle_sym_value(menu);
+ gtk_tree_view_expand_row(view, path, TRUE);
+ }
+ } else {
+ if (col == COL_VALUE) {
+ toggle_sym_value(menu);
+ gtk_tree_view_expand_row(view, path, TRUE);
+ } else if (col == COL_NO || col == COL_MOD
+ || col == COL_YES) {
+ change_sym_value(menu, col);
+ gtk_tree_view_expand_row(view, path, TRUE);
+ }
+ }
+
+ return FALSE;
+}
+
+/* Key pressed: update choice */
+gboolean
+on_treeview2_key_press_event(GtkWidget * widget,
+ GdkEventKey * event, gpointer user_data)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ GtkTreeIter iter;
+ struct menu *menu;
+ gint col;
+
+ gtk_tree_view_get_cursor(view, &path, &column);
+ if (path == NULL)
+ return FALSE;
+
+ if (event->keyval == GDK_space) {
+ if (gtk_tree_view_row_expanded(view, path))
+ gtk_tree_view_collapse_row(view, path);
+ else
+ gtk_tree_view_expand_row(view, path, FALSE);
+ return TRUE;
+ }
+ if (event->keyval == GDK_KP_Enter) {
+ }
+ if (widget == tree1_w)
+ return FALSE;
+
+ gtk_tree_model_get_iter(model2, &iter, path);
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+
+ if (!strcasecmp(event->string, "n"))
+ col = COL_NO;
+ else if (!strcasecmp(event->string, "m"))
+ col = COL_MOD;
+ else if (!strcasecmp(event->string, "y"))
+ col = COL_YES;
+ else
+ col = -1;
+ change_sym_value(menu, col);
+
+ return FALSE;
+}
+
+
+/* Row selection changed: update help */
+void
+on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ struct menu *menu;
+
+ selection = gtk_tree_view_get_selection(treeview);
+ if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ text_insert_help(menu);
+ }
+}
+
+
+/* User click: display sub-tree in the right frame. */
+gboolean
+on_treeview1_button_press_event(GtkWidget * widget,
+ GdkEventButton * event, gpointer user_data)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ GtkTreeIter iter;
+ struct menu *menu;
+
+ gint tx = (gint) event->x;
+ gint ty = (gint) event->y;
+ gint cx, cy;
+
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
+ &cy);
+ if (path == NULL)
+ return FALSE;
+
+ gtk_tree_model_get_iter(model1, &iter, path);
+ gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
+
+ if (event->type == GDK_2BUTTON_PRESS) {
+ toggle_sym_value(menu);
+ current = menu;
+ display_tree_part();
+ } else {
+ browsed = menu;
+ display_tree_part();
+ }
+
+ gtk_widget_realize(tree2_w);
+ gtk_tree_view_set_cursor(view, path, NULL, FALSE);
+ gtk_widget_grab_focus(tree2_w);
+
+ return FALSE;
+}
+
+
+/* Fill a row of strings */
+static gchar **fill_row(struct menu *menu)
+{
+ static gchar *row[COL_NUMBER];
+ struct symbol *sym = menu->sym;
+ const char *def;
+ int stype;
+ tristate val;
+ enum prop_type ptype;
+ int i;
+
+ for (i = COL_OPTION; i <= COL_COLOR; i++)
+ g_free(row[i]);
+ bzero(row, sizeof(row));
+
+ row[COL_OPTION] =
+ g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
+ sym && !sym_has_value(sym) ? "(NEW)" : "");
+
+ if (opt_mode == OPT_ALL && !menu_is_visible(menu))
+ row[COL_COLOR] = g_strdup("DarkGray");
+ else if (opt_mode == OPT_PROMPT &&
+ menu_has_prompt(menu) && !menu_is_visible(menu))
+ row[COL_COLOR] = g_strdup("DarkGray");
+ else
+ row[COL_COLOR] = g_strdup("Black");
+
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ switch (ptype) {
+ case P_MENU:
+ row[COL_PIXBUF] = (gchar *) xpm_menu;
+ if (view_mode == SINGLE_VIEW)
+ row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+ break;
+ case P_COMMENT:
+ row[COL_PIXBUF] = (gchar *) xpm_void;
+ row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+ break;
+ default:
+ row[COL_PIXBUF] = (gchar *) xpm_void;
+ row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
+ row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
+ break;
+ }
+
+ if (!sym)
+ return row;
+ row[COL_NAME] = g_strdup(sym->name);
+
+ sym_calc_value(sym);
+ sym->flags &= ~SYMBOL_CHANGED;
+
+ if (sym_is_choice(sym)) { // parse childs for getting final value
+ struct menu *child;
+ struct symbol *def_sym = sym_get_choice_value(sym);
+ struct menu *def_menu = NULL;
+
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child)
+ && child->sym == def_sym)
+ def_menu = child;
+ }
+
+ if (def_menu)
+ row[COL_VALUE] =
+ g_strdup(_(menu_get_prompt(def_menu)));
+ }
+ if (sym->flags & SYMBOL_CHOICEVAL)
+ row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
+
+ stype = sym_get_type(sym);
+ switch (stype) {
+ case S_BOOLEAN:
+ if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
+ row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
+ if (sym_is_choice(sym))
+ break;
+ /* fall through */
+ case S_TRISTATE:
+ val = sym_get_tristate_value(sym);
+ switch (val) {
+ case no:
+ row[COL_NO] = g_strdup("N");
+ row[COL_VALUE] = g_strdup("N");
+ row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
+ row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
+ break;
+ case mod:
+ row[COL_MOD] = g_strdup("M");
+ row[COL_VALUE] = g_strdup("M");
+ row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
+ break;
+ case yes:
+ row[COL_YES] = g_strdup("Y");
+ row[COL_VALUE] = g_strdup("Y");
+ row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
+ row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
+ break;
+ }
+
+ if (val != no && sym_tristate_within_range(sym, no))
+ row[COL_NO] = g_strdup("_");
+ if (val != mod && sym_tristate_within_range(sym, mod))
+ row[COL_MOD] = g_strdup("_");
+ if (val != yes && sym_tristate_within_range(sym, yes))
+ row[COL_YES] = g_strdup("_");
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ def = sym_get_string_value(sym);
+ row[COL_VALUE] = g_strdup(def);
+ row[COL_EDIT] = GINT_TO_POINTER(TRUE);
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+ break;
+ }
+
+ return row;
+}
+
+
+/* Set the node content with a row of strings */
+static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
+{
+ GdkColor color;
+ gboolean success;
+ GdkPixbuf *pix;
+
+ pix = gdk_pixbuf_new_from_xpm_data((const char **)
+ row[COL_PIXBUF]);
+
+ gdk_color_parse(row[COL_COLOR], &color);
+ gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
+ FALSE, FALSE, &success);
+
+ gtk_tree_store_set(tree, node,
+ COL_OPTION, row[COL_OPTION],
+ COL_NAME, row[COL_NAME],
+ COL_NO, row[COL_NO],
+ COL_MOD, row[COL_MOD],
+ COL_YES, row[COL_YES],
+ COL_VALUE, row[COL_VALUE],
+ COL_MENU, (gpointer) menu,
+ COL_COLOR, &color,
+ COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
+ COL_PIXBUF, pix,
+ COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
+ COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
+ COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
+ COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
+ COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
+ -1);
+
+ g_object_unref(pix);
+}
+
+
+/* Add a node to the tree */
+static void place_node(struct menu *menu, char **row)
+{
+ GtkTreeIter *parent = parents[indent - 1];
+ GtkTreeIter *node = parents[indent];
+
+ gtk_tree_store_append(tree, node, parent);
+ set_node(node, menu, row);
+}
+
+
+/* Find a node in the GTK+ tree */
+static GtkTreeIter found;
+
+/*
+ * Find a menu in the GtkTree starting at parent.
+ */
+GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
+ struct menu *tofind)
+{
+ GtkTreeIter iter;
+ GtkTreeIter *child = &iter;
+ gboolean valid;
+ GtkTreeIter *ret;
+
+ valid = gtk_tree_model_iter_children(model2, child, parent);
+ while (valid) {
+ struct menu *menu;
+
+ gtk_tree_model_get(model2, child, 6, &menu, -1);
+
+ if (menu == tofind) {
+ memcpy(&found, child, sizeof(GtkTreeIter));
+ return &found;
+ }
+
+ ret = gtktree_iter_find_node(child, tofind);
+ if (ret)
+ return ret;
+
+ valid = gtk_tree_model_iter_next(model2, child);
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Update the tree by adding/removing entries
+ * Does not change other nodes
+ */
+static void update_tree(struct menu *src, GtkTreeIter * dst)
+{
+ struct menu *child1;
+ GtkTreeIter iter, tmp;
+ GtkTreeIter *child2 = &iter;
+ gboolean valid;
+ GtkTreeIter *sibling;
+ struct symbol *sym;
+ struct menu *menu1, *menu2;
+
+ if (src == &rootmenu)
+ indent = 1;
+
+ valid = gtk_tree_model_iter_children(model2, child2, dst);
+ for (child1 = src->list; child1; child1 = child1->next) {
+
+ sym = child1->sym;
+
+ reparse:
+ menu1 = child1;
+ if (valid)
+ gtk_tree_model_get(model2, child2, COL_MENU,
+ &menu2, -1);
+ else
+ menu2 = NULL; // force adding of a first child
+
+#ifdef DEBUG
+ printf("%*c%s | %s\n", indent, ' ',
+ menu1 ? menu_get_prompt(menu1) : "nil",
+ menu2 ? menu_get_prompt(menu2) : "nil");
+#endif
+
+ if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
+ (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
+ (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
+
+ /* remove node */
+ if (gtktree_iter_find_node(dst, menu1) != NULL) {
+ memcpy(&tmp, child2, sizeof(GtkTreeIter));
+ valid = gtk_tree_model_iter_next(model2,
+ child2);
+ gtk_tree_store_remove(tree2, &tmp);
+ if (!valid)
+ return; /* next parent */
+ else
+ goto reparse; /* next child */
+ } else
+ continue;
+ }
+
+ if (menu1 != menu2) {
+ if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
+ if (!valid && !menu2)
+ sibling = NULL;
+ else
+ sibling = child2;
+ gtk_tree_store_insert_before(tree2,
+ child2,
+ dst, sibling);
+ set_node(child2, menu1, fill_row(menu1));
+ if (menu2 == NULL)
+ valid = TRUE;
+ } else { // remove node
+ memcpy(&tmp, child2, sizeof(GtkTreeIter));
+ valid = gtk_tree_model_iter_next(model2,
+ child2);
+ gtk_tree_store_remove(tree2, &tmp);
+ if (!valid)
+ return; // next parent
+ else
+ goto reparse; // next child
+ }
+ } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
+ set_node(child2, menu1, fill_row(menu1));
+ }
+
+ indent++;
+ update_tree(child1, child2);
+ indent--;
+
+ valid = gtk_tree_model_iter_next(model2, child2);
+ }
+}
+
+
+/* Display the whole tree (single/split/full view) */
+static void display_tree(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+ enum prop_type ptype;
+
+ if (menu == &rootmenu) {
+ indent = 1;
+ current = &rootmenu;
+ }
+
+ for (child = menu->list; child; child = child->next) {
+ prop = child->prompt;
+ sym = child->sym;
+ ptype = prop ? prop->type : P_UNKNOWN;
+
+ if (sym)
+ sym->flags &= ~SYMBOL_CHANGED;
+
+ if ((view_mode == SPLIT_VIEW)
+ && !(child->flags & MENU_ROOT) && (tree == tree1))
+ continue;
+
+ if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
+ && (tree == tree2))
+ continue;
+
+ if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
+ (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
+ (opt_mode == OPT_ALL && menu_get_prompt(child)))
+ place_node(child, fill_row(child));
+#ifdef DEBUG
+ printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
+ printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
+ printf("%s", prop_get_type_name(ptype));
+ printf(" | ");
+ if (sym) {
+ printf("%s", sym_type_name(sym->type));
+ printf(" | ");
+ printf("%s", dbg_sym_flags(sym->flags));
+ printf("\n");
+ } else
+ printf("\n");
+#endif
+ if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
+ && (tree == tree2))
+ continue;
+/*
+ if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
+ || (view_mode == FULL_VIEW)
+ || (view_mode == SPLIT_VIEW))*/
+
+ /* Change paned position if the view is not in 'split mode' */
+ if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {
+ gtk_paned_set_position(GTK_PANED(hpaned), 0);
+ }
+
+ if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
+ || (view_mode == FULL_VIEW)
+ || (view_mode == SPLIT_VIEW)) {
+ indent++;
+ display_tree(child);
+ indent--;
+ }
+ }
+}
+
+/* Display a part of the tree starting at current node (single/split view) */
+static void display_tree_part(void)
+{
+ if (tree2)
+ gtk_tree_store_clear(tree2);
+ if (view_mode == SINGLE_VIEW)
+ display_tree(current);
+ else if (view_mode == SPLIT_VIEW)
+ display_tree(browsed);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
+
+/* Display the list in the left frame (split view) */
+static void display_list(void)
+{
+ if (tree1)
+ gtk_tree_store_clear(tree1);
+
+ tree = tree1;
+ display_tree(&rootmenu);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
+ tree = tree2;
+}
+
+void fixup_rootmenu(struct menu *menu)
+{
+ struct menu *child;
+ static int menu_cnt = 0;
+
+ menu->flags |= MENU_ROOT;
+ for (child = menu->list; child; child = child->next) {
+ if (child->prompt && child->prompt->type == P_MENU) {
+ menu_cnt++;
+ fixup_rootmenu(child);
+ menu_cnt--;
+ } else if (!menu_cnt)
+ fixup_rootmenu(child);
+ }
+}
+
+
+/* Main */
+int main(int ac, char *av[])
+{
+ const char *name;
+ char *env;
+ gchar *glade_file;
+
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset(PACKAGE, "UTF-8");
+ textdomain(PACKAGE);
+
+ /* GTK stuffs */
+ gtk_set_locale();
+ gtk_init(&ac, &av);
+ glade_init();
+
+ //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
+ //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
+
+ /* Determine GUI path */
+ env = getenv(SRCTREE);
+ if (env)
+ glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
+ else if (av[0][0] == '/')
+ glade_file = g_strconcat(av[0], ".glade", NULL);
+ else
+ glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
+
+ /* Conf stuffs */
+ if (ac > 1 && av[1][0] == '-') {
+ switch (av[1][1]) {
+ case 'a':
+ //showAll = 1;
+ break;
+ case 'h':
+ case '?':
+ printf("%s <config>\n", av[0]);
+ exit(0);
+ }
+ name = av[2];
+ } else
+ name = av[1];
+
+ conf_parse(name);
+ fixup_rootmenu(&rootmenu);
+ conf_read(NULL);
+
+ /* Load the interface and connect signals */
+ init_main_window(glade_file);
+ init_tree_model();
+ init_left_tree();
+ init_right_tree();
+
+ switch (view_mode) {
+ case SINGLE_VIEW:
+ display_tree_part();
+ break;
+ case SPLIT_VIEW:
+ display_list();
+ break;
+ case FULL_VIEW:
+ display_tree(&rootmenu);
+ break;
+ }
+
+ gtk_main();
+
+ return 0;
+}
+
+static void conf_changed(void)
+{
+ bool changed = conf_get_changed();
+ gtk_widget_set_sensitive(save_btn, changed);
+ gtk_widget_set_sensitive(save_menu_item, changed);
+}
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
new file mode 100644
index 0000000..aa483cb
--- /dev/null
+++ b/scripts/kconfig/gconf.glade
@@ -0,0 +1,661 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+
+<glade-interface>
+
+<widget class="GtkWindow" id="window1">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Gtk Kernel Configurator</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="default_width">640</property>
+ <property name="default_height">480</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <signal name="destroy" handler="on_window1_destroy" object="window1"/>
+ <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/>
+ <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkMenuBar" id="menubar1">
+ <property name="visible">True</property>
+
+ <child>
+ <widget class="GtkMenuItem" id="file1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="file1_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="load1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Load a config file</property>
+ <property name="label" translatable="yes">_Load</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_load1_activate"/>
+ <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image39">
+ <property name="visible">True</property>
+ <property name="stock">gtk-open</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="save1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Save the config in .config</property>
+ <property name="label" translatable="yes">_Save</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_save_activate"/>
+ <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image40">
+ <property name="visible">True</property>
+ <property name="stock">gtk-save</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="save_as1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Save the config in a file</property>
+ <property name="label" translatable="yes">Save _as</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_save_as1_activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image41">
+ <property name="visible">True</property>
+ <property name="stock">gtk-save-as</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator1">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="quit1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Quit</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_quit1_activate"/>
+ <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image42">
+ <property name="visible">True</property>
+ <property name="stock">gtk-quit</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="options1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Options</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="options1_menu">
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="show_name1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show name</property>
+ <property name="label" translatable="yes">Show _name</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="on_show_name1_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="show_range1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
+ <property name="label" translatable="yes">Show _range</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="on_show_range1_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="show_data1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show value of the option</property>
+ <property name="label" translatable="yes">Show _data</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="on_show_data1_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator2">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkRadioMenuItem" id="set_option_mode1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show normal options</property>
+ <property name="label" translatable="yes">Show normal options</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <signal name="activate" handler="on_set_option_mode1_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkRadioMenuItem" id="set_option_mode2">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show all options</property>
+ <property name="label" translatable="yes">Show all _options</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <property name="group">set_option_mode1</property>
+ <signal name="activate" handler="on_set_option_mode2_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkRadioMenuItem" id="set_option_mode3">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show all options with prompts</property>
+ <property name="label" translatable="yes">Show all prompt options</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <property name="group">set_option_mode1</property>
+ <signal name="activate" handler="on_set_option_mode3_activate"/>
+ </widget>
+ </child>
+
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="help1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="help1_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="introduction1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Introduction</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+ <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image43">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-question</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="about1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_About</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+ <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image44">
+ <property name="visible">True</property>
+ <property name="stock">gtk-properties</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="license1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_License</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image45">
+ <property name="visible">True</property>
+ <property name="stock">gtk-justify-fill</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHandleBox" id="handlebox1">
+ <property name="visible">True</property>
+ <property name="shadow_type">GTK_SHADOW_OUT</property>
+ <property name="handle_position">GTK_POS_LEFT</property>
+ <property name="snap_edge">GTK_POS_TOP</property>
+
+ <child>
+ <widget class="GtkToolbar" id="toolbar1">
+ <property name="visible">True</property>
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
+ <property name="tooltips">True</property>
+ <property name="show_arrow">True</property>
+
+ <child>
+ <widget class="GtkToolButton" id="button1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
+ <property name="label" translatable="yes">Back</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-undo</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_back_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolItem" id="toolitem1">
+ <property name="visible">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+
+ <child>
+ <widget class="GtkVSeparator" id="vseparator1">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button2">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Load a config file</property>
+ <property name="label" translatable="yes">Load</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-open</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_load_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button3">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Save a config file</property>
+ <property name="label" translatable="yes">Save</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-save</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_save_activate"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolItem" id="toolitem2">
+ <property name="visible">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+
+ <child>
+ <widget class="GtkVSeparator" id="vseparator2">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button4">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Single view</property>
+ <property name="label" translatable="yes">Single</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-missing-image</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button5">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Split view</property>
+ <property name="label" translatable="yes">Split</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-missing-image</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button6">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Full view</property>
+ <property name="label" translatable="yes">Full</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-missing-image</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolItem" id="toolitem3">
+ <property name="visible">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+
+ <child>
+ <widget class="GtkVSeparator" id="vseparator3">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button7">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
+ <property name="label" translatable="yes">Collapse</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-remove</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_collapse_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button8">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
+ <property name="label" translatable="yes">Expand</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-add</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_expand_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHPaned" id="hpaned1">
+ <property name="width_request">1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">False</property>
+ <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/>
+ <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/>
+ <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVPaned" id="vpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">False</property>
+ <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/>
+ <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/>
+ <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow3">
+ <property name="visible">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="textview3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_WORD</property>
+ <property name="cursor_visible">True</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes">Sorry, no help available for this option yet.</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
diff --git a/scripts/kconfig/images.c b/scripts/kconfig/images.c
new file mode 100644
index 0000000..d4f84bd
--- /dev/null
+++ b/scripts/kconfig/images.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+static const char *xpm_load[] = {
+"22 22 5 1",
+". c None",
+"# c #000000",
+"c c #838100",
+"a c #ffff00",
+"b c #ffffff",
+"......................",
+"......................",
+"......................",
+"............####....#.",
+"...........#....##.##.",
+"..................###.",
+".................####.",
+".####...........#####.",
+"#abab##########.......",
+"#babababababab#.......",
+"#ababababababa#.......",
+"#babababababab#.......",
+"#ababab###############",
+"#babab##cccccccccccc##",
+"#abab##cccccccccccc##.",
+"#bab##cccccccccccc##..",
+"#ab##cccccccccccc##...",
+"#b##cccccccccccc##....",
+"###cccccccccccc##.....",
+"##cccccccccccc##......",
+"###############.......",
+"......................"};
+
+static const char *xpm_save[] = {
+"22 22 5 1",
+". c None",
+"# c #000000",
+"a c #838100",
+"b c #c5c2c5",
+"c c #cdb6d5",
+"......................",
+".####################.",
+".#aa#bbbbbbbbbbbb#bb#.",
+".#aa#bbbbbbbbbbbb#bb#.",
+".#aa#bbbbbbbbbcbb####.",
+".#aa#bbbccbbbbbbb#aa#.",
+".#aa#bbbccbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aaa############aaa#.",
+".#aaaaaaaaaaaaaaaaaa#.",
+".#aaaaaaaaaaaaaaaaaa#.",
+".#aaa#############aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+"..##################..",
+"......................"};
+
+static const char *xpm_back[] = {
+"22 22 3 1",
+". c None",
+"# c #000083",
+"a c #838183",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................",
+"...........######a....",
+"..#......##########...",
+"..##...####......##a..",
+"..###.###.........##..",
+"..######..........##..",
+"..#####...........##..",
+"..######..........##..",
+"..#######.........##..",
+"..########.......##a..",
+"...............a###...",
+"...............###....",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................"};
+
+static const char *xpm_tree_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......................",
+"......................"};
+
+static const char *xpm_single_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"......................",
+"......................"};
+
+static const char *xpm_split_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......................",
+"......................"};
+
+static const char *xpm_symbol_no[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_symbol_mod[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_symbol_yes[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . . ",
+" . . . ",
+" . .. . ",
+" . . .. . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_choice_no[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .... ",
+" .. .. ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .. .. ",
+" .... ",
+" "};
+
+static const char *xpm_choice_yes[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .... ",
+" .. .. ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .. .. ",
+" .... ",
+" "};
+
+static const char *xpm_menu[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . ...... . ",
+" . ...... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_menu_inv[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" .......... ",
+" .. ...... ",
+" .. .... ",
+" .. .. ",
+" .. .. ",
+" .. .... ",
+" .. ...... ",
+" .......... ",
+" .......... ",
+" "};
+
+static const char *xpm_menuback[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . ...... . ",
+" . ...... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_void[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c
new file mode 100644
index 0000000..2858738
--- /dev/null
+++ b/scripts/kconfig/kxgettext.c
@@ -0,0 +1,235 @@
+/*
+ * Arnaldo Carvalho de Melo <acme at conectiva.com.br>, 2005
+ *
+ * Released under the terms of the GNU GPL v2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "lkc.h"
+
+static char *escape(const char* text, char *bf, int len)
+{
+ char *bfp = bf;
+ int multiline = strchr(text, '\n') != NULL;
+ int eol = 0;
+ int textlen = strlen(text);
+
+ if ((textlen > 0) && (text[textlen-1] == '\n'))
+ eol = 1;
+
+ *bfp++ = '"';
+ --len;
+
+ if (multiline) {
+ *bfp++ = '"';
+ *bfp++ = '\n';
+ *bfp++ = '"';
+ len -= 3;
+ }
+
+ while (*text != '\0' && len > 1) {
+ if (*text == '"')
+ *bfp++ = '\\';
+ else if (*text == '\n') {
+ *bfp++ = '\\';
+ *bfp++ = 'n';
+ *bfp++ = '"';
+ *bfp++ = '\n';
+ *bfp++ = '"';
+ len -= 5;
+ ++text;
+ goto next;
+ }
+ else if (*text == '\\') {
+ *bfp++ = '\\';
+ len--;
+ }
+ *bfp++ = *text++;
+next:
+ --len;
+ }
+
+ if (multiline && eol)
+ bfp -= 3;
+
+ *bfp++ = '"';
+ *bfp = '\0';
+
+ return bf;
+}
+
+struct file_line {
+ struct file_line *next;
+ const char *file;
+ int lineno;
+};
+
+static struct file_line *file_line__new(const char *file, int lineno)
+{
+ struct file_line *self = malloc(sizeof(*self));
+
+ if (self == NULL)
+ goto out;
+
+ self->file = file;
+ self->lineno = lineno;
+ self->next = NULL;
+out:
+ return self;
+}
+
+struct message {
+ const char *msg;
+ const char *option;
+ struct message *next;
+ struct file_line *files;
+};
+
+static struct message *message__list;
+
+static struct message *message__new(const char *msg, char *option,
+ const char *file, int lineno)
+{
+ struct message *self = malloc(sizeof(*self));
+
+ if (self == NULL)
+ goto out;
+
+ self->files = file_line__new(file, lineno);
+ if (self->files == NULL)
+ goto out_fail;
+
+ self->msg = strdup(msg);
+ if (self->msg == NULL)
+ goto out_fail_msg;
+
+ self->option = option;
+ self->next = NULL;
+out:
+ return self;
+out_fail_msg:
+ free(self->files);
+out_fail:
+ free(self);
+ self = NULL;
+ goto out;
+}
+
+static struct message *mesage__find(const char *msg)
+{
+ struct message *m = message__list;
+
+ while (m != NULL) {
+ if (strcmp(m->msg, msg) == 0)
+ break;
+ m = m->next;
+ }
+
+ return m;
+}
+
+static int message__add_file_line(struct message *self, const char *file,
+ int lineno)
+{
+ int rc = -1;
+ struct file_line *fl = file_line__new(file, lineno);
+
+ if (fl == NULL)
+ goto out;
+
+ fl->next = self->files;
+ self->files = fl;
+ rc = 0;
+out:
+ return rc;
+}
+
+static int message__add(const char *msg, char *option, const char *file,
+ int lineno)
+{
+ int rc = 0;
+ char bf[16384];
+ char *escaped = escape(msg, bf, sizeof(bf));
+ struct message *m = mesage__find(escaped);
+
+ if (m != NULL)
+ rc = message__add_file_line(m, file, lineno);
+ else {
+ m = message__new(escaped, option, file, lineno);
+
+ if (m != NULL) {
+ m->next = message__list;
+ message__list = m;
+ } else
+ rc = -1;
+ }
+ return rc;
+}
+
+static void menu_build_message_list(struct menu *menu)
+{
+ struct menu *child;
+
+ message__add(menu_get_prompt(menu), NULL,
+ menu->file == NULL ? "Root Menu" : menu->file->name,
+ menu->lineno);
+
+ if (menu->sym != NULL && menu_has_help(menu))
+ message__add(menu_get_help(menu), menu->sym->name,
+ menu->file == NULL ? "Root Menu" : menu->file->name,
+ menu->lineno);
+
+ for (child = menu->list; child != NULL; child = child->next)
+ if (child->prompt != NULL)
+ menu_build_message_list(child);
+}
+
+static void message__print_file_lineno(struct message *self)
+{
+ struct file_line *fl = self->files;
+
+ putchar('\n');
+ if (self->option != NULL)
+ printf("# %s:00000\n", self->option);
+
+ printf("#: %s:%d", fl->file, fl->lineno);
+ fl = fl->next;
+
+ while (fl != NULL) {
+ printf(", %s:%d", fl->file, fl->lineno);
+ fl = fl->next;
+ }
+
+ putchar('\n');
+}
+
+static void message__print_gettext_msgid_msgstr(struct message *self)
+{
+ message__print_file_lineno(self);
+
+ printf("msgid %s\n"
+ "msgstr \"\"\n", self->msg);
+}
+
+static void menu__xgettext(void)
+{
+ struct message *m = message__list;
+
+ while (m != NULL) {
+ /* skip empty lines ("") */
+ if (strlen(m->msg) > sizeof("\"\""))
+ message__print_gettext_msgid_msgstr(m);
+ m = m->next;
+ }
+}
+
+int main(int ac, char **av)
+{
+ conf_parse(av[1]);
+
+ menu_build_message_list(menu_get_root_menu(NULL));
+ menu__xgettext();
+ return 0;
+}
diff --git a/scripts/kconfig/list.h b/scripts/kconfig/list.h
new file mode 100644
index 0000000..0ae730b
--- /dev/null
+++ b/scripts/kconfig/list.h
@@ -0,0 +1,91 @@
+#ifndef LIST_H
+#define LIST_H
+
+/*
+ * Copied from include/linux/...
+ */
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *_new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = _new;
+ _new->next = next;
+ _new->prev = prev;
+ prev->next = _new;
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *_new, struct list_head *head)
+{
+ __list_add(_new, head->prev, head);
+}
+
+#endif
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
new file mode 100644
index 0000000..f8aee5f
--- /dev/null
+++ b/scripts/kconfig/lkc.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef LKC_H
+#define LKC_H
+
+#include "expr.h"
+
+#ifndef KBUILD_NO_NLS
+# include <libintl.h>
+#else
+static inline const char *gettext(const char *txt) { return txt; }
+static inline void textdomain(const char *domainname) {}
+static inline void bindtextdomain(const char *name, const char *dir) {}
+static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define P(name,type,arg) extern type name arg
+#include "lkc_proto.h"
+#undef P
+
+#define SRCTREE "srctree"
+
+#ifndef PACKAGE
+#define PACKAGE "linux"
+#endif
+
+#define LOCALEDIR "/usr/share/locale"
+
+#define _(text) gettext(text)
+#define N_(text) (text)
+
+#ifndef CONFIG_
+#define CONFIG_ "CONFIG_"
+#endif
+static inline const char *CONFIG_prefix(void)
+{
+ return getenv( "CONFIG_" ) ?: CONFIG_;
+}
+#undef CONFIG_
+#define CONFIG_ CONFIG_prefix()
+
+#define TF_COMMAND 0x0001
+#define TF_PARAM 0x0002
+#define TF_OPTION 0x0004
+
+enum conf_def_mode {
+ def_default,
+ def_yes,
+ def_mod,
+ def_no,
+ def_random
+};
+
+#define T_OPT_MODULES 1
+#define T_OPT_DEFCONFIG_LIST 2
+#define T_OPT_ENV 3
+
+struct kconf_id {
+ int name;
+ int token;
+ unsigned int flags;
+ enum symbol_type stype;
+};
+
+extern int zconfdebug;
+
+int zconfparse(void);
+void zconfdump(FILE *out);
+void zconf_starthelp(void);
+FILE *zconf_fopen(const char *name);
+void zconf_initscan(const char *name);
+void zconf_nextfile(const char *name);
+int zconf_lineno(void);
+const char *zconf_curname(void);
+
+/* confdata.c */
+const char *conf_get_configname(void);
+const char *conf_get_autoconfig_name(void);
+char *conf_get_default_confname(void);
+void sym_set_change_count(int count);
+void sym_add_change_count(int count);
+void conf_set_all_new_symbols(enum conf_def_mode mode);
+
+struct conf_printer {
+ void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
+ void (*print_comment)(FILE *, const char *, void *);
+};
+
+/* confdata.c and expr.c */
+static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
+{
+ assert(len != 0);
+
+ if (fwrite(str, len, count, out) != count)
+ fprintf(stderr, "Error in writing or end of file.\n");
+}
+
+/* menu.c */
+void _menu_init(void);
+void menu_warn(struct menu *menu, const char *fmt, ...);
+struct menu *menu_add_menu(void);
+void menu_end_menu(void);
+void menu_add_entry(struct symbol *sym);
+void menu_end_entry(void);
+void menu_add_dep(struct expr *dep);
+void menu_add_visibility(struct expr *dep);
+struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
+void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
+void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
+void menu_add_option(int token, char *arg);
+void menu_finalize(struct menu *parent);
+void menu_set_type(int type);
+
+/* util.c */
+struct file *file_lookup(const char *name);
+int file_write_dep(const char *name);
+void *xmalloc(size_t size);
+void *xcalloc(size_t nmemb, size_t size);
+
+struct gstr {
+ size_t len;
+ char *s;
+ /*
+ * when max_width is not zero long lines in string s (if any) get
+ * wrapped not to exceed the max_width value
+ */
+ int max_width;
+};
+struct gstr str_new(void);
+struct gstr str_assign(const char *s);
+void str_free(struct gstr *gs);
+void str_append(struct gstr *gs, const char *s);
+void str_printf(struct gstr *gs, const char *fmt, ...);
+const char *str_get(struct gstr *gs);
+
+/* symbol.c */
+extern struct expr *sym_env_list;
+
+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_choice_default(struct symbol *sym);
+const char *sym_get_string_default(struct symbol *sym);
+struct symbol *sym_check_deps(struct symbol *sym);
+struct property *prop_alloc(enum prop_type type, struct symbol *sym);
+struct symbol *prop_get_symbol(struct property *prop);
+struct property *sym_get_env_prop(struct symbol *sym);
+
+static inline tristate sym_get_tristate_value(struct symbol *sym)
+{
+ return sym->curr.tri;
+}
+
+
+static inline struct symbol *sym_get_choice_value(struct symbol *sym)
+{
+ return (struct symbol *)sym->curr.val;
+}
+
+static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
+{
+ return sym_set_tristate_value(chval, yes);
+}
+
+static inline bool sym_is_choice(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_CHOICE ? true : false;
+}
+
+static inline bool sym_is_choice_value(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_CHOICEVAL ? true : false;
+}
+
+static inline bool sym_is_optional(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_OPTIONAL ? true : false;
+}
+
+static inline bool sym_has_value(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_DEF_USER ? true : false;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LKC_H */
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
new file mode 100644
index 0000000..ef1a738
--- /dev/null
+++ b/scripts/kconfig/lkc_proto.h
@@ -0,0 +1,56 @@
+#include <stdarg.h>
+
+/* confdata.c */
+P(conf_parse,void,(const char *name));
+P(conf_read,int,(const char *name));
+P(conf_read_simple,int,(const char *name, int));
+P(conf_write_defconfig,int,(const char *name));
+P(conf_write,int,(const char *name));
+P(conf_write_autoconf,int,(void));
+P(conf_get_changed,bool,(void));
+P(conf_set_changed_callback, void,(void (*fn)(void)));
+P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap)));
+
+/* menu.c */
+P(rootmenu,struct menu,);
+
+P(menu_is_visible, bool, (struct menu *menu));
+P(menu_has_prompt, bool, (struct menu *menu));
+P(menu_get_prompt,const char *,(struct menu *menu));
+P(menu_get_root_menu,struct menu *,(struct menu *menu));
+P(menu_get_parent_menu,struct menu *,(struct menu *menu));
+P(menu_has_help,bool,(struct menu *menu));
+P(menu_get_help,const char *,(struct menu *menu));
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head
+ *head));
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head
+ *head));
+P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
+
+/* symbol.c */
+P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
+
+P(sym_lookup,struct symbol *,(const char *name, int flags));
+P(sym_find,struct symbol *,(const char *name));
+P(sym_expand_string_value,const char *,(const char *in));
+P(sym_escape_string_value, const char *,(const char *in));
+P(sym_re_search,struct symbol **,(const char *pattern));
+P(sym_type_name,const char *,(enum symbol_type type));
+P(sym_calc_value,void,(struct symbol *sym));
+P(sym_get_type,enum symbol_type,(struct symbol *sym));
+P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
+P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
+P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
+P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
+P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
+P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
+P(sym_is_changable,bool,(struct symbol *sym));
+P(sym_get_choice_prop,struct property *,(struct symbol *sym));
+P(sym_get_default_prop,struct property *,(struct symbol *sym));
+P(sym_get_string_value,const char *,(struct symbol *sym));
+
+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 *, struct symbol *, const char *), void *data, int prevtoken));
diff --git a/scripts/kconfig/lxdialog/.gitignore b/scripts/kconfig/lxdialog/.gitignore
new file mode 100644
index 0000000..90b08ff
--- /dev/null
+++ b/scripts/kconfig/lxdialog/.gitignore
@@ -0,0 +1,4 @@
+#
+# Generated files
+#
+lxdialog
diff --git a/scripts/kconfig/lxdialog/BIG.FAT.WARNING b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
new file mode 100644
index 0000000..a8999d8
--- /dev/null
+++ b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
@@ -0,0 +1,4 @@
+This is NOT the official version of dialog. This version has been
+significantly modified from the original. It is for use by the Linux
+kernel configuration script. Please do not bother Savio Lam with
+questions about this program.
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
new file mode 100644
index 0000000..8078813
--- /dev/null
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+# Check ncurses compatibility
+
+# What library to link
+ldflags()
+{
+ for ext in so a dll.a dylib ; do
+ for lib in ncursesw ncurses curses ; do
+ $cc -print-file-name=lib${lib}.${ext} | grep -q /
+ if [ $? -eq 0 ]; then
+ echo "-l${lib}"
+ exit
+ fi
+ done
+ done
+ exit 1
+}
+
+# Where is ncurses.h?
+ccflags()
+{
+ if [ -f /usr/include/ncursesw/curses.h ]; then
+ echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
+ echo ' -DNCURSES_WIDECHAR=1'
+ elif [ -f /usr/include/ncurses/ncurses.h ]; then
+ echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
+ elif [ -f /usr/include/ncurses/curses.h ]; then
+ echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
+ elif [ -f /usr/include/ncurses.h ]; then
+ echo '-DCURSES_LOC="<ncurses.h>"'
+ else
+ echo '-DCURSES_LOC="<curses.h>"'
+ fi
+}
+
+# Temp file, try to clean up after us
+tmp=.lxdialog.tmp
+trap "rm -f $tmp" 0 1 2 3 15
+
+# Check if we can link to ncurses
+check() {
+ $cc -x c - -o $tmp 2>/dev/null <<'EOF'
+#include CURSES_LOC
+main() {}
+EOF
+ if [ $? != 0 ]; then
+ echo " *** Unable to find the ncurses libraries or the" 1>&2
+ echo " *** required header files." 1>&2
+ echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2
+ echo " *** " 1>&2
+ echo " *** Install ncurses (ncurses-devel) and try again." 1>&2
+ echo " *** " 1>&2
+ exit 1
+ fi
+}
+
+usage() {
+ printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n"
+}
+
+if [ $# -eq 0 ]; then
+ usage
+ exit 1
+fi
+
+cc=""
+case "$1" in
+ "-check")
+ shift
+ cc="$@"
+ check
+ ;;
+ "-ccflags")
+ ccflags
+ ;;
+ "-ldflags")
+ shift
+ cc="$@"
+ ldflags
+ ;;
+ "*")
+ usage
+ exit 1
+ ;;
+esac
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
new file mode 100644
index 0000000..a2eb80f
--- /dev/null
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -0,0 +1,332 @@
+/*
+ * checklist.c -- implements the checklist box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ * Stuart Herbert - S.Herbert at sheffield.ac.uk: radiolist extension
+ * Alessandro Rubini - rubini at ipvvis.unipv.it: merged the two
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static int list_width, check_x, item_x;
+
+/*
+ * Print list item
+ */
+static void print_item(WINDOW * win, int choice, int selected)
+{
+ int i;
+ char *list_item = malloc(list_width + 1);
+
+ strncpy(list_item, item_str(), list_width - item_x);
+ list_item[list_width - item_x] = '\0';
+
+ /* Clear 'residue' of last item */
+ wattrset(win, dlg.menubox.atr);
+ wmove(win, choice, 0);
+ for (i = 0; i < list_width; i++)
+ waddch(win, ' ');
+
+ wmove(win, choice, check_x);
+ wattrset(win, selected ? dlg.check_selected.atr
+ : dlg.check.atr);
+ if (!item_is_tag(':'))
+ wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
+
+ wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
+ mvwaddch(win, choice, item_x, list_item[0]);
+ wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
+ waddstr(win, list_item + 1);
+ if (selected) {
+ wmove(win, choice, check_x + 1);
+ wrefresh(win);
+ }
+ free(list_item);
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
+ int y, int x, int height)
+{
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset(win, dlg.uarrow.atr);
+ waddch(win, ACS_UARROW);
+ waddstr(win, "(-)");
+ } else {
+ wattrset(win, dlg.menubox.atr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+
+ if ((height < item_no) && (scroll + choice < item_no - 1)) {
+ wattrset(win, dlg.darrow.atr);
+ waddch(win, ACS_DARROW);
+ waddstr(win, "(+)");
+ } else {
+ wattrset(win, dlg.menubox_border.atr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+}
+
+/*
+ * Display the termination buttons
+ */
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button(dialog, gettext("Select"), y, x, selected == 0);
+ print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
+
+ wmove(dialog, y, x + 1 + 14 * selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ * in the style of radiolist (only one option turned on at a time).
+ */
+int dialog_checklist(const char *title, const char *prompt, int height,
+ int width, int list_height)
+{
+ int i, x, y, box_x, box_y;
+ int key = 0, button = 0, choice = 0, scroll = 0, max_choice;
+ WINDOW *dialog, *list;
+
+ /* which item to highlight */
+ item_foreach() {
+ if (item_is_tag('X'))
+ choice = item_n();
+ if (item_is_selected()) {
+ choice = item_n();
+ break;
+ }
+ }
+
+do_resize:
+ if (getmaxy(stdscr) < (height + 6))
+ return -ERRDISPLAYTOOSMALL;
+ if (getmaxx(stdscr) < (width + 6))
+ return -ERRDISPLAYTOOSMALL;
+
+ max_choice = MIN(list_height, item_count());
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width,
+ dlg.dialog.atr, dlg.border.atr);
+ wattrset(dialog, dlg.border.atr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dlg.dialog.atr);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dlg.dialog.atr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ list_width = width - 6;
+ box_y = height - list_height - 5;
+ box_x = (width - list_width) / 2 - 1;
+
+ /* create new window for the list */
+ list = subwin(dialog, list_height, list_width, y + box_y + 1,
+ x + box_x + 1);
+
+ keypad(list, TRUE);
+
+ /* draw a box around the list items */
+ draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
+ dlg.menubox_border.atr, dlg.menubox.atr);
+
+ /* Find length of longest item in order to center checklist */
+ check_x = 0;
+ item_foreach()
+ check_x = MAX(check_x, strlen(item_str()) + 4);
+ check_x = MIN(check_x, list_width);
+
+ check_x = (list_width - check_x) / 2;
+ item_x = check_x + 4;
+
+ if (choice >= list_height) {
+ scroll = choice - list_height + 1;
+ choice -= scroll;
+ }
+
+ /* Print the list */
+ for (i = 0; i < max_choice; i++) {
+ item_set(scroll + i);
+ print_item(list, i, i == choice);
+ }
+
+ print_arrows(dialog, choice, item_count(), scroll,
+ box_y, box_x + check_x + 5, list_height);
+
+ print_buttons(dialog, height, width, 0);
+
+ wnoutrefresh(dialog);
+ wnoutrefresh(list);
+ doupdate();
+
+ while (key != KEY_ESC) {
+ key = wgetch(dialog);
+
+ for (i = 0; i < max_choice; i++) {
+ item_set(i + scroll);
+ if (toupper(key) == toupper(item_str()[0]))
+ break;
+ }
+
+ if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
+ key == '+' || key == '-') {
+ if (key == KEY_UP || key == '-') {
+ if (!choice) {
+ if (!scroll)
+ continue;
+ /* Scroll list down */
+ if (list_height > 1) {
+ /* De-highlight current first item */
+ item_set(scroll);
+ print_item(list, 0, FALSE);
+ scrollok(list, TRUE);
+ wscrl(list, -1);
+ scrollok(list, FALSE);
+ }
+ scroll--;
+ item_set(scroll);
+ print_item(list, 0, TRUE);
+ print_arrows(dialog, choice, item_count(),
+ scroll, box_y, box_x + check_x + 5, list_height);
+
+ wnoutrefresh(dialog);
+ wrefresh(list);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice - 1;
+ } else if (key == KEY_DOWN || key == '+') {
+ if (choice == max_choice - 1) {
+ if (scroll + choice >= item_count() - 1)
+ continue;
+ /* Scroll list up */
+ if (list_height > 1) {
+ /* De-highlight current last item before scrolling up */
+ item_set(scroll + max_choice - 1);
+ print_item(list,
+ max_choice - 1,
+ FALSE);
+ scrollok(list, TRUE);
+ wscrl(list, 1);
+ scrollok(list, FALSE);
+ }
+ scroll++;
+ item_set(scroll + max_choice - 1);
+ print_item(list, max_choice - 1, TRUE);
+
+ print_arrows(dialog, choice, item_count(),
+ scroll, box_y, box_x + check_x + 5, list_height);
+
+ wnoutrefresh(dialog);
+ wrefresh(list);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice + 1;
+ }
+ if (i != choice) {
+ /* De-highlight current item */
+ item_set(scroll + choice);
+ print_item(list, choice, FALSE);
+ /* Highlight new item */
+ choice = i;
+ item_set(scroll + choice);
+ print_item(list, choice, TRUE);
+ wnoutrefresh(dialog);
+ wrefresh(list);
+ }
+ continue; /* wait for another key press */
+ }
+ switch (key) {
+ case 'H':
+ case 'h':
+ case '?':
+ button = 1;
+ /* fall-through */
+ case 'S':
+ case 's':
+ case ' ':
+ case '\n':
+ item_foreach()
+ item_set_selected(0);
+ item_set(scroll + choice);
+ item_set_selected(1);
+ delwin(list);
+ delwin(dialog);
+ return button;
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh(dialog);
+ break;
+ case 'X':
+ case 'x':
+ key = KEY_ESC;
+ break;
+ case KEY_ESC:
+ key = on_key_esc(dialog);
+ break;
+ case KEY_RESIZE:
+ delwin(list);
+ delwin(dialog);
+ on_key_resize();
+ goto do_resize;
+ }
+
+ /* Now, update everything... */
+ doupdate();
+ }
+ delwin(list);
+ delwin(dialog);
+ return key; /* ESC pressed */
+}
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
new file mode 100644
index 0000000..307022a
--- /dev/null
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -0,0 +1,236 @@
+/*
+ * dialog.h -- common declarations for all dialog modules
+ *
+ * AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#ifndef KBUILD_NO_NLS
+# include <libintl.h>
+#else
+# define gettext(Msgid) ((const char *) (Msgid))
+#endif
+
+#ifdef __sun__
+#define CURS_MACROS
+#endif
+#include CURSES_LOC
+
+/*
+ * Colors in ncurses 1.9.9e do not work properly since foreground and
+ * background colors are OR'd rather than separately masked. This version
+ * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
+ * with standard curses. The simplest fix (to make this work with standard
+ * curses) uses the wbkgdset() function, not used in the original hack.
+ * Turn it off if we're building with 1.9.9e, since it just confuses things.
+ */
+#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
+#define OLD_NCURSES 1
+#undef wbkgdset
+#define wbkgdset(w,p) /*nothing */
+#else
+#define OLD_NCURSES 0
+#endif
+
+#define TR(params) _tracef params
+
+#define KEY_ESC 27
+#define TAB 9
+#define MAX_LEN 2048
+#define BUF_SIZE (10*1024)
+#define MIN(x,y) (x < y ? x : y)
+#define MAX(x,y) (x > y ? x : y)
+
+#ifndef ACS_ULCORNER
+#define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+#define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+#define ACS_URCORNER '+'
+#endif
+#ifndef ACS_LRCORNER
+#define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_HLINE
+#define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+#define ACS_VLINE '|'
+#endif
+#ifndef ACS_LTEE
+#define ACS_LTEE '+'
+#endif
+#ifndef ACS_RTEE
+#define ACS_RTEE '+'
+#endif
+#ifndef ACS_UARROW
+#define ACS_UARROW '^'
+#endif
+#ifndef ACS_DARROW
+#define ACS_DARROW 'v'
+#endif
+
+/* error return codes */
+#define ERRDISPLAYTOOSMALL (KEY_MAX + 1)
+
+/*
+ * Color definitions
+ */
+struct dialog_color {
+ chtype atr; /* Color attribute */
+ int fg; /* foreground */
+ int bg; /* background */
+ int hl; /* highlight this item */
+};
+
+struct dialog_info {
+ const char *backtitle;
+ struct dialog_color screen;
+ struct dialog_color shadow;
+ struct dialog_color dialog;
+ struct dialog_color title;
+ struct dialog_color border;
+ struct dialog_color button_active;
+ struct dialog_color button_inactive;
+ struct dialog_color button_key_active;
+ struct dialog_color button_key_inactive;
+ struct dialog_color button_label_active;
+ struct dialog_color button_label_inactive;
+ struct dialog_color inputbox;
+ struct dialog_color inputbox_border;
+ struct dialog_color searchbox;
+ struct dialog_color searchbox_title;
+ struct dialog_color searchbox_border;
+ struct dialog_color position_indicator;
+ struct dialog_color menubox;
+ struct dialog_color menubox_border;
+ struct dialog_color item;
+ struct dialog_color item_selected;
+ struct dialog_color tag;
+ struct dialog_color tag_selected;
+ struct dialog_color tag_key;
+ struct dialog_color tag_key_selected;
+ struct dialog_color check;
+ struct dialog_color check_selected;
+ struct dialog_color uarrow;
+ struct dialog_color darrow;
+};
+
+/*
+ * Global variables
+ */
+extern struct dialog_info dlg;
+extern char dialog_input_result[];
+extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */
+
+/*
+ * Function prototypes
+ */
+
+/* item list as used by checklist and menubox */
+void item_reset(void);
+void item_make(const char *fmt, ...);
+void item_add_str(const char *fmt, ...);
+void item_set_tag(char tag);
+void item_set_data(void *p);
+void item_set_selected(int val);
+int item_activate_selected(void);
+void *item_data(void);
+char item_tag(void);
+
+/* item list manipulation for lxdialog use */
+#define MAXITEMSTR 200
+struct dialog_item {
+ char str[MAXITEMSTR]; /* promtp displayed */
+ char tag;
+ void *data; /* pointer to menu item - used by menubox+checklist */
+ int selected; /* Set to 1 by dialog_*() function if selected. */
+};
+
+/* list of lialog_items */
+struct dialog_list {
+ struct dialog_item node;
+ struct dialog_list *next;
+};
+
+extern struct dialog_list *item_cur;
+extern struct dialog_list item_nil;
+extern struct dialog_list *item_head;
+
+int item_count(void);
+void item_set(int n);
+int item_n(void);
+const char *item_str(void);
+int item_is_selected(void);
+int item_is_tag(char tag);
+#define item_foreach() \
+ for (item_cur = item_head ? item_head: item_cur; \
+ item_cur && (item_cur != &item_nil); item_cur = item_cur->next)
+
+/* generic key handlers */
+int on_key_esc(WINDOW *win);
+int on_key_resize(void);
+
+int init_dialog(const char *backtitle);
+void set_dialog_backtitle(const char *backtitle);
+void end_dialog(int x, int y);
+void attr_clear(WINDOW * win, int height, int width, chtype attr);
+void dialog_clear(void);
+void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x);
+void print_button(WINDOW * win, const char *label, int y, int x, int selected);
+void print_title(WINDOW *dialog, const char *title, int width);
+void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box,
+ chtype border);
+void draw_shadow(WINDOW * win, int y, int x, int height, int width);
+
+int first_alpha(const char *string, const char *exempt);
+int dialog_yesno(const char *title, const char *prompt, int height, int width);
+int dialog_msgbox(const char *title, const char *prompt, int height,
+ int width, int pause);
+
+
+typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
+ *_data);
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+ int initial_width, int *keys, int *_vscroll, int *_hscroll,
+ update_text_fn update_text, void *data);
+int dialog_menu(const char *title, const char *prompt,
+ const void *selected, int *s_scroll);
+int dialog_checklist(const char *title, const char *prompt, int height,
+ int width, int list_height);
+int dialog_inputbox(const char *title, const char *prompt, int height,
+ int width, const char *init);
+
+/*
+ * This is the base for fictitious keys, which activate
+ * the buttons.
+ *
+ * Mouse-generated keys are the following:
+ * -- the first 32 are used as numbers, in addition to '0'-'9'
+ * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
+ * -- uppercase chars are used to invoke the button (M_EVENT + 'O')
+ */
+#define M_EVENT (KEY_MAX+1)
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
new file mode 100644
index 0000000..21404a0
--- /dev/null
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -0,0 +1,301 @@
+/*
+ * inputbox.c -- implements the input box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+char dialog_input_result[MAX_LEN + 1];
+
+/*
+ * Print the termination buttons
+ */
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button(dialog, gettext(" Ok "), y, x, selected == 0);
+ print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
+
+ wmove(dialog, y, x + 1 + 14 * selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box for inputing a string
+ */
+int dialog_inputbox(const char *title, const char *prompt, int height, int width,
+ const char *init)
+{
+ int i, x, y, box_y, box_x, box_width;
+ int input_x = 0, key = 0, button = -1;
+ int show_x, len, pos;
+ char *instr = dialog_input_result;
+ WINDOW *dialog;
+
+ if (!init)
+ instr[0] = '\0';
+ else
+ strcpy(instr, init);
+
+do_resize:
+ if (getmaxy(stdscr) <= (height - 2))
+ return -ERRDISPLAYTOOSMALL;
+ if (getmaxx(stdscr) <= (width - 2))
+ return -ERRDISPLAYTOOSMALL;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width,
+ dlg.dialog.atr, dlg.border.atr);
+ wattrset(dialog, dlg.border.atr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dlg.dialog.atr);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dlg.dialog.atr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ /* Draw the input field box */
+ box_width = width - 6;
+ getyx(dialog, y, x);
+ box_y = y + 2;
+ box_x = (width - box_width) / 2;
+ draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
+ dlg.dialog.atr, dlg.border.atr);
+
+ print_buttons(dialog, height, width, 0);
+
+ /* Set up the initial value */
+ wmove(dialog, box_y, box_x);
+ wattrset(dialog, dlg.inputbox.atr);
+
+ len = strlen(instr);
+ pos = len;
+
+ if (len >= box_width) {
+ show_x = len - box_width + 1;
+ input_x = box_width - 1;
+ for (i = 0; i < box_width - 1; i++)
+ waddch(dialog, instr[show_x + i]);
+ } else {
+ show_x = 0;
+ input_x = len;
+ waddstr(dialog, instr);
+ }
+
+ wmove(dialog, box_y, box_x + input_x);
+
+ wrefresh(dialog);
+
+ while (key != KEY_ESC) {
+ key = wgetch(dialog);
+
+ if (button == -1) { /* Input box selected */
+ switch (key) {
+ case TAB:
+ case KEY_UP:
+ case KEY_DOWN:
+ break;
+ case KEY_BACKSPACE:
+ case 127:
+ if (pos) {
+ wattrset(dialog, dlg.inputbox.atr);
+ if (input_x == 0) {
+ show_x--;
+ } else
+ input_x--;
+
+ if (pos < len) {
+ for (i = pos - 1; i < len; i++) {
+ instr[i] = instr[i+1];
+ }
+ }
+
+ pos--;
+ len--;
+ instr[len] = '\0';
+ wmove(dialog, box_y, box_x);
+ for (i = 0; i < box_width; i++) {
+ if (!instr[show_x + i]) {
+ waddch(dialog, ' ');
+ break;
+ }
+ waddch(dialog, instr[show_x + i]);
+ }
+ wmove(dialog, box_y, input_x + box_x);
+ wrefresh(dialog);
+ }
+ continue;
+ case KEY_LEFT:
+ if (pos > 0) {
+ if (input_x > 0) {
+ wmove(dialog, box_y, --input_x + box_x);
+ } else if (input_x == 0) {
+ show_x--;
+ wmove(dialog, box_y, box_x);
+ for (i = 0; i < box_width; i++) {
+ if (!instr[show_x + i]) {
+ waddch(dialog, ' ');
+ break;
+ }
+ waddch(dialog, instr[show_x + i]);
+ }
+ wmove(dialog, box_y, box_x);
+ }
+ pos--;
+ }
+ continue;
+ case KEY_RIGHT:
+ if (pos < len) {
+ if (input_x < box_width - 1) {
+ wmove(dialog, box_y, ++input_x + box_x);
+ } else if (input_x == box_width - 1) {
+ show_x++;
+ wmove(dialog, box_y, box_x);
+ for (i = 0; i < box_width; i++) {
+ if (!instr[show_x + i]) {
+ waddch(dialog, ' ');
+ break;
+ }
+ waddch(dialog, instr[show_x + i]);
+ }
+ wmove(dialog, box_y, input_x + box_x);
+ }
+ pos++;
+ }
+ continue;
+ default:
+ if (key < 0x100 && isprint(key)) {
+ if (len < MAX_LEN) {
+ wattrset(dialog, dlg.inputbox.atr);
+ if (pos < len) {
+ for (i = len; i > pos; i--)
+ instr[i] = instr[i-1];
+ instr[pos] = key;
+ } else {
+ instr[len] = key;
+ }
+ pos++;
+ len++;
+ instr[len] = '\0';
+
+ if (input_x == box_width - 1) {
+ show_x++;
+ } else {
+ input_x++;
+ }
+
+ wmove(dialog, box_y, box_x);
+ for (i = 0; i < box_width; i++) {
+ if (!instr[show_x + i]) {
+ waddch(dialog, ' ');
+ break;
+ }
+ waddch(dialog, instr[show_x + i]);
+ }
+ wmove(dialog, box_y, input_x + box_x);
+ wrefresh(dialog);
+ } else
+ flash(); /* Alarm user about overflow */
+ continue;
+ }
+ }
+ }
+ switch (key) {
+ case 'O':
+ case 'o':
+ delwin(dialog);
+ return 0;
+ case 'H':
+ case 'h':
+ delwin(dialog);
+ return 1;
+ case KEY_UP:
+ case KEY_LEFT:
+ switch (button) {
+ case -1:
+ button = 1; /* Indicates "Help" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 0:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove(dialog, box_y, box_x + input_x);
+ wrefresh(dialog);
+ break;
+ case 1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ }
+ break;
+ case TAB:
+ case KEY_DOWN:
+ case KEY_RIGHT:
+ switch (button) {
+ case -1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ case 0:
+ button = 1; /* Indicates "Help" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 1:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove(dialog, box_y, box_x + input_x);
+ wrefresh(dialog);
+ break;
+ }
+ break;
+ case ' ':
+ case '\n':
+ delwin(dialog);
+ return (button == -1 ? 0 : button);
+ case 'X':
+ case 'x':
+ key = KEY_ESC;
+ break;
+ case KEY_ESC:
+ key = on_key_esc(dialog);
+ break;
+ case KEY_RESIZE:
+ delwin(dialog);
+ on_key_resize();
+ goto do_resize;
+ }
+ }
+
+ delwin(dialog);
+ return KEY_ESC; /* ESC pressed */
+}
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
new file mode 100644
index 0000000..48d382e
--- /dev/null
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -0,0 +1,436 @@
+/*
+ * menubox.c -- implements the menu box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw at cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Changes by Clifford Wolf (god at clifford.at)
+ *
+ * [ 1998-06-13 ]
+ *
+ * *) A bugfix for the Page-Down problem
+ *
+ * *) Formerly when I used Page Down and Page Up, the cursor would be set
+ * to the first position in the menu box. Now lxdialog is a bit
+ * smarter and works more like other menu systems (just have a look at
+ * it).
+ *
+ * *) Formerly if I selected something my scrolling would be broken because
+ * lxdialog is re-invoked by the Menuconfig shell script, can't
+ * remember the last scrolling position, and just sets it so that the
+ * cursor is at the bottom of the box. Now it writes the temporary file
+ * lxdialog.scrltmp which contains this information. The file is
+ * deleted by lxdialog if the user leaves a submenu or enters a new
+ * one, but it would be nice if Menuconfig could make another "rm -f"
+ * just to be sure. Just try it out - you will recognise a difference!
+ *
+ * [ 1998-06-14 ]
+ *
+ * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
+ * and menus change their size on the fly.
+ *
+ * *) If for some reason the last scrolling position is not saved by
+ * lxdialog, it sets the scrolling so that the selected item is in the
+ * middle of the menu box, not at the bottom.
+ *
+ * 02 January 1999, Michael Elizabeth Chastain (mec at shout.net)
+ * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
+ * This fixes a bug in Menuconfig where using ' ' to descend into menus
+ * would leave mis-synchronized lxdialog.scrltmp files lying around,
+ * fscanf would read in 'scroll', and eventually that value would get used.
+ */
+
+#include "dialog.h"
+
+static int menu_width, item_x;
+
+/*
+ * Print menu item
+ */
+static void do_print_item(WINDOW * win, const char *item, int line_y,
+ int selected, int hotkey)
+{
+ int j;
+ char *menu_item = malloc(menu_width + 1);
+
+ strncpy(menu_item, item, menu_width - item_x);
+ menu_item[menu_width - item_x] = '\0';
+ j = first_alpha(menu_item, "YyNnMmHh");
+
+ /* Clear 'residue' of last item */
+ wattrset(win, dlg.menubox.atr);
+ wmove(win, line_y, 0);
+#if OLD_NCURSES
+ {
+ int i;
+ for (i = 0; i < menu_width; i++)
+ waddch(win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+ wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
+ mvwaddstr(win, line_y, item_x, menu_item);
+ if (hotkey) {
+ wattrset(win, selected ? dlg.tag_key_selected.atr
+ : dlg.tag_key.atr);
+ mvwaddch(win, line_y, item_x + j, menu_item[j]);
+ }
+ if (selected) {
+ wmove(win, line_y, item_x + 1);
+ }
+ free(menu_item);
+ wrefresh(win);
+}
+
+#define print_item(index, choice, selected) \
+do { \
+ item_set(index); \
+ do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
+} while (0)
+
+/*
+ * Print the scroll indicators.
+ */
+static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
+ int height)
+{
+ int cur_y, cur_x;
+
+ getyx(win, cur_y, cur_x);
+
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset(win, dlg.uarrow.atr);
+ waddch(win, ACS_UARROW);
+ waddstr(win, "(-)");
+ } else {
+ wattrset(win, dlg.menubox.atr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+ wrefresh(win);
+
+ if ((height < item_no) && (scroll + height < item_no)) {
+ wattrset(win, dlg.darrow.atr);
+ waddch(win, ACS_DARROW);
+ waddstr(win, "(+)");
+ } else {
+ wattrset(win, dlg.menubox_border.atr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+
+ wmove(win, cur_y, cur_x);
+ wrefresh(win);
+}
+
+/*
+ * Display the termination buttons.
+ */
+static void print_buttons(WINDOW * win, int height, int width, int selected)
+{
+ int x = width / 2 - 28;
+ int y = height - 2;
+
+ print_button(win, gettext("Select"), y, x, selected == 0);
+ print_button(win, gettext(" Exit "), y, x + 12, selected == 1);
+ print_button(win, gettext(" Help "), y, x + 24, selected == 2);
+ print_button(win, gettext(" Save "), y, x + 36, selected == 3);
+ print_button(win, gettext(" Load "), y, x + 48, selected == 4);
+
+ wmove(win, y, x + 1 + 12 * selected);
+ wrefresh(win);
+}
+
+/* scroll up n lines (n may be negative) */
+static void do_scroll(WINDOW *win, int *scroll, int n)
+{
+ /* Scroll menu up */
+ scrollok(win, TRUE);
+ wscrl(win, n);
+ scrollok(win, FALSE);
+ *scroll = *scroll + n;
+ wrefresh(win);
+}
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+int dialog_menu(const char *title, const char *prompt,
+ const void *selected, int *s_scroll)
+{
+ int i, j, x, y, box_x, box_y;
+ int height, width, menu_height;
+ int key = 0, button = 0, scroll = 0, choice = 0;
+ int first_item = 0, max_choice;
+ WINDOW *dialog, *menu;
+
+do_resize:
+ height = getmaxy(stdscr);
+ width = getmaxx(stdscr);
+ if (height < 15 || width < 65)
+ return -ERRDISPLAYTOOSMALL;
+
+ height -= 4;
+ width -= 5;
+ menu_height = height - 10;
+
+ max_choice = MIN(menu_height, item_count());
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width,
+ dlg.dialog.atr, dlg.border.atr);
+ wattrset(dialog, dlg.border.atr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dlg.dialog.atr);
+ wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dlg.dialog.atr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ menu_width = width - 6;
+ box_y = height - menu_height - 5;
+ box_x = (width - menu_width) / 2 - 1;
+
+ /* create new window for the menu */
+ menu = subwin(dialog, menu_height, menu_width,
+ y + box_y + 1, x + box_x + 1);
+ keypad(menu, TRUE);
+
+ /* draw a box around the menu items */
+ draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
+ dlg.menubox_border.atr, dlg.menubox.atr);
+
+ if (menu_width >= 80)
+ item_x = (menu_width - 70) / 2;
+ else
+ item_x = 4;
+
+ /* Set choice to default item */
+ item_foreach()
+ if (selected && (selected == item_data()))
+ choice = item_n();
+ /* get the saved scroll info */
+ scroll = *s_scroll;
+ if ((scroll <= choice) && (scroll + max_choice > choice) &&
+ (scroll >= 0) && (scroll + max_choice <= item_count())) {
+ first_item = scroll;
+ choice = choice - scroll;
+ } else {
+ scroll = 0;
+ }
+ if ((choice >= max_choice)) {
+ if (choice >= item_count() - max_choice / 2)
+ scroll = first_item = item_count() - max_choice;
+ else
+ scroll = first_item = choice - max_choice / 2;
+ choice = choice - scroll;
+ }
+
+ /* Print the menu */
+ for (i = 0; i < max_choice; i++) {
+ print_item(first_item + i, i, i == choice);
+ }
+
+ wnoutrefresh(menu);
+
+ print_arrows(dialog, item_count(), scroll,
+ box_y, box_x + item_x + 1, menu_height);
+
+ print_buttons(dialog, height, width, 0);
+ wmove(menu, choice, item_x + 1);
+ wrefresh(menu);
+
+ while (key != KEY_ESC) {
+ key = wgetch(menu);
+
+ if (key < 256 && isalpha(key))
+ key = tolower(key);
+
+ if (strchr("ynmh", key))
+ i = max_choice;
+ else {
+ for (i = choice + 1; i < max_choice; i++) {
+ item_set(scroll + i);
+ j = first_alpha(item_str(), "YyNnMmHh");
+ if (key == tolower(item_str()[j]))
+ break;
+ }
+ if (i == max_choice)
+ for (i = 0; i < max_choice; i++) {
+ item_set(scroll + i);
+ j = first_alpha(item_str(), "YyNnMmHh");
+ if (key == tolower(item_str()[j]))
+ break;
+ }
+ }
+
+ if (i < max_choice ||
+ key == KEY_UP || key == KEY_DOWN ||
+ key == '-' || key == '+' ||
+ key == KEY_PPAGE || key == KEY_NPAGE) {
+ /* Remove highligt of current item */
+ print_item(scroll + choice, choice, FALSE);
+
+ if (key == KEY_UP || key == '-') {
+ if (choice < 2 && scroll) {
+ /* Scroll menu down */
+ do_scroll(menu, &scroll, -1);
+
+ print_item(scroll, 0, FALSE);
+ } else
+ choice = MAX(choice - 1, 0);
+
+ } else if (key == KEY_DOWN || key == '+') {
+ print_item(scroll+choice, choice, FALSE);
+
+ if ((choice > max_choice - 3) &&
+ (scroll + max_choice < item_count())) {
+ /* Scroll menu up */
+ do_scroll(menu, &scroll, 1);
+
+ print_item(scroll+max_choice - 1,
+ max_choice - 1, FALSE);
+ } else
+ choice = MIN(choice + 1, max_choice - 1);
+
+ } else if (key == KEY_PPAGE) {
+ scrollok(menu, TRUE);
+ for (i = 0; (i < max_choice); i++) {
+ if (scroll > 0) {
+ do_scroll(menu, &scroll, -1);
+ print_item(scroll, 0, FALSE);
+ } else {
+ if (choice > 0)
+ choice--;
+ }
+ }
+
+ } else if (key == KEY_NPAGE) {
+ for (i = 0; (i < max_choice); i++) {
+ if (scroll + max_choice < item_count()) {
+ do_scroll(menu, &scroll, 1);
+ print_item(scroll+max_choice-1,
+ max_choice - 1, FALSE);
+ } else {
+ if (choice + 1 < max_choice)
+ choice++;
+ }
+ }
+ } else
+ choice = i;
+
+ print_item(scroll + choice, choice, TRUE);
+
+ print_arrows(dialog, item_count(), scroll,
+ box_y, box_x + item_x + 1, menu_height);
+
+ wnoutrefresh(dialog);
+ wrefresh(menu);
+
+ continue; /* wait for another key press */
+ }
+
+ switch (key) {
+ case KEY_LEFT:
+ case TAB:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 4 : (button > 4 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh(menu);
+ break;
+ case ' ':
+ case 's':
+ case 'y':
+ case 'n':
+ case 'm':
+ case '/':
+ case 'h':
+ case '?':
+ case 'z':
+ case '\n':
+ /* save scroll info */
+ *s_scroll = scroll;
+ delwin(menu);
+ delwin(dialog);
+ item_set(scroll + choice);
+ item_set_selected(1);
+ switch (key) {
+ case 'h':
+ case '?':
+ return 2;
+ case 's':
+ case 'y':
+ return 5;
+ case 'n':
+ return 6;
+ case 'm':
+ return 7;
+ case ' ':
+ return 8;
+ case '/':
+ return 9;
+ case 'z':
+ return 10;
+ case '\n':
+ return button;
+ }
+ return 0;
+ case 'e':
+ case 'x':
+ key = KEY_ESC;
+ break;
+ case KEY_ESC:
+ key = on_key_esc(menu);
+ break;
+ case KEY_RESIZE:
+ on_key_resize();
+ delwin(menu);
+ delwin(dialog);
+ goto do_resize;
+ }
+ }
+ delwin(menu);
+ delwin(dialog);
+ return key; /* ESC pressed */
+}
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
new file mode 100644
index 0000000..a48bb93
--- /dev/null
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -0,0 +1,408 @@
+/*
+ * textbox.c -- implements the text box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static void back_lines(int n);
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+ update_text, void *data);
+static void print_line(WINDOW *win, int row, int width);
+static char *get_line(void);
+static void print_position(WINDOW * win);
+
+static int hscroll;
+static int begin_reached, end_reached, page_length;
+static char *buf;
+static char *page;
+
+/*
+ * refresh window content
+ */
+static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
+ int cur_y, int cur_x, update_text_fn update_text,
+ void *data)
+{
+ print_page(box, boxh, boxw, update_text, data);
+ print_position(dialog);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+}
+
+
+/*
+ * Display text from a file in a dialog box.
+ *
+ * keys is a null-terminated array
+ * update_text() may not add or remove any '\n' or '\0' in tbuf
+ */
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+ int initial_width, int *keys, int *_vscroll, int *_hscroll,
+ update_text_fn update_text, void *data)
+{
+ int i, x, y, cur_x, cur_y, key = 0;
+ int height, width, boxh, boxw;
+ WINDOW *dialog, *box;
+ bool done = false;
+
+ begin_reached = 1;
+ end_reached = 0;
+ page_length = 0;
+ hscroll = 0;
+ buf = tbuf;
+ page = buf; /* page is pointer to start of page to be displayed */
+
+ if (_vscroll && *_vscroll) {
+ begin_reached = 0;
+
+ for (i = 0; i < *_vscroll; i++)
+ get_line();
+ }
+ if (_hscroll)
+ hscroll = *_hscroll;
+
+do_resize:
+ getmaxyx(stdscr, height, width);
+ if (height < 8 || width < 8)
+ return -ERRDISPLAYTOOSMALL;
+ if (initial_height != 0)
+ height = initial_height;
+ else
+ if (height > 4)
+ height -= 4;
+ else
+ height = 0;
+ if (initial_width != 0)
+ width = initial_width;
+ else
+ if (width > 5)
+ width -= 5;
+ else
+ width = 0;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ /* Create window for box region, used for scrolling text */
+ boxh = height - 4;
+ boxw = width - 2;
+ box = subwin(dialog, boxh, boxw, y + 1, x + 1);
+ wattrset(box, dlg.dialog.atr);
+ wbkgdset(box, dlg.dialog.atr & A_COLOR);
+
+ keypad(box, TRUE);
+
+ /* register the new window, along with its borders */
+ draw_box(dialog, 0, 0, height, width,
+ dlg.dialog.atr, dlg.border.atr);
+
+ wattrset(dialog, dlg.border.atr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dlg.dialog.atr);
+ wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
+ wnoutrefresh(dialog);
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+
+ /* Print first page of text */
+ attr_clear(box, boxh, boxw, dlg.dialog.atr);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
+ data);
+
+ while (!done) {
+ key = wgetch(dialog);
+ switch (key) {
+ case 'E': /* Exit */
+ case 'e':
+ case 'X':
+ case 'x':
+ case 'q':
+ case '\n':
+ done = true;
+ break;
+ case 'g': /* First page */
+ case KEY_HOME:
+ if (!begin_reached) {
+ begin_reached = 1;
+ page = buf;
+ refresh_text_box(dialog, box, boxh, boxw,
+ cur_y, cur_x, update_text,
+ data);
+ }
+ break;
+ case 'G': /* Last page */
+ case KEY_END:
+
+ end_reached = 1;
+ /* point to last char in buf */
+ page = buf + strlen(buf);
+ back_lines(boxh);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
+ break;
+ case 'K': /* Previous line */
+ case 'k':
+ case KEY_UP:
+ if (begin_reached)
+ break;
+
+ back_lines(page_length + 1);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
+ break;
+ case 'B': /* Previous page */
+ case 'b':
+ case 'u':
+ case KEY_PPAGE:
+ if (begin_reached)
+ break;
+ back_lines(page_length + boxh);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
+ break;
+ case 'J': /* Next line */
+ case 'j':
+ case KEY_DOWN:
+ if (end_reached)
+ break;
+
+ back_lines(page_length - 1);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
+ break;
+ case KEY_NPAGE: /* Next page */
+ case ' ':
+ case 'd':
+ if (end_reached)
+ break;
+
+ begin_reached = 0;
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
+ break;
+ case '0': /* Beginning of line */
+ case 'H': /* Scroll left */
+ case 'h':
+ case KEY_LEFT:
+ if (hscroll <= 0)
+ break;
+
+ if (key == '0')
+ hscroll = 0;
+ else
+ hscroll--;
+ /* Reprint current page to scroll horizontally */
+ back_lines(page_length);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
+ break;
+ case 'L': /* Scroll right */
+ case 'l':
+ case KEY_RIGHT:
+ if (hscroll >= MAX_LEN)
+ break;
+ hscroll++;
+ /* Reprint current page to scroll horizontally */
+ back_lines(page_length);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
+ break;
+ case KEY_ESC:
+ if (on_key_esc(dialog) == KEY_ESC)
+ done = true;
+ break;
+ case KEY_RESIZE:
+ back_lines(height);
+ delwin(box);
+ delwin(dialog);
+ on_key_resize();
+ goto do_resize;
+ default:
+ for (i = 0; keys[i]; i++) {
+ if (key == keys[i]) {
+ done = true;
+ break;
+ }
+ }
+ }
+ }
+ delwin(box);
+ delwin(dialog);
+ if (_vscroll) {
+ const char *s;
+
+ s = buf;
+ *_vscroll = 0;
+ back_lines(page_length);
+ while (s < page && (s = strchr(s, '\n'))) {
+ (*_vscroll)++;
+ s++;
+ }
+ }
+ if (_hscroll)
+ *_hscroll = hscroll;
+ return key;
+}
+
+/*
+ * Go back 'n' lines in text. Called by dialog_textbox().
+ * 'page' will be updated to point to the desired line in 'buf'.
+ */
+static void back_lines(int n)
+{
+ int i;
+
+ begin_reached = 0;
+ /* Go back 'n' lines */
+ for (i = 0; i < n; i++) {
+ if (*page == '\0') {
+ if (end_reached) {
+ end_reached = 0;
+ continue;
+ }
+ }
+ if (page == buf) {
+ begin_reached = 1;
+ return;
+ }
+ page--;
+ do {
+ if (page == buf) {
+ begin_reached = 1;
+ return;
+ }
+ page--;
+ } while (*page != '\n');
+ page++;
+ }
+}
+
+/*
+ * Print a new page of text.
+ */
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+ update_text, void *data)
+{
+ int i, passed_end = 0;
+
+ if (update_text) {
+ char *end;
+
+ for (i = 0; i < height; i++)
+ get_line();
+ end = page;
+ back_lines(height);
+ update_text(buf, page - buf, end - buf, data);
+ }
+
+ page_length = 0;
+ for (i = 0; i < height; i++) {
+ print_line(win, i, width);
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+ wnoutrefresh(win);
+}
+
+/*
+ * Print a new line of text.
+ */
+static void print_line(WINDOW * win, int row, int width)
+{
+ char *line;
+
+ line = get_line();
+ line += MIN(strlen(line), hscroll); /* Scroll horizontally */
+ wmove(win, row, 0); /* move cursor to correct line */
+ waddch(win, ' ');
+ waddnstr(win, line, MIN(strlen(line), width - 2));
+
+ /* Clear 'residue' of previous line */
+#if OLD_NCURSES
+ {
+ int x = getcurx(win);
+ int i;
+ for (i = 0; i < width - x; i++)
+ waddch(win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+}
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static char *get_line(void)
+{
+ int i = 0;
+ static char line[MAX_LEN + 1];
+
+ end_reached = 0;
+ while (*page != '\n') {
+ if (*page == '\0') {
+ end_reached = 1;
+ break;
+ } else if (i < MAX_LEN)
+ line[i++] = *(page++);
+ else {
+ /* Truncate lines longer than MAX_LEN characters */
+ if (i == MAX_LEN)
+ line[i++] = '\0';
+ page++;
+ }
+ }
+ if (i <= MAX_LEN)
+ line[i] = '\0';
+ if (!end_reached)
+ page++; /* move past '\n' */
+
+ return line;
+}
+
+/*
+ * Print current position
+ */
+static void print_position(WINDOW * win)
+{
+ int percent;
+
+ wattrset(win, dlg.position_indicator.atr);
+ wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
+ percent = (page - buf) * 100 / strlen(buf);
+ wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
+ wprintw(win, "(%3d%%)", percent);
+}
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
new file mode 100644
index 0000000..109d531
--- /dev/null
+++ b/scripts/kconfig/lxdialog/util.c
@@ -0,0 +1,664 @@
+/*
+ * util.c
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdarg.h>
+
+#include "dialog.h"
+
+/* Needed in signal handler in mconf.c */
+int saved_x, saved_y;
+
+struct dialog_info dlg;
+
+static void set_mono_theme(void)
+{
+ dlg.screen.atr = A_NORMAL;
+ dlg.shadow.atr = A_NORMAL;
+ dlg.dialog.atr = A_NORMAL;
+ dlg.title.atr = A_BOLD;
+ dlg.border.atr = A_NORMAL;
+ dlg.button_active.atr = A_REVERSE;
+ dlg.button_inactive.atr = A_DIM;
+ dlg.button_key_active.atr = A_REVERSE;
+ dlg.button_key_inactive.atr = A_BOLD;
+ dlg.button_label_active.atr = A_REVERSE;
+ dlg.button_label_inactive.atr = A_NORMAL;
+ dlg.inputbox.atr = A_NORMAL;
+ dlg.inputbox_border.atr = A_NORMAL;
+ dlg.searchbox.atr = A_NORMAL;
+ dlg.searchbox_title.atr = A_BOLD;
+ dlg.searchbox_border.atr = A_NORMAL;
+ dlg.position_indicator.atr = A_BOLD;
+ dlg.menubox.atr = A_NORMAL;
+ dlg.menubox_border.atr = A_NORMAL;
+ dlg.item.atr = A_NORMAL;
+ dlg.item_selected.atr = A_REVERSE;
+ dlg.tag.atr = A_BOLD;
+ dlg.tag_selected.atr = A_REVERSE;
+ dlg.tag_key.atr = A_BOLD;
+ dlg.tag_key_selected.atr = A_REVERSE;
+ dlg.check.atr = A_BOLD;
+ dlg.check_selected.atr = A_REVERSE;
+ dlg.uarrow.atr = A_BOLD;
+ dlg.darrow.atr = A_BOLD;
+}
+
+#define DLG_COLOR(dialog, f, b, h) \
+do { \
+ dlg.dialog.fg = (f); \
+ dlg.dialog.bg = (b); \
+ dlg.dialog.hl = (h); \
+} while (0)
+
+static void set_classic_theme(void)
+{
+ DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true);
+ DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true);
+ DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false);
+ DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true);
+ DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true);
+ DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true);
+ DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false);
+ DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true);
+ DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false);
+ DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true);
+ DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true);
+ DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false);
+ DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false);
+ DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false);
+ DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true);
+ DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true);
+ DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true);
+ DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false);
+ DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true);
+ DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false);
+ DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true);
+ DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true);
+ DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true);
+ DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true);
+ DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true);
+ DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false);
+ DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true);
+ DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true);
+ DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true);
+}
+
+static void set_blackbg_theme(void)
+{
+ DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true);
+ DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
+ DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
+ DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false);
+ DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
+
+ DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false);
+ DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false);
+ DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true);
+ DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false);
+ DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false);
+ DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true);
+
+ DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false);
+ DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false);
+
+ DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false);
+ DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true);
+ DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true);
+
+ DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false);
+
+ DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false);
+ DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true);
+
+ DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false);
+ DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false);
+
+ DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false);
+ DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true);
+ DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false);
+ DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true);
+
+ DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false);
+ DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true);
+
+ DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
+ DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
+}
+
+static void set_bluetitle_theme(void)
+{
+ set_classic_theme();
+ DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true);
+ DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true);
+ DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true);
+ DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true);
+ DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true);
+ DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true);
+ DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true);
+
+}
+
+/*
+ * Select color theme
+ */
+static int set_theme(const char *theme)
+{
+ int use_color = 1;
+ if (!theme)
+ set_bluetitle_theme();
+ else if (strcmp(theme, "classic") == 0)
+ set_classic_theme();
+ else if (strcmp(theme, "bluetitle") == 0)
+ set_bluetitle_theme();
+ else if (strcmp(theme, "blackbg") == 0)
+ set_blackbg_theme();
+ else if (strcmp(theme, "mono") == 0)
+ use_color = 0;
+
+ return use_color;
+}
+
+static void init_one_color(struct dialog_color *color)
+{
+ static int pair = 0;
+
+ pair++;
+ init_pair(pair, color->fg, color->bg);
+ if (color->hl)
+ color->atr = A_BOLD | COLOR_PAIR(pair);
+ else
+ color->atr = COLOR_PAIR(pair);
+}
+
+static void init_dialog_colors(void)
+{
+ init_one_color(&dlg.screen);
+ init_one_color(&dlg.shadow);
+ init_one_color(&dlg.dialog);
+ init_one_color(&dlg.title);
+ init_one_color(&dlg.border);
+ init_one_color(&dlg.button_active);
+ init_one_color(&dlg.button_inactive);
+ init_one_color(&dlg.button_key_active);
+ init_one_color(&dlg.button_key_inactive);
+ init_one_color(&dlg.button_label_active);
+ init_one_color(&dlg.button_label_inactive);
+ init_one_color(&dlg.inputbox);
+ init_one_color(&dlg.inputbox_border);
+ init_one_color(&dlg.searchbox);
+ init_one_color(&dlg.searchbox_title);
+ init_one_color(&dlg.searchbox_border);
+ init_one_color(&dlg.position_indicator);
+ init_one_color(&dlg.menubox);
+ init_one_color(&dlg.menubox_border);
+ init_one_color(&dlg.item);
+ init_one_color(&dlg.item_selected);
+ init_one_color(&dlg.tag);
+ init_one_color(&dlg.tag_selected);
+ init_one_color(&dlg.tag_key);
+ init_one_color(&dlg.tag_key_selected);
+ init_one_color(&dlg.check);
+ init_one_color(&dlg.check_selected);
+ init_one_color(&dlg.uarrow);
+ init_one_color(&dlg.darrow);
+}
+
+/*
+ * Setup for color display
+ */
+static void color_setup(const char *theme)
+{
+ int use_color;
+
+ use_color = set_theme(theme);
+ if (use_color && has_colors()) {
+ start_color();
+ init_dialog_colors();
+ } else
+ set_mono_theme();
+}
+
+/*
+ * Set window to attribute 'attr'
+ */
+void attr_clear(WINDOW * win, int height, int width, chtype attr)
+{
+ int i, j;
+
+ wattrset(win, attr);
+ for (i = 0; i < height; i++) {
+ wmove(win, i, 0);
+ for (j = 0; j < width; j++)
+ waddch(win, ' ');
+ }
+ touchwin(win);
+}
+
+void dialog_clear(void)
+{
+ attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
+ /* Display background title if it exists ... - SLH */
+ if (dlg.backtitle != NULL) {
+ int i;
+
+ wattrset(stdscr, dlg.screen.atr);
+ mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
+ wmove(stdscr, 1, 1);
+ for (i = 1; i < COLS - 1; i++)
+ waddch(stdscr, ACS_HLINE);
+ }
+ wnoutrefresh(stdscr);
+}
+
+/*
+ * Do some initialization for dialog
+ */
+int init_dialog(const char *backtitle)
+{
+ int height, width;
+
+ initscr(); /* Init curses */
+
+ /* Get current cursor position for signal handler in mconf.c */
+ getyx(stdscr, saved_y, saved_x);
+
+ getmaxyx(stdscr, height, width);
+ if (height < 19 || width < 80) {
+ endwin();
+ return -ERRDISPLAYTOOSMALL;
+ }
+
+ dlg.backtitle = backtitle;
+ color_setup(getenv("MENUCONFIG_COLOR"));
+
+ keypad(stdscr, TRUE);
+ cbreak();
+ noecho();
+ dialog_clear();
+
+ return 0;
+}
+
+void set_dialog_backtitle(const char *backtitle)
+{
+ dlg.backtitle = backtitle;
+}
+
+/*
+ * End using dialog functions.
+ */
+void end_dialog(int x, int y)
+{
+ /* move cursor back to original position */
+ move(y, x);
+ refresh();
+ endwin();
+}
+
+/* Print the title of the dialog. Center the title and truncate
+ * tile if wider than dialog (- 2 chars).
+ **/
+void print_title(WINDOW *dialog, const char *title, int width)
+{
+ if (title) {
+ int tlen = MIN(width - 2, strlen(title));
+ wattrset(dialog, dlg.title.atr);
+ mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
+ mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
+ waddch(dialog, ' ');
+ }
+}
+
+/*
+ * Print a string of text in a window, automatically wrap around to the
+ * next line if the string is too long to fit on one line. Newline
+ * characters '\n' are replaced by spaces. We start on a new line
+ * if there is no room for at least 4 nonblanks following a double-space.
+ */
+void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
+{
+ int newl, cur_x, cur_y;
+ int i, prompt_len, room, wlen;
+ char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
+
+ strcpy(tempstr, prompt);
+
+ prompt_len = strlen(tempstr);
+
+ /*
+ * Remove newlines
+ */
+ for (i = 0; i < prompt_len; i++) {
+ if (tempstr[i] == '\n')
+ tempstr[i] = ' ';
+ }
+
+ if (prompt_len <= width - x * 2) { /* If prompt is short */
+ wmove(win, y, (width - prompt_len) / 2);
+ waddstr(win, tempstr);
+ } else {
+ cur_x = x;
+ cur_y = y;
+ newl = 1;
+ word = tempstr;
+ while (word && *word) {
+ sp = strchr(word, ' ');
+ if (sp)
+ *sp++ = 0;
+
+ /* Wrap to next line if either the word does not fit,
+ or it is the first word of a new sentence, and it is
+ short, and the next word does not fit. */
+ room = width - cur_x;
+ wlen = strlen(word);
+ if (wlen > room ||
+ (newl && wlen < 4 && sp
+ && wlen + 1 + strlen(sp) > room
+ && (!(sp2 = strchr(sp, ' '))
+ || wlen + 1 + (sp2 - sp) > room))) {
+ cur_y++;
+ cur_x = x;
+ }
+ wmove(win, cur_y, cur_x);
+ waddstr(win, word);
+ getyx(win, cur_y, cur_x);
+ cur_x++;
+ if (sp && *sp == ' ') {
+ cur_x++; /* double space */
+ while (*++sp == ' ') ;
+ newl = 1;
+ } else
+ newl = 0;
+ word = sp;
+ }
+ }
+}
+
+/*
+ * Print a button
+ */
+void print_button(WINDOW * win, const char *label, int y, int x, int selected)
+{
+ int i, temp;
+
+ wmove(win, y, x);
+ wattrset(win, selected ? dlg.button_active.atr
+ : dlg.button_inactive.atr);
+ waddstr(win, "<");
+ temp = strspn(label, " ");
+ label += temp;
+ wattrset(win, selected ? dlg.button_label_active.atr
+ : dlg.button_label_inactive.atr);
+ for (i = 0; i < temp; i++)
+ waddch(win, ' ');
+ wattrset(win, selected ? dlg.button_key_active.atr
+ : dlg.button_key_inactive.atr);
+ waddch(win, label[0]);
+ wattrset(win, selected ? dlg.button_label_active.atr
+ : dlg.button_label_inactive.atr);
+ waddstr(win, (char *)label + 1);
+ wattrset(win, selected ? dlg.button_active.atr
+ : dlg.button_inactive.atr);
+ waddstr(win, ">");
+ wmove(win, y, x + temp + 1);
+}
+
+/*
+ * Draw a rectangular box with line drawing characters
+ */
+void
+draw_box(WINDOW * win, int y, int x, int height, int width,
+ chtype box, chtype border)
+{
+ int i, j;
+
+ wattrset(win, 0);
+ for (i = 0; i < height; i++) {
+ wmove(win, y + i, x);
+ for (j = 0; j < width; j++)
+ if (!i && !j)
+ waddch(win, border | ACS_ULCORNER);
+ else if (i == height - 1 && !j)
+ waddch(win, border | ACS_LLCORNER);
+ else if (!i && j == width - 1)
+ waddch(win, box | ACS_URCORNER);
+ else if (i == height - 1 && j == width - 1)
+ waddch(win, box | ACS_LRCORNER);
+ else if (!i)
+ waddch(win, border | ACS_HLINE);
+ else if (i == height - 1)
+ waddch(win, box | ACS_HLINE);
+ else if (!j)
+ waddch(win, border | ACS_VLINE);
+ else if (j == width - 1)
+ waddch(win, box | ACS_VLINE);
+ else
+ waddch(win, box | ' ');
+ }
+}
+
+/*
+ * Draw shadows along the right and bottom edge to give a more 3D look
+ * to the boxes
+ */
+void draw_shadow(WINDOW * win, int y, int x, int height, int width)
+{
+ int i;
+
+ if (has_colors()) { /* Whether terminal supports color? */
+ wattrset(win, dlg.shadow.atr);
+ wmove(win, y + height, x + 2);
+ for (i = 0; i < width; i++)
+ waddch(win, winch(win) & A_CHARTEXT);
+ for (i = y + 1; i < y + height + 1; i++) {
+ wmove(win, i, x + width);
+ waddch(win, winch(win) & A_CHARTEXT);
+ waddch(win, winch(win) & A_CHARTEXT);
+ }
+ wnoutrefresh(win);
+ }
+}
+
+/*
+ * Return the position of the first alphabetic character in a string.
+ */
+int first_alpha(const char *string, const char *exempt)
+{
+ int i, in_paren = 0, c;
+
+ for (i = 0; i < strlen(string); i++) {
+ c = tolower(string[i]);
+
+ if (strchr("<[(", c))
+ ++in_paren;
+ if (strchr(">])", c) && in_paren > 0)
+ --in_paren;
+
+ if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
+ return i;
+ }
+
+ return 0;
+}
+
+/*
+ * ncurses uses ESC to detect escaped char sequences. This resutl in
+ * a small timeout before ESC is actually delivered to the application.
+ * lxdialog suggest <ESC> <ESC> which is correctly translated to two
+ * times esc. But then we need to ignore the second esc to avoid stepping
+ * out one menu too much. Filter away all escaped key sequences since
+ * keypad(FALSE) turn off ncurses support for escape sequences - and thats
+ * needed to make notimeout() do as expected.
+ */
+int on_key_esc(WINDOW *win)
+{
+ int key;
+ int key2;
+ int key3;
+
+ nodelay(win, TRUE);
+ keypad(win, FALSE);
+ key = wgetch(win);
+ key2 = wgetch(win);
+ do {
+ key3 = wgetch(win);
+ } while (key3 != ERR);
+ nodelay(win, FALSE);
+ keypad(win, TRUE);
+ if (key == KEY_ESC && key2 == ERR)
+ return KEY_ESC;
+ else if (key != ERR && key != KEY_ESC && key2 == ERR)
+ ungetch(key);
+
+ return -1;
+}
+
+/* redraw screen in new size */
+int on_key_resize(void)
+{
+ dialog_clear();
+ return KEY_RESIZE;
+}
+
+struct dialog_list *item_cur;
+struct dialog_list item_nil;
+struct dialog_list *item_head;
+
+void item_reset(void)
+{
+ struct dialog_list *p, *next;
+
+ for (p = item_head; p; p = next) {
+ next = p->next;
+ free(p);
+ }
+ item_head = NULL;
+ item_cur = &item_nil;
+}
+
+void item_make(const char *fmt, ...)
+{
+ va_list ap;
+ struct dialog_list *p = malloc(sizeof(*p));
+
+ if (item_head)
+ item_cur->next = p;
+ else
+ item_head = p;
+ item_cur = p;
+ memset(p, 0, sizeof(*p));
+
+ va_start(ap, fmt);
+ vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
+ va_end(ap);
+}
+
+void item_add_str(const char *fmt, ...)
+{
+ va_list ap;
+ size_t avail;
+
+ avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
+
+ va_start(ap, fmt);
+ vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
+ avail, fmt, ap);
+ item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
+ va_end(ap);
+}
+
+void item_set_tag(char tag)
+{
+ item_cur->node.tag = tag;
+}
+void item_set_data(void *ptr)
+{
+ item_cur->node.data = ptr;
+}
+
+void item_set_selected(int val)
+{
+ item_cur->node.selected = val;
+}
+
+int item_activate_selected(void)
+{
+ item_foreach()
+ if (item_is_selected())
+ return 1;
+ return 0;
+}
+
+void *item_data(void)
+{
+ return item_cur->node.data;
+}
+
+char item_tag(void)
+{
+ return item_cur->node.tag;
+}
+
+int item_count(void)
+{
+ int n = 0;
+ struct dialog_list *p;
+
+ for (p = item_head; p; p = p->next)
+ n++;
+ return n;
+}
+
+void item_set(int n)
+{
+ int i = 0;
+ item_foreach()
+ if (i++ == n)
+ return;
+}
+
+int item_n(void)
+{
+ int n = 0;
+ struct dialog_list *p;
+
+ for (p = item_head; p; p = p->next) {
+ if (p == item_cur)
+ return n;
+ n++;
+ }
+ return 0;
+}
+
+const char *item_str(void)
+{
+ return item_cur->node.str;
+}
+
+int item_is_selected(void)
+{
+ return (item_cur->node.selected != 0);
+}
+
+int item_is_tag(char tag)
+{
+ return (item_cur->node.tag == tag);
+}
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c
new file mode 100644
index 0000000..4e6e809
--- /dev/null
+++ b/scripts/kconfig/lxdialog/yesno.c
@@ -0,0 +1,114 @@
+/*
+ * yesno.c -- implements the yes/no box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display termination buttons
+ */
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 10;
+ int y = height - 2;
+
+ print_button(dialog, gettext(" Yes "), y, x, selected == 0);
+ print_button(dialog, gettext(" No "), y, x + 13, selected == 1);
+
+ wmove(dialog, y, x + 1 + 13 * selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box with two buttons - Yes and No
+ */
+int dialog_yesno(const char *title, const char *prompt, int height, int width)
+{
+ int i, x, y, key = 0, button = 0;
+ WINDOW *dialog;
+
+do_resize:
+ if (getmaxy(stdscr) < (height + 4))
+ return -ERRDISPLAYTOOSMALL;
+ if (getmaxx(stdscr) < (width + 4))
+ return -ERRDISPLAYTOOSMALL;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width,
+ dlg.dialog.atr, dlg.border.atr);
+ wattrset(dialog, dlg.border.atr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dlg.dialog.atr);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dlg.dialog.atr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ print_buttons(dialog, height, width, 0);
+
+ while (key != KEY_ESC) {
+ key = wgetch(dialog);
+ switch (key) {
+ case 'Y':
+ case 'y':
+ delwin(dialog);
+ return 0;
+ case 'N':
+ case 'n':
+ delwin(dialog);
+ return 1;
+
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh(dialog);
+ break;
+ case ' ':
+ case '\n':
+ delwin(dialog);
+ return button;
+ case KEY_ESC:
+ key = on_key_esc(dialog);
+ break;
+ case KEY_RESIZE:
+ delwin(dialog);
+ on_key_resize();
+ goto do_resize;
+ }
+ }
+
+ delwin(dialog);
+ return key; /* ESC pressed */
+}
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
new file mode 100644
index 0000000..566288a
--- /dev/null
+++ b/scripts/kconfig/mconf.c
@@ -0,0 +1,963 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Introduced single menu mode (show all sub-menus in one large tree).
+ * 2002-11-06 Petr Baudis <pasky at ucw.cz>
+ *
+ * i18n, 2005, Arnaldo Carvalho de Melo <acme at conectiva.com.br>
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <locale.h>
+
+#include "lkc.h"
+#include "lxdialog/dialog.h"
+
+static const char mconf_readme[] = N_(
+"Overview\n"
+"--------\n"
+"This interface let you select features and parameters for the build.\n"
+"Features can either be built-in, modularized, or ignored. Parameters\n"
+"must be entered in as decimal or hexadecimal numbers or text.\n"
+"\n"
+"Menu items beginning with following braces represent features that\n"
+" [ ] can be built in or removed\n"
+" < > can be built in, modularized or removed\n"
+" { } can be built in or modularized (selected by other feature)\n"
+" - - are selected by other feature,\n"
+"while *, M or whitespace inside braces means to build in, build as\n"
+"a module or to exclude the feature respectively.\n"
+"\n"
+"To change any of these features, highlight it with the cursor\n"
+"keys and press <Y> to build it in, <M> to make it a module or\n"
+"<N> to removed it. You may also press the <Space Bar> to cycle\n"
+"through the available options (ie. Y->N->M->Y).\n"
+"\n"
+"Some additional keyboard hints:\n"
+"\n"
+"Menus\n"
+"----------\n"
+"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
+" you wish to change or submenu wish to select and press <Enter>.\n"
+" Submenus are designated by \"--->\".\n"
+"\n"
+" Shortcut: Press the option's highlighted letter (hotkey).\n"
+" Pressing a hotkey more than once will sequence\n"
+" through all visible items which use that hotkey.\n"
+"\n"
+" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
+" unseen options into view.\n"
+"\n"
+"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
+" and press <ENTER>.\n"
+"\n"
+" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
+" using those letters. You may press a single <ESC>, but\n"
+" there is a delayed response which you may find annoying.\n"
+"\n"
+" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
+" <Exit> and <Help>.\n"
+"\n"
+"o To get help with an item, use the cursor keys to highlight <Help>\n"
+" and press <ENTER>.\n"
+"\n"
+" Shortcut: Press <H> or <?>.\n"
+"\n"
+"o To toggle the display of hidden options, press <Z>.\n"
+"\n"
+"\n"
+"Radiolists (Choice lists)\n"
+"-----------\n"
+"o Use the cursor keys to select the option you wish to set and press\n"
+" <S> or the <SPACE BAR>.\n"
+"\n"
+" Shortcut: Press the first letter of the option you wish to set then\n"
+" press <S> or <SPACE BAR>.\n"
+"\n"
+"o To see available help for the item, use the cursor keys to highlight\n"
+" <Help> and Press <ENTER>.\n"
+"\n"
+" Shortcut: Press <H> or <?>.\n"
+"\n"
+" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
+" <Help>\n"
+"\n"
+"\n"
+"Data Entry\n"
+"-----------\n"
+"o Enter the requested information and press <ENTER>\n"
+" If you are entering hexadecimal values, it is not necessary to\n"
+" add the '0x' prefix to the entry.\n"
+"\n"
+"o For help, use the <TAB> or cursor keys to highlight the help option\n"
+" and press <ENTER>. You can try <TAB><H> as well.\n"
+"\n"
+"\n"
+"Text Box (Help Window)\n"
+"--------\n"
+"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
+" keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for \n"
+" those who are familiar with less and lynx.\n"
+"\n"
+"o Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n"
+"\n"
+"\n"
+"Alternate Configuration Files\n"
+"-----------------------------\n"
+"Menuconfig supports the use of alternate configuration files for\n"
+"those who, for various reasons, find it necessary to switch\n"
+"between different configurations.\n"
+"\n"
+"At the end of the main menu you will find two options. One is\n"
+"for saving the current configuration to a file of your choosing.\n"
+"The other option is for loading a previously saved alternate\n"
+"configuration.\n"
+"\n"
+"Even if you don't use alternate configuration files, but you\n"
+"find during a Menuconfig session that you have completely messed\n"
+"up your settings, you may use the \"Load Alternate...\" option to\n"
+"restore your previously saved settings from \".config\" without\n"
+"restarting Menuconfig.\n"
+"\n"
+"Other information\n"
+"-----------------\n"
+"If you use Menuconfig in an XTERM window make sure you have your\n"
+"$TERM variable set to point to a xterm definition which supports color.\n"
+"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
+"display correctly in a RXVT window because rxvt displays only one\n"
+"intensity of color, bright.\n"
+"\n"
+"Menuconfig will display larger menus on screens or xterms which are\n"
+"set to display more than the standard 25 row by 80 column geometry.\n"
+"In order for this to work, the \"stty size\" command must be able to\n"
+"display the screen's current row and column geometry. I STRONGLY\n"
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
+"LINES and COLUMNS exported into your environment. Some distributions\n"
+"export those variables via /etc/profile. Some ncurses programs can\n"
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
+"the true screen size.\n"
+"\n"
+"Optional personality available\n"
+"------------------------------\n"
+"If you prefer to have all of the options listed in a single menu, rather\n"
+"than the default multimenu hierarchy, run the menuconfig with\n"
+"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
+"\n"
+"make MENUCONFIG_MODE=single_menu menuconfig\n"
+"\n"
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
+"is already unrolled.\n"
+"\n"
+"Note that this mode can eventually be a little more CPU expensive\n"
+"(especially with a larger number of unrolled categories) than the\n"
+"default mode.\n"
+"\n"
+"Different color themes available\n"
+"--------------------------------\n"
+"It is possible to select different color themes using the variable\n"
+"MENUCONFIG_COLOR. To select a theme use:\n"
+"\n"
+"make MENUCONFIG_COLOR=<theme> menuconfig\n"
+"\n"
+"Available themes are\n"
+" mono => selects colors suitable for monochrome displays\n"
+" blackbg => selects a color scheme with black background\n"
+" classic => theme with blue background. The classic look\n"
+" bluetitle => a LCD friendly version of classic. (default)\n"
+"\n"),
+menu_instructions[] = N_(
+ "Arrow keys navigate the menu. "
+ "<Enter> selects submenus --->. "
+ "Highlighted letters are hotkeys. "
+ "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
+ "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
+ "Legend: [*] built-in [ ] excluded <M> module < > module capable"),
+radiolist_instructions[] = N_(
+ "Use the arrow keys to navigate this window or "
+ "press the hotkey of the item you wish to select "
+ "followed by the <SPACE BAR>. "
+ "Press <?> for additional information about this option."),
+inputbox_instructions_int[] = N_(
+ "Please enter a decimal value. "
+ "Fractions will not be accepted. "
+ "Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_hex[] = N_(
+ "Please enter a hexadecimal value. "
+ "Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_string[] = N_(
+ "Please enter a string value. "
+ "Use the <TAB> key to move from the input field to the buttons below it."),
+setmod_text[] = N_(
+ "This feature depends on another which has been configured as a module.\n"
+ "As a result, this feature will be built as a module."),
+load_config_text[] = N_(
+ "Enter the name of the configuration file you wish to load. "
+ "Accept the name shown to restore the configuration you "
+ "last retrieved. Leave blank to abort."),
+load_config_help[] = N_(
+ "\n"
+ "For various reasons, one may wish to keep several different\n"
+ "configurations available on a single machine.\n"
+ "\n"
+ "If you have saved a previous configuration in a file other than the\n"
+ "default one, entering its name here will allow you to modify that\n"
+ "configuration.\n"
+ "\n"
+ "If you are uncertain, then you have probably never used alternate\n"
+ "configuration files. You should therefore leave this blank to abort.\n"),
+save_config_text[] = N_(
+ "Enter a filename to which this configuration should be saved "
+ "as an alternate. Leave blank to abort."),
+save_config_help[] = N_(
+ "\n"
+ "For various reasons, one may wish to keep different configurations\n"
+ "available on a single machine.\n"
+ "\n"
+ "Entering a file name here will allow you to later retrieve, modify\n"
+ "and use the current configuration as an alternate to whatever\n"
+ "configuration options you have selected at that time.\n"
+ "\n"
+ "If you are uncertain what all this means then you should probably\n"
+ "leave this blank.\n"),
+search_help[] = N_(
+ "\n"
+ "Search for symbols and display their relations.\n"
+ "Regular expressions are allowed.\n"
+ "Example: search for \"^FOO\"\n"
+ "Result:\n"
+ "-----------------------------------------------------------------\n"
+ "Symbol: FOO [=m]\n"
+ "Type : tristate\n"
+ "Prompt: Foo bus is used to drive the bar HW\n"
+ " Defined at drivers/pci/Kconfig:47\n"
+ " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+ " Location:\n"
+ " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
+ " -> PCI support (PCI [=y])\n"
+ "(1) -> PCI access mode (<choice> [=y])\n"
+ " Selects: LIBCRC32\n"
+ " Selected by: BAR\n"
+ "-----------------------------------------------------------------\n"
+ "o The line 'Type:' shows the type of the configuration option for\n"
+ " this symbol (boolean, tristate, string, ...)\n"
+ "o The line 'Prompt:' shows the text used in the menu structure for\n"
+ " this symbol\n"
+ "o The 'Defined at' line tell at what file / line number the symbol\n"
+ " is defined\n"
+ "o The 'Depends on:' line tell what symbols needs to be defined for\n"
+ " this symbol to be visible in the menu (selectable)\n"
+ "o The 'Location:' lines tell where in the menu structure this symbol\n"
+ " is located\n"
+ " A location followed by a [=y] indicates that this is a\n"
+ " selectable menu item - and the current value is displayed inside\n"
+ " brackets.\n"
+ " Press the key in the (#) prefix to jump directly to that\n"
+ " location. You will be returned to the current search results\n"
+ " after exiting this new menu.\n"
+ "o The 'Selects:' line tell what symbol will be automatically\n"
+ " selected if this symbol is selected (y or m)\n"
+ "o The 'Selected by' line tell what symbol has selected this symbol\n"
+ "\n"
+ "Only relevant lines are shown.\n"
+ "\n\n"
+ "Search examples:\n"
+ "Examples: USB => find all symbols containing USB\n"
+ " ^USB => find all symbols starting with USB\n"
+ " USB$ => find all symbols ending with USB\n"
+ "\n");
+
+static int indent;
+static struct menu *current_menu;
+static int child_count;
+static int single_menu_mode;
+static int show_all_options;
+static int save_and_exit;
+
+static void conf(struct menu *menu, struct menu *active_menu);
+static void conf_choice(struct menu *menu);
+static void conf_string(struct menu *menu);
+static void conf_load(void);
+static void conf_save(void);
+static int show_textbox_ext(const char *title, char *text, int r, int c,
+ int *keys, int *vscroll, int *hscroll,
+ update_text_fn update_text, void *data);
+static void show_textbox(const char *title, const char *text, int r, int c);
+static void show_helptext(const char *title, const char *text);
+static void show_help(struct menu *menu);
+
+static char filename[PATH_MAX+1];
+static void set_config_filename(const char *config_filename)
+{
+ static char menu_backtitle[PATH_MAX+128];
+ int size;
+
+ size = snprintf(menu_backtitle, sizeof(menu_backtitle),
+ "%s - %s", config_filename, rootmenu.prompt->text);
+ if (size >= sizeof(menu_backtitle))
+ menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
+ set_dialog_backtitle(menu_backtitle);
+
+ size = snprintf(filename, sizeof(filename), "%s", config_filename);
+ if (size >= sizeof(filename))
+ filename[sizeof(filename)-1] = '\0';
+}
+
+
+struct search_data {
+ struct list_head *head;
+ struct menu **targets;
+ int *keys;
+};
+
+static void update_text(char *buf, size_t start, size_t end, void *_data)
+{
+ struct search_data *data = _data;
+ struct jump_key *pos;
+ int k = 0;
+
+ list_for_each_entry(pos, data->head, entries) {
+ if (pos->offset >= start && pos->offset < end) {
+ char header[4];
+
+ if (k < JUMP_NB) {
+ int key = '0' + (pos->index % JUMP_NB) + 1;
+
+ sprintf(header, "(%c)", key);
+ data->keys[k] = key;
+ data->targets[k] = pos->target;
+ k++;
+ } else {
+ sprintf(header, " ");
+ }
+
+ memcpy(buf + pos->offset, header, sizeof(header) - 1);
+ }
+ }
+ data->keys[k] = 0;
+}
+
+static void search_conf(void)
+{
+ struct symbol **sym_arr;
+ struct gstr res;
+ struct gstr title;
+ char *dialog_input;
+ int dres, vscroll = 0, hscroll = 0;
+ bool again;
+
+ title = str_new();
+ str_printf( &title, _("Enter %s (sub)string to search for "
+ "(with or without \"%s\")"), CONFIG_, CONFIG_);
+
+again:
+ dialog_clear();
+ dres = dialog_inputbox(_("Search Configuration Parameter"),
+ str_get(&title),
+ 10, 75, "");
+ switch (dres) {
+ case 0:
+ break;
+ case 1:
+ show_helptext(_("Search Configuration"), search_help);
+ goto again;
+ default:
+ str_free(&title);
+ return;
+ }
+
+ /* strip the prefix if necessary */
+ dialog_input = dialog_input_result;
+ if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
+ dialog_input += strlen(CONFIG_);
+
+ sym_arr = sym_re_search(dialog_input);
+ do {
+ LIST_HEAD(head);
+ struct menu *targets[JUMP_NB];
+ int keys[JUMP_NB + 1], i;
+ struct search_data data = {
+ .head = &head,
+ .targets = targets,
+ .keys = keys,
+ };
+
+ res = get_relations_str(sym_arr, &head);
+ dres = show_textbox_ext(_("Search Results"), (char *)
+ str_get(&res), 0, 0, keys, &vscroll,
+ &hscroll, &update_text, (void *)
+ &data);
+ again = false;
+ for (i = 0; i < JUMP_NB && keys[i]; i++)
+ if (dres == keys[i]) {
+ conf(targets[i]->parent, targets[i]);
+ again = true;
+ }
+ str_free(&res);
+ } while (again);
+ free(sym_arr);
+ str_free(&title);
+}
+
+static void build_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+ int type, tmp, doint = 2;
+ tristate val;
+ char ch;
+ bool visible;
+
+ /*
+ * note: menu_is_visible() has side effect that it will
+ * recalc the value of the symbol.
+ */
+ visible = menu_is_visible(menu);
+ if (show_all_options && !menu_has_prompt(menu))
+ return;
+ else if (!show_all_options && !visible)
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (!sym) {
+ if (prop && menu != current_menu) {
+ const char *prompt = menu_get_prompt(menu);
+ switch (prop->type) {
+ case P_MENU:
+ child_count++;
+ prompt = _(prompt);
+ if (single_menu_mode) {
+ item_make("%s%*c%s",
+ menu->data ? "-->" : "++>",
+ indent + 1, ' ', prompt);
+ } else
+ item_make(" %*c%s --->", indent + 1, ' ', prompt);
+
+ item_set_tag('m');
+ item_set_data(menu);
+ if (single_menu_mode && menu->data)
+ goto conf_childs;
+ return;
+ case P_COMMENT:
+ if (prompt) {
+ child_count++;
+ item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt));
+ item_set_tag(':');
+ item_set_data(menu);
+ }
+ break;
+ default:
+ if (prompt) {
+ child_count++;
+ item_make("---%*c%s", indent + 1, ' ', _(prompt));
+ item_set_tag(':');
+ item_set_data(menu);
+ }
+ }
+ } else
+ doint = 0;
+ goto conf_childs;
+ }
+
+ type = sym_get_type(sym);
+ if (sym_is_choice(sym)) {
+ struct symbol *def_sym = sym_get_choice_value(sym);
+ struct menu *def_menu = NULL;
+
+ child_count++;
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child) && child->sym == def_sym)
+ def_menu = child;
+ }
+
+ val = sym_get_tristate_value(sym);
+ if (sym_is_changable(sym)) {
+ switch (type) {
+ case S_BOOLEAN:
+ item_make("[%c]", val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes: ch = '*'; break;
+ case mod: ch = 'M'; break;
+ default: ch = ' '; break;
+ }
+ item_make("<%c>", ch);
+ break;
+ }
+ item_set_tag('t');
+ item_set_data(menu);
+ } else {
+ item_make(" ");
+ item_set_tag(def_menu ? 't' : ':');
+ item_set_data(menu);
+ }
+
+ item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
+ if (val == yes) {
+ if (def_menu) {
+ item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
+ item_add_str(" --->");
+ if (def_menu->list) {
+ indent += 2;
+ build_conf(def_menu);
+ indent -= 2;
+ }
+ }
+ return;
+ }
+ } else {
+ if (menu == current_menu) {
+ item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
+ item_set_tag(':');
+ item_set_data(menu);
+ goto conf_childs;
+ }
+ child_count++;
+ val = sym_get_tristate_value(sym);
+ if (sym_is_choice_value(sym) && val == yes) {
+ item_make(" ");
+ item_set_tag(':');
+ item_set_data(menu);
+ } else {
+ switch (type) {
+ case S_BOOLEAN:
+ if (sym_is_changable(sym))
+ item_make("[%c]", val == no ? ' ' : '*');
+ else
+ item_make("-%c-", val == no ? ' ' : '*');
+ item_set_tag('t');
+ item_set_data(menu);
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes: ch = '*'; break;
+ case mod: ch = 'M'; break;
+ default: ch = ' '; break;
+ }
+ if (sym_is_changable(sym)) {
+ if (sym->rev_dep.tri == mod)
+ item_make("{%c}", ch);
+ else
+ item_make("<%c>", ch);
+ } else
+ item_make("-%c-", ch);
+ item_set_tag('t');
+ item_set_data(menu);
+ break;
+ default:
+ tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
+ item_make("(%s)", sym_get_string_value(sym));
+ tmp = indent - tmp + 4;
+ if (tmp < 0)
+ tmp = 0;
+ item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : _(" (NEW)"));
+ item_set_tag('s');
+ item_set_data(menu);
+ goto conf_childs;
+ }
+ }
+ item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : _(" (NEW)"));
+ if (menu->prompt->type == P_MENU) {
+ item_add_str(" --->");
+ return;
+ }
+ }
+
+conf_childs:
+ indent += doint;
+ for (child = menu->list; child; child = child->next)
+ build_conf(child);
+ indent -= doint;
+}
+
+static void conf(struct menu *menu, struct menu *active_menu)
+{
+ struct menu *submenu;
+ const char *prompt = menu_get_prompt(menu);
+ struct symbol *sym;
+ int res;
+ int s_scroll = 0;
+
+ while (1) {
+ item_reset();
+ current_menu = menu;
+ build_conf(menu);
+ if (!child_count)
+ break;
+ dialog_clear();
+ res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
+ _(menu_instructions),
+ active_menu, &s_scroll);
+ if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
+ break;
+ if (!item_activate_selected())
+ continue;
+ if (!item_tag())
+ continue;
+
+ submenu = item_data();
+ active_menu = item_data();
+ if (submenu)
+ sym = submenu->sym;
+ else
+ sym = NULL;
+
+ switch (res) {
+ case 0:
+ switch (item_tag()) {
+ case 'm':
+ if (single_menu_mode)
+ submenu->data = (void *) (long) !submenu->data;
+ else
+ conf(submenu, NULL);
+ break;
+ case 't':
+ if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
+ conf_choice(submenu);
+ else if (submenu->prompt->type == P_MENU)
+ conf(submenu, NULL);
+ break;
+ case 's':
+ conf_string(submenu);
+ break;
+ }
+ break;
+ case 2:
+ if (sym)
+ show_help(submenu);
+ else
+ show_helptext(_("README"), _(mconf_readme));
+ break;
+ case 3:
+ conf_save();
+ break;
+ case 4:
+ conf_load();
+ break;
+ case 5:
+ if (item_is_tag('t')) {
+ if (sym_set_tristate_value(sym, yes))
+ break;
+ if (sym_set_tristate_value(sym, mod))
+ show_textbox(NULL, setmod_text, 6, 74);
+ }
+ break;
+ case 6:
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, no);
+ break;
+ case 7:
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, mod);
+ break;
+ case 8:
+ if (item_is_tag('t'))
+ sym_toggle_tristate_value(sym);
+ else if (item_is_tag('m'))
+ conf(submenu, NULL);
+ break;
+ case 9:
+ search_conf();
+ break;
+ case 10:
+ show_all_options = !show_all_options;
+ break;
+ }
+ }
+}
+
+static int show_textbox_ext(const char *title, char *text, int r, int c, int
+ *keys, int *vscroll, int *hscroll, update_text_fn
+ update_text, void *data)
+{
+ dialog_clear();
+ return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
+ update_text, data);
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+ show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
+ NULL, NULL);
+}
+
+static void show_helptext(const char *title, const char *text)
+{
+ show_textbox(title, text, 0, 0);
+}
+
+static void conf_message_callback(const char *fmt, va_list ap)
+{
+ char buf[PATH_MAX+1];
+
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ if (save_and_exit)
+ printf("%s", buf);
+ else
+ show_textbox(NULL, buf, 6, 60);
+}
+
+static void show_help(struct menu *menu)
+{
+ struct gstr help = str_new();
+
+ help.max_width = getmaxx(stdscr) - 10;
+ menu_get_ext_help(menu, &help);
+
+ show_helptext(_(menu_get_prompt(menu)), str_get(&help));
+ str_free(&help);
+}
+
+static void conf_choice(struct menu *menu)
+{
+ const char *prompt = _(menu_get_prompt(menu));
+ struct menu *child;
+ struct symbol *active;
+
+ active = sym_get_choice_value(menu->sym);
+ while (1) {
+ int res;
+ int selected;
+ item_reset();
+
+ current_menu = menu;
+ for (child = menu->list; child; child = child->next) {
+ if (!menu_is_visible(child))
+ continue;
+ if (child->sym)
+ item_make("%s", _(menu_get_prompt(child)));
+ else {
+ item_make("*** %s ***", _(menu_get_prompt(child)));
+ item_set_tag(':');
+ }
+ item_set_data(child);
+ if (child->sym == active)
+ item_set_selected(1);
+ if (child->sym == sym_get_choice_value(menu->sym))
+ item_set_tag('X');
+ }
+ dialog_clear();
+ res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
+ _(radiolist_instructions),
+ 15, 70, 6);
+ selected = item_activate_selected();
+ switch (res) {
+ case 0:
+ if (selected) {
+ child = item_data();
+ if (!child->sym)
+ break;
+
+ sym_set_tristate_value(child->sym, yes);
+ }
+ return;
+ case 1:
+ if (selected) {
+ child = item_data();
+ show_help(child);
+ active = child->sym;
+ } else
+ show_help(menu);
+ break;
+ case KEY_ESC:
+ return;
+ case -ERRDISPLAYTOOSMALL:
+ return;
+ }
+ }
+}
+
+static void conf_string(struct menu *menu)
+{
+ const char *prompt = menu_get_prompt(menu);
+
+ while (1) {
+ int res;
+ const char *heading;
+
+ switch (sym_get_type(menu->sym)) {
+ case S_INT:
+ heading = _(inputbox_instructions_int);
+ break;
+ case S_HEX:
+ heading = _(inputbox_instructions_hex);
+ break;
+ case S_STRING:
+ heading = _(inputbox_instructions_string);
+ break;
+ default:
+ heading = _("Internal mconf error!");
+ }
+ dialog_clear();
+ res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
+ heading, 10, 75,
+ sym_get_string_value(menu->sym));
+ switch (res) {
+ case 0:
+ if (sym_set_string_value(menu->sym, dialog_input_result))
+ return;
+ show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
+ break;
+ case 1:
+ show_help(menu);
+ break;
+ case KEY_ESC:
+ return;
+ }
+ }
+}
+
+static void conf_load(void)
+{
+
+ while (1) {
+ int res;
+ dialog_clear();
+ res = dialog_inputbox(NULL, load_config_text,
+ 11, 55, filename);
+ switch(res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ if (!conf_read(dialog_input_result)) {
+ set_config_filename(dialog_input_result);
+ sym_set_change_count(1);
+ return;
+ }
+ show_textbox(NULL, _("File does not exist!"), 5, 38);
+ break;
+ case 1:
+ show_helptext(_("Load Alternate Configuration"), load_config_help);
+ break;
+ case KEY_ESC:
+ return;
+ }
+ }
+}
+
+static void conf_save(void)
+{
+ while (1) {
+ int res;
+ dialog_clear();
+ res = dialog_inputbox(NULL, save_config_text,
+ 11, 55, filename);
+ switch(res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ if (!conf_write(dialog_input_result)) {
+ set_config_filename(dialog_input_result);
+ return;
+ }
+ show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
+ break;
+ case 1:
+ show_helptext(_("Save Alternate Configuration"), save_config_help);
+ break;
+ case KEY_ESC:
+ return;
+ }
+ }
+}
+
+static int handle_exit(void)
+{
+ int res;
+
+ save_and_exit = 1;
+ dialog_clear();
+ if (conf_get_changed())
+ res = dialog_yesno(NULL,
+ _("Do you wish to save your new configuration ?\n"
+ "<ESC><ESC> to continue."),
+ 6, 60);
+ else
+ res = -1;
+
+ end_dialog(saved_x, saved_y);
+
+ switch (res) {
+ case 0:
+ if (conf_write(filename)) {
+ fprintf(stderr, _("\n\n"
+ "Error while writing of the configuration.\n"
+ "Your configuration changes were NOT saved."
+ "\n\n"));
+ return 1;
+ }
+ /* fall through */
+ case -1:
+ printf(_("\n\n"
+ "*** End of the configuration.\n"
+ "*** Execute 'make' to start the build or try 'make help'."
+ "\n\n"));
+ res = 0;
+ break;
+ default:
+ fprintf(stderr, _("\n\n"
+ "Your configuration changes were NOT saved."
+ "\n\n"));
+ if (res != KEY_ESC)
+ res = 0;
+ }
+
+ return res;
+}
+
+static void sig_handler(int signo)
+{
+ exit(handle_exit());
+}
+
+int main(int ac, char **av)
+{
+ char *mode;
+ int res;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ signal(SIGINT, sig_handler);
+
+ conf_parse(av[1]);
+ conf_read(NULL);
+
+ mode = getenv("MENUCONFIG_MODE");
+ if (mode) {
+ if (!strcasecmp(mode, "single_menu"))
+ single_menu_mode = 1;
+ }
+
+ if (init_dialog(NULL)) {
+ fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
+ fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
+ return 1;
+ }
+
+ set_config_filename(conf_get_configname());
+ conf_set_message_callback(conf_message_callback);
+ do {
+ conf(&rootmenu, NULL);
+ res = handle_exit();
+ } while (res == KEY_ESC);
+
+ return res;
+}
+
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
new file mode 100644
index 0000000..f3bffa3
--- /dev/null
+++ b/scripts/kconfig/menu.c
@@ -0,0 +1,644 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lkc.h"
+
+static const char nohelp_text[] = "There is no help available for this option.";
+
+struct menu rootmenu;
+static struct menu **last_entry_ptr;
+
+struct file *file_list;
+struct file *current_file;
+
+void menu_warn(struct menu *menu, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+static void prop_warn(struct property *prop, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+void _menu_init(void)
+{
+ current_entry = current_menu = &rootmenu;
+ last_entry_ptr = &rootmenu.list;
+}
+
+void menu_add_entry(struct symbol *sym)
+{
+ struct menu *menu;
+
+ menu = xmalloc(sizeof(*menu));
+ memset(menu, 0, sizeof(*menu));
+ menu->sym = sym;
+ menu->parent = current_menu;
+ menu->file = current_file;
+ menu->lineno = zconf_lineno();
+
+ *last_entry_ptr = menu;
+ last_entry_ptr = &menu->next;
+ current_entry = menu;
+ if (sym)
+ menu_add_symbol(P_SYMBOL, sym, NULL);
+}
+
+void menu_end_entry(void)
+{
+}
+
+struct menu *menu_add_menu(void)
+{
+ menu_end_entry();
+ last_entry_ptr = ¤t_entry->list;
+ return current_menu = current_entry;
+}
+
+void menu_end_menu(void)
+{
+ last_entry_ptr = ¤t_menu->next;
+ current_menu = current_menu->parent;
+}
+
+static struct expr *menu_check_dep(struct expr *e)
+{
+ if (!e)
+ return e;
+
+ switch (e->type) {
+ case E_NOT:
+ e->left.expr = menu_check_dep(e->left.expr);
+ break;
+ case E_OR:
+ case E_AND:
+ e->left.expr = menu_check_dep(e->left.expr);
+ e->right.expr = menu_check_dep(e->right.expr);
+ break;
+ case E_SYMBOL:
+ /* change 'm' into 'm' && MODULES */
+ if (e->left.sym == &symbol_mod)
+ return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
+ break;
+ default:
+ break;
+ }
+ return e;
+}
+
+void menu_add_dep(struct expr *dep)
+{
+ current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
+}
+
+void menu_set_type(int type)
+{
+ struct symbol *sym = current_entry->sym;
+
+ if (sym->type == type)
+ return;
+ if (sym->type == S_UNKNOWN) {
+ sym->type = type;
+ return;
+ }
+ 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));
+}
+
+struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
+{
+ struct property *prop = prop_alloc(type, current_entry->sym);
+
+ prop->menu = current_entry;
+ 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 && current_entry != &rootmenu)
+ prop_warn(prop, "prompt redefined");
+
+ /* Apply all upper menus' visibilities to actual prompts. */
+ if(type == P_PROMPT) {
+ struct menu *menu = current_entry;
+
+ while ((menu = menu->parent) != NULL) {
+ if (!menu->visibility)
+ continue;
+ prop->visible.expr
+ = expr_alloc_and(prop->visible.expr,
+ menu->visibility);
+ }
+ }
+
+ current_entry->prompt = prop;
+ }
+ prop->text = prompt;
+
+ return prop;
+}
+
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
+{
+ return menu_add_prop(type, prompt, NULL, dep);
+}
+
+void menu_add_visibility(struct expr *expr)
+{
+ current_entry->visibility = expr_alloc_and(current_entry->visibility,
+ expr);
+}
+
+void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
+{
+ menu_add_prop(type, NULL, expr, dep);
+}
+
+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;
+ case T_OPT_ENV:
+ prop_add_env(arg);
+ break;
+ }
+}
+
+static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
+{
+ return sym2->type == S_INT || sym2->type == S_HEX ||
+ (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
+}
+
+static void sym_check_prop(struct symbol *sym)
+{
+ struct property *prop;
+ struct symbol *sym2;
+ for (prop = sym->prop; prop; prop = prop->next) {
+ switch (prop->type) {
+ case P_DEFAULT:
+ if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
+ prop->expr->type != E_SYMBOL)
+ prop_warn(prop,
+ "default for config symbol '%s'"
+ " must be a single symbol", sym->name);
+ if (prop->expr->type != E_SYMBOL)
+ break;
+ sym2 = prop_get_symbol(prop);
+ if (sym->type == S_HEX || sym->type == S_INT) {
+ if (!menu_validate_number(sym, sym2))
+ prop_warn(prop,
+ "'%s': number is invalid",
+ sym->name);
+ }
+ break;
+ case P_SELECT:
+ sym2 = prop_get_symbol(prop);
+ if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
+ prop_warn(prop,
+ "config symbol '%s' uses select, but is "
+ "not boolean or tristate", sym->name);
+ else if (sym2->type != S_UNKNOWN &&
+ sym2->type != S_BOOLEAN &&
+ sym2->type != S_TRISTATE)
+ prop_warn(prop,
+ "'%s' has wrong type. 'select' only "
+ "accept arguments of boolean and "
+ "tristate type", sym2->name);
+ break;
+ case P_RANGE:
+ if (sym->type != S_INT && sym->type != S_HEX)
+ prop_warn(prop, "range is only allowed "
+ "for int or hex symbols");
+ if (!menu_validate_number(sym, prop->expr->left.sym) ||
+ !menu_validate_number(sym, prop->expr->right.sym))
+ prop_warn(prop, "range is invalid");
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+void menu_finalize(struct menu *parent)
+{
+ struct menu *menu, *last_menu;
+ struct symbol *sym;
+ struct property *prop;
+ struct expr *parentdep, *basedep, *dep, *dep2, **ep;
+
+ sym = parent->sym;
+ if (parent->list) {
+ if (sym && sym_is_choice(sym)) {
+ if (sym->type == S_UNKNOWN) {
+ /* find the first choice value to find out choice type */
+ current_entry = parent;
+ for (menu = parent->list; menu; menu = menu->next) {
+ if (menu->sym && menu->sym->type != S_UNKNOWN) {
+ menu_set_type(menu->sym->type);
+ break;
+ }
+ }
+ }
+ /* set the type of the remaining choice values */
+ for (menu = parent->list; menu; menu = menu->next) {
+ current_entry = menu;
+ if (menu->sym && menu->sym->type == S_UNKNOWN)
+ menu_set_type(sym->type);
+ }
+ parentdep = expr_alloc_symbol(sym);
+ } else if (parent->prompt)
+ parentdep = parent->prompt->visible.expr;
+ else
+ parentdep = parent->dep;
+
+ for (menu = parent->list; menu; menu = menu->next) {
+ basedep = expr_transform(menu->dep);
+ basedep = expr_alloc_and(expr_copy(parentdep), basedep);
+ basedep = expr_eliminate_dups(basedep);
+ menu->dep = basedep;
+ if (menu->sym)
+ prop = menu->sym->prop;
+ else
+ prop = menu->prompt;
+ for (; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ dep = expr_transform(prop->visible.expr);
+ dep = expr_alloc_and(expr_copy(basedep), dep);
+ dep = expr_eliminate_dups(dep);
+ if (menu->sym && menu->sym->type != S_TRISTATE)
+ dep = expr_trans_bool(dep);
+ prop->visible.expr = dep;
+ if (prop->type == P_SELECT) {
+ struct symbol *es = prop_get_symbol(prop);
+ es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
+ expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+ }
+ }
+ }
+ for (menu = parent->list; menu; menu = menu->next)
+ menu_finalize(menu);
+ } else if (sym) {
+ basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
+ basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
+ basedep = expr_eliminate_dups(expr_transform(basedep));
+ last_menu = NULL;
+ for (menu = parent->next; menu; menu = menu->next) {
+ dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
+ if (!expr_contains_symbol(dep, sym))
+ break;
+ if (expr_depends_symbol(dep, sym))
+ goto next;
+ dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
+ dep = expr_eliminate_dups(expr_transform(dep));
+ dep2 = expr_copy(basedep);
+ expr_eliminate_eq(&dep, &dep2);
+ expr_free(dep);
+ if (!expr_is_yes(dep2)) {
+ expr_free(dep2);
+ break;
+ }
+ expr_free(dep2);
+ next:
+ menu_finalize(menu);
+ menu->parent = parent;
+ last_menu = menu;
+ }
+ if (last_menu) {
+ parent->list = parent->next;
+ parent->next = last_menu->next;
+ last_menu->next = NULL;
+ }
+
+ sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
+ }
+ for (menu = parent->list; menu; menu = menu->next) {
+ if (sym && sym_is_choice(sym) &&
+ menu->sym && !sym_is_choice_value(menu->sym)) {
+ current_entry = menu;
+ menu->sym->flags |= SYMBOL_CHOICEVAL;
+ if (!menu->prompt)
+ menu_warn(menu, "choice value must have a prompt");
+ for (prop = menu->sym->prop; prop; prop = prop->next) {
+ if (prop->type == P_DEFAULT)
+ prop_warn(prop, "defaults for choice "
+ "values not supported");
+ if (prop->menu == menu)
+ continue;
+ if (prop->type == P_PROMPT &&
+ prop->menu->parent->sym != sym)
+ prop_warn(prop, "choice value used outside its choice group");
+ }
+ /* Non-tristate choice values of tristate choices must
+ * depend on the choice being set to Y. The choice
+ * values' dependencies were propagated to their
+ * properties above, so the change here must be re-
+ * propagated.
+ */
+ if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
+ basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
+ menu->dep = expr_alloc_and(basedep, menu->dep);
+ for (prop = menu->sym->prop; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ prop->visible.expr = expr_alloc_and(expr_copy(basedep),
+ prop->visible.expr);
+ }
+ }
+ menu_add_symbol(P_CHOICE, sym, NULL);
+ prop = sym_get_choice_prop(sym);
+ for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
+ ;
+ *ep = expr_alloc_one(E_LIST, NULL);
+ (*ep)->right.sym = menu->sym;
+ }
+ if (menu->list && (!menu->prompt || !menu->prompt->text)) {
+ for (last_menu = menu->list; ; last_menu = last_menu->next) {
+ last_menu->parent = parent;
+ if (!last_menu->next)
+ break;
+ }
+ last_menu->next = menu->next;
+ menu->next = menu->list;
+ menu->list = NULL;
+ }
+ }
+
+ if (sym && !(sym->flags & SYMBOL_WARNED)) {
+ if (sym->type == S_UNKNOWN)
+ menu_warn(parent, "config symbol defined without type");
+
+ if (sym_is_choice(sym) && !parent->prompt)
+ menu_warn(parent, "choice must have a prompt");
+
+ /* Check properties connected to this symbol */
+ sym_check_prop(sym);
+ sym->flags |= SYMBOL_WARNED;
+ }
+
+ if (sym && !sym_is_optional(sym) && parent->prompt) {
+ sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
+ expr_alloc_and(parent->prompt->visible.expr,
+ expr_alloc_symbol(&symbol_mod)));
+ }
+}
+
+bool menu_has_prompt(struct menu *menu)
+{
+ if (!menu->prompt)
+ return false;
+ return true;
+}
+
+bool menu_is_visible(struct menu *menu)
+{
+ struct menu *child;
+ struct symbol *sym;
+ tristate visible;
+
+ if (!menu->prompt)
+ return false;
+
+ if (menu->visibility) {
+ if (expr_calc_value(menu->visibility) == no)
+ return no;
+ }
+
+ sym = menu->sym;
+ if (sym) {
+ sym_calc_value(sym);
+ visible = menu->prompt->visible.tri;
+ } else
+ visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
+
+ if (visible != no)
+ return true;
+
+ if (!sym || sym_get_tristate_value(menu->sym) == no)
+ return false;
+
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child)) {
+ if (sym)
+ sym->flags |= SYMBOL_DEF_USER;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+const char *menu_get_prompt(struct menu *menu)
+{
+ if (menu->prompt)
+ return menu->prompt->text;
+ else if (menu->sym)
+ return menu->sym->name;
+ return NULL;
+}
+
+struct menu *menu_get_root_menu(struct menu *menu)
+{
+ return &rootmenu;
+}
+
+struct menu *menu_get_parent_menu(struct menu *menu)
+{
+ enum prop_type type;
+
+ for (; menu != &rootmenu; menu = menu->parent) {
+ type = menu->prompt ? menu->prompt->type : 0;
+ if (type == P_MENU)
+ break;
+ }
+ return menu;
+}
+
+bool menu_has_help(struct menu *menu)
+{
+ return menu->help != NULL;
+}
+
+const char *menu_get_help(struct menu *menu)
+{
+ if (menu->help)
+ return menu->help;
+ else
+ return "";
+}
+
+static void get_prompt_str(struct gstr *r, struct property *prop,
+ struct list_head *head)
+{
+ int i, j;
+ struct menu *submenu[8], *menu, *location = NULL;
+ struct jump_key *jump;
+
+ str_printf(r, _("Prompt: %s\n"), _(prop->text));
+ str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
+ prop->menu->lineno);
+ if (!expr_is_yes(prop->visible.expr)) {
+ str_append(r, _(" Depends on: "));
+ expr_gstr_print(prop->visible.expr, r);
+ str_append(r, "\n");
+ }
+ menu = prop->menu->parent;
+ for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
+ bool accessible = menu_is_visible(menu);
+
+ submenu[i++] = menu;
+ if (location == NULL && accessible)
+ location = menu;
+ }
+ if (head && location) {
+ jump = xmalloc(sizeof(struct jump_key));
+
+ if (menu_is_visible(prop->menu)) {
+ /*
+ * There is not enough room to put the hint at the
+ * beginning of the "Prompt" line. Put the hint on the
+ * last "Location" line even when it would belong on
+ * the former.
+ */
+ jump->target = prop->menu;
+ } else
+ jump->target = location;
+
+ if (list_empty(head))
+ jump->index = 0;
+ else
+ jump->index = list_entry(head->prev, struct jump_key,
+ entries)->index + 1;
+
+ list_add_tail(&jump->entries, head);
+ }
+
+ if (i > 0) {
+ str_printf(r, _(" Location:\n"));
+ for (j = 4; --i >= 0; j += 2) {
+ menu = submenu[i];
+ if (head && location && menu == location)
+ jump->offset = r->len - 1;
+ str_printf(r, "%*c-> %s", j, ' ',
+ _(menu_get_prompt(menu)));
+ if (menu->sym) {
+ str_printf(r, " (%s [=%s])", menu->sym->name ?
+ menu->sym->name : _("<choice>"),
+ sym_get_string_value(menu->sym));
+ }
+ str_append(r, "\n");
+ }
+ }
+}
+
+/*
+ * head is optional and may be NULL
+ */
+void get_symbol_str(struct gstr *r, struct symbol *sym,
+ struct list_head *head)
+{
+ bool hit;
+ struct property *prop;
+
+ if (sym && sym->name) {
+ str_printf(r, "Symbol: %s [=%s]\n", sym->name,
+ sym_get_string_value(sym));
+ str_printf(r, "Type : %s\n", sym_type_name(sym->type));
+ if (sym->type == S_INT || sym->type == S_HEX) {
+ prop = sym_get_range_prop(sym);
+ if (prop) {
+ str_printf(r, "Range : ");
+ expr_gstr_print(prop->expr, r);
+ str_append(r, "\n");
+ }
+ }
+ }
+ for_all_prompts(sym, prop)
+ get_prompt_str(r, prop, head);
+ hit = false;
+ for_all_properties(sym, prop, P_SELECT) {
+ if (!hit) {
+ str_append(r, " Selects: ");
+ hit = true;
+ } else
+ str_printf(r, " && ");
+ expr_gstr_print(prop->expr, r);
+ }
+ if (hit)
+ str_append(r, "\n");
+ if (sym->rev_dep.expr) {
+ str_append(r, _(" Selected by: "));
+ expr_gstr_print(sym->rev_dep.expr, r);
+ str_append(r, "\n");
+ }
+ str_append(r, "\n\n");
+}
+
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
+{
+ struct symbol *sym;
+ struct gstr res = str_new();
+ int i;
+
+ for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
+ get_symbol_str(&res, sym, head);
+ if (!i)
+ str_append(&res, _("No matches found.\n"));
+ return res;
+}
+
+
+void menu_get_ext_help(struct menu *menu, struct gstr *help)
+{
+ struct symbol *sym = menu->sym;
+ const char *help_text = nohelp_text;
+
+ if (menu_has_help(menu)) {
+ if (sym->name)
+ str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
+ help_text = menu_get_help(menu);
+ }
+ str_printf(help, "%s\n", _(help_text));
+ if (sym)
+ get_symbol_str(help, sym, NULL);
+}
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
new file mode 100755
index 0000000..05274fc
--- /dev/null
+++ b/scripts/kconfig/merge_config.sh
@@ -0,0 +1,142 @@
+#!/bin/sh
+# merge_config.sh - Takes a list of config fragment values, and merges
+# them one by one. Provides warnings on overridden values, and specified
+# values that did not make it to the resulting .config file (due to missed
+# dependencies or config symbol removal).
+#
+# Portions reused from kconf_check and generate_cfg:
+# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check
+# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg
+#
+# Copyright (c) 2009-2010 Wind River Systems, Inc.
+# Copyright 2011 Linaro
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+
+clean_up() {
+ rm -f $TMP_FILE
+ exit
+}
+trap clean_up HUP INT TERM
+
+usage() {
+ echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
+ echo " -h display this help text"
+ echo " -m only merge the fragments, do not execute the make command"
+ echo " -n use allnoconfig instead of alldefconfig"
+ echo " -r list redundant entries when merging fragments"
+ echo " -O dir to put generated output files"
+}
+
+MAKE=true
+ALLTARGET=alldefconfig
+WARNREDUN=false
+OUTPUT=.
+
+while true; do
+ case $1 in
+ "-n")
+ ALLTARGET=allnoconfig
+ shift
+ continue
+ ;;
+ "-m")
+ MAKE=false
+ shift
+ continue
+ ;;
+ "-h")
+ usage
+ exit
+ ;;
+ "-r")
+ WARNREDUN=true
+ shift
+ continue
+ ;;
+ "-O")
+ if [ -d $2 ];then
+ OUTPUT=$(echo $2 | sed 's/\/*$//')
+ else
+ echo "output directory $2 does not exist" 1>&2
+ exit 1
+ fi
+ shift 2
+ continue
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+INITFILE=$1
+shift;
+
+MERGE_LIST=$*
+SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p"
+TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
+
+echo "Using $INITFILE as base"
+cat $INITFILE > $TMP_FILE
+
+# Merge files, printing warnings on overrided values
+for MERGE_FILE in $MERGE_LIST ; do
+ echo "Merging $MERGE_FILE"
+ CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE)
+
+ for CFG in $CFG_LIST ; do
+ grep -q -w $CFG $TMP_FILE
+ if [ $? -eq 0 ] ; then
+ PREV_VAL=$(grep -w $CFG $TMP_FILE)
+ NEW_VAL=$(grep -w $CFG $MERGE_FILE)
+ if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
+ echo Value of $CFG is redefined by fragment $MERGE_FILE:
+ echo Previous value: $PREV_VAL
+ echo New value: $NEW_VAL
+ echo
+ elif [ "$WARNREDUN" = "true" ]; then
+ echo Value of $CFG is redundant by fragment $MERGE_FILE:
+ fi
+ sed -i "/$CFG[ =]/d" $TMP_FILE
+ fi
+ done
+ cat $MERGE_FILE >> $TMP_FILE
+done
+
+if [ "$MAKE" = "false" ]; then
+ cp $TMP_FILE $OUTPUT/.config
+ echo "#"
+ echo "# merged configuration written to $OUTPUT/.config (needs make)"
+ echo "#"
+ clean_up
+ exit
+fi
+
+# Use the merged file as the starting point for:
+# alldefconfig: Fills in any missing symbols with Kconfig default
+# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set
+make KCONFIG_ALLCONFIG=$TMP_FILE O=$OUTPUT $ALLTARGET
+
+
+# Check all specified config values took (might have missed-dependency issues)
+for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do
+
+ REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
+ ACTUAL_VAL=$(grep -w -e "$CFG" $OUTPUT/.config)
+ if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
+ echo "Value requested for $CFG not in final .config"
+ echo "Requested value: $REQUESTED_VAL"
+ echo "Actual value: $ACTUAL_VAL"
+ echo ""
+ fi
+done
+
+clean_up
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
new file mode 100644
index 0000000..ce93e87
--- /dev/null
+++ b/scripts/kconfig/nconf.c
@@ -0,0 +1,1558 @@
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar at gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+
+#include "lkc.h"
+#include "nconf.h"
+#include <ctype.h>
+
+static const char nconf_readme[] = N_(
+"Overview\n"
+"--------\n"
+"This interface let you select features and parameters for the build.\n"
+"Features can either be built-in, modularized, or ignored. Parameters\n"
+"must be entered in as decimal or hexadecimal numbers or text.\n"
+"\n"
+"Menu items beginning with following braces represent features that\n"
+" [ ] can be built in or removed\n"
+" < > can be built in, modularized or removed\n"
+" { } can be built in or modularized (selected by other feature)\n"
+" - - are selected by other feature,\n"
+" XXX cannot be selected. Use Symbol Info to find out why,\n"
+"while *, M or whitespace inside braces means to build in, build as\n"
+"a module or to exclude the feature respectively.\n"
+"\n"
+"To change any of these features, highlight it with the cursor\n"
+"keys and press <Y> to build it in, <M> to make it a module or\n"
+"<N> to removed it. You may also press the <Space Bar> to cycle\n"
+"through the available options (ie. Y->N->M->Y).\n"
+"\n"
+"Some additional keyboard hints:\n"
+"\n"
+"Menus\n"
+"----------\n"
+"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
+" you wish to change use <Enter> or <Space>. Goto submenu by \n"
+" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
+" Submenus are designated by \"--->\".\n"
+"\n"
+" Searching: pressing '/' triggers interactive search mode.\n"
+" nconfig performs a case insensitive search for the string\n"
+" in the menu prompts (no regex support).\n"
+" Pressing the up/down keys highlights the previous/next\n"
+" matching item. Backspace removes one character from the\n"
+" match string. Pressing either '/' again or ESC exits\n"
+" search mode. All other keys behave normally.\n"
+"\n"
+" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
+" unseen options into view.\n"
+"\n"
+"o To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n"
+"\n"
+"o To get help with an item, press <F1>\n"
+" Shortcut: Press <h> or <?>.\n"
+"\n"
+"\n"
+"Radiolists (Choice lists)\n"
+"-----------\n"
+"o Use the cursor keys to select the option you wish to set and press\n"
+" <S> or the <SPACE BAR>.\n"
+"\n"
+" Shortcut: Press the first letter of the option you wish to set then\n"
+" press <S> or <SPACE BAR>.\n"
+"\n"
+"o To see available help for the item, press <F1>\n"
+" Shortcut: Press <H> or <?>.\n"
+"\n"
+"\n"
+"Data Entry\n"
+"-----------\n"
+"o Enter the requested information and press <ENTER>\n"
+" If you are entering hexadecimal values, it is not necessary to\n"
+" add the '0x' prefix to the entry.\n"
+"\n"
+"o For help, press <F1>.\n"
+"\n"
+"\n"
+"Text Box (Help Window)\n"
+"--------\n"
+"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
+" keys h,j,k,l function here as do <u>, <d> and <SPACE BAR> for\n"
+" those who are familiar with less and lynx.\n"
+"\n"
+"o Press <Enter>, <F1>, <F5>, <F9>, <q> or <Esc> to exit.\n"
+"\n"
+"\n"
+"Alternate Configuration Files\n"
+"-----------------------------\n"
+"nconfig supports the use of alternate configuration files for\n"
+"those who, for various reasons, find it necessary to switch\n"
+"between different configurations.\n"
+"\n"
+"At the end of the main menu you will find two options. One is\n"
+"for saving the current configuration to a file of your choosing.\n"
+"The other option is for loading a previously saved alternate\n"
+"configuration.\n"
+"\n"
+"Even if you don't use alternate configuration files, but you\n"
+"find during a nconfig session that you have completely messed\n"
+"up your settings, you may use the \"Load Alternate...\" option to\n"
+"restore your previously saved settings from \".config\" without\n"
+"restarting nconfig.\n"
+"\n"
+"Other information\n"
+"-----------------\n"
+"If you use nconfig in an XTERM window make sure you have your\n"
+"$TERM variable set to point to a xterm definition which supports color.\n"
+"Otherwise, nconfig will look rather bad. nconfig will not\n"
+"display correctly in a RXVT window because rxvt displays only one\n"
+"intensity of color, bright.\n"
+"\n"
+"nconfig will display larger menus on screens or xterms which are\n"
+"set to display more than the standard 25 row by 80 column geometry.\n"
+"In order for this to work, the \"stty size\" command must be able to\n"
+"display the screen's current row and column geometry. I STRONGLY\n"
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
+"LINES and COLUMNS exported into your environment. Some distributions\n"
+"export those variables via /etc/profile. Some ncurses programs can\n"
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
+"the true screen size.\n"
+"\n"
+"Optional personality available\n"
+"------------------------------\n"
+"If you prefer to have all of the options listed in a single menu, rather\n"
+"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n"
+"environment variable set to single_menu. Example:\n"
+"\n"
+"make NCONFIG_MODE=single_menu nconfig\n"
+"\n"
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
+"is already unrolled.\n"
+"\n"
+"Note that this mode can eventually be a little more CPU expensive\n"
+"(especially with a larger number of unrolled categories) than the\n"
+"default mode.\n"
+"\n"),
+menu_no_f_instructions[] = N_(
+" You do not have function keys support. Please follow the\n"
+" following instructions:\n"
+" Arrow keys navigate the menu.\n"
+" <Enter> or <right-arrow> selects submenus --->.\n"
+" Capital Letters are hotkeys.\n"
+" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
+" Pressing SpaceBar toggles between the above options.\n"
+" Press <Esc> or <left-arrow> to go back one menu,\n"
+" <?> or <h> for Help, </> for Search.\n"
+" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
+" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
+" <Esc> always leaves the current window.\n"),
+menu_instructions[] = N_(
+" Arrow keys navigate the menu.\n"
+" <Enter> or <right-arrow> selects submenus --->.\n"
+" Capital Letters are hotkeys.\n"
+" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
+" Pressing SpaceBar toggles between the above options\n"
+" Press <Esc>, <F5> or <left-arrow> to go back one menu,\n"
+" <?>, <F1> or <h> for Help, </> for Search.\n"
+" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
+" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
+" <Esc> always leaves the current window\n"),
+radiolist_instructions[] = N_(
+" Use the arrow keys to navigate this window or\n"
+" press the hotkey of the item you wish to select\n"
+" followed by the <SPACE BAR>.\n"
+" Press <?>, <F1> or <h> for additional information about this option.\n"),
+inputbox_instructions_int[] = N_(
+"Please enter a decimal value.\n"
+"Fractions will not be accepted.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+inputbox_instructions_hex[] = N_(
+"Please enter a hexadecimal value.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+inputbox_instructions_string[] = N_(
+"Please enter a string value.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+setmod_text[] = N_(
+"This feature depends on another which\n"
+"has been configured as a module.\n"
+"As a result, this feature will be built as a module."),
+load_config_text[] = N_(
+"Enter the name of the configuration file you wish to load.\n"
+"Accept the name shown to restore the configuration you\n"
+"last retrieved. Leave blank to abort."),
+load_config_help[] = N_(
+"\n"
+"For various reasons, one may wish to keep several different\n"
+"configurations available on a single machine.\n"
+"\n"
+"If you have saved a previous configuration in a file other than the\n"
+"default one, entering its name here will allow you to modify that\n"
+"configuration.\n"
+"\n"
+"If you are uncertain, then you have probably never used alternate\n"
+"configuration files. You should therefor leave this blank to abort.\n"),
+save_config_text[] = N_(
+"Enter a filename to which this configuration should be saved\n"
+"as an alternate. Leave blank to abort."),
+save_config_help[] = N_(
+"\n"
+"For various reasons, one may wish to keep different configurations\n"
+"available on a single machine.\n"
+"\n"
+"Entering a file name here will allow you to later retrieve, modify\n"
+"and use the current configuration as an alternate to whatever\n"
+"configuration options you have selected at that time.\n"
+"\n"
+"If you are uncertain what all this means then you should probably\n"
+"leave this blank.\n"),
+search_help[] = N_(
+"\n"
+"Search for symbols and display their relations. Regular expressions\n"
+"are allowed.\n"
+"Example: search for \"^FOO\"\n"
+"Result:\n"
+"-----------------------------------------------------------------\n"
+"Symbol: FOO [ = m]\n"
+"Prompt: Foo bus is used to drive the bar HW\n"
+"Defined at drivers/pci/Kconfig:47\n"
+"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+"Location:\n"
+" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
+" -> PCI support (PCI [ = y])\n"
+" -> PCI access mode (<choice> [ = y])\n"
+"Selects: LIBCRC32\n"
+"Selected by: BAR\n"
+"-----------------------------------------------------------------\n"
+"o The line 'Prompt:' shows the text used in the menu structure for\n"
+" this symbol\n"
+"o The 'Defined at' line tell at what file / line number the symbol\n"
+" is defined\n"
+"o The 'Depends on:' line tell what symbols needs to be defined for\n"
+" this symbol to be visible in the menu (selectable)\n"
+"o The 'Location:' lines tell where in the menu structure this symbol\n"
+" is located\n"
+" A location followed by a [ = y] indicate that this is a selectable\n"
+" menu item - and current value is displayed inside brackets.\n"
+"o The 'Selects:' line tell what symbol will be automatically\n"
+" selected if this symbol is selected (y or m)\n"
+"o The 'Selected by' line tell what symbol has selected this symbol\n"
+"\n"
+"Only relevant lines are shown.\n"
+"\n\n"
+"Search examples:\n"
+"Examples: USB => find all symbols containing USB\n"
+" ^USB => find all symbols starting with USB\n"
+" USB$ => find all symbols ending with USB\n"
+"\n");
+
+struct mitem {
+ char str[256];
+ char tag;
+ void *usrptr;
+ int is_visible;
+};
+
+#define MAX_MENU_ITEMS 4096
+static int show_all_items;
+static int indent;
+static struct menu *current_menu;
+static int child_count;
+static int single_menu_mode;
+/* the window in which all information appears */
+static WINDOW *main_window;
+/* the largest size of the menu window */
+static int mwin_max_lines;
+static int mwin_max_cols;
+/* the window in which we show option buttons */
+static MENU *curses_menu;
+static ITEM *curses_menu_items[MAX_MENU_ITEMS];
+static struct mitem k_menu_items[MAX_MENU_ITEMS];
+static int items_num;
+static int global_exit;
+/* the currently selected button */
+const char *current_instructions = menu_instructions;
+
+static char *dialog_input_result;
+static int dialog_input_result_len;
+
+static void conf(struct menu *menu);
+static void conf_choice(struct menu *menu);
+static void conf_string(struct menu *menu);
+static void conf_load(void);
+static void conf_save(void);
+static void show_help(struct menu *menu);
+static int do_exit(void);
+static void setup_windows(void);
+static void search_conf(void);
+
+typedef void (*function_key_handler_t)(int *key, struct menu *menu);
+static void handle_f1(int *key, struct menu *current_item);
+static void handle_f2(int *key, struct menu *current_item);
+static void handle_f3(int *key, struct menu *current_item);
+static void handle_f4(int *key, struct menu *current_item);
+static void handle_f5(int *key, struct menu *current_item);
+static void handle_f6(int *key, struct menu *current_item);
+static void handle_f7(int *key, struct menu *current_item);
+static void handle_f8(int *key, struct menu *current_item);
+static void handle_f9(int *key, struct menu *current_item);
+
+struct function_keys {
+ const char *key_str;
+ const char *func;
+ function_key key;
+ function_key_handler_t handler;
+};
+
+static const int function_keys_num = 9;
+struct function_keys function_keys[] = {
+ {
+ .key_str = "F1",
+ .func = "Help",
+ .key = F_HELP,
+ .handler = handle_f1,
+ },
+ {
+ .key_str = "F2",
+ .func = "Sym Info",
+ .key = F_SYMBOL,
+ .handler = handle_f2,
+ },
+ {
+ .key_str = "F3",
+ .func = "Insts",
+ .key = F_INSTS,
+ .handler = handle_f3,
+ },
+ {
+ .key_str = "F4",
+ .func = "Config",
+ .key = F_CONF,
+ .handler = handle_f4,
+ },
+ {
+ .key_str = "F5",
+ .func = "Back",
+ .key = F_BACK,
+ .handler = handle_f5,
+ },
+ {
+ .key_str = "F6",
+ .func = "Save",
+ .key = F_SAVE,
+ .handler = handle_f6,
+ },
+ {
+ .key_str = "F7",
+ .func = "Load",
+ .key = F_LOAD,
+ .handler = handle_f7,
+ },
+ {
+ .key_str = "F8",
+ .func = "Sym Search",
+ .key = F_SEARCH,
+ .handler = handle_f8,
+ },
+ {
+ .key_str = "F9",
+ .func = "Exit",
+ .key = F_EXIT,
+ .handler = handle_f9,
+ },
+};
+
+static void print_function_line(void)
+{
+ int i;
+ int offset = 1;
+ const int skip = 1;
+
+ for (i = 0; i < function_keys_num; i++) {
+ (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
+ mvwprintw(main_window, LINES-3, offset,
+ "%s",
+ function_keys[i].key_str);
+ (void) wattrset(main_window, attributes[FUNCTION_TEXT]);
+ offset += strlen(function_keys[i].key_str);
+ mvwprintw(main_window, LINES-3,
+ offset, "%s",
+ function_keys[i].func);
+ offset += strlen(function_keys[i].func) + skip;
+ }
+ (void) wattrset(main_window, attributes[NORMAL]);
+}
+
+/* help */
+static void handle_f1(int *key, struct menu *current_item)
+{
+ show_scroll_win(main_window,
+ _("README"), _(nconf_readme));
+ return;
+}
+
+/* symbole help */
+static void handle_f2(int *key, struct menu *current_item)
+{
+ show_help(current_item);
+ return;
+}
+
+/* instructions */
+static void handle_f3(int *key, struct menu *current_item)
+{
+ show_scroll_win(main_window,
+ _("Instructions"),
+ _(current_instructions));
+ return;
+}
+
+/* config */
+static void handle_f4(int *key, struct menu *current_item)
+{
+ int res = btn_dialog(main_window,
+ _("Show all symbols?"),
+ 2,
+ " <Show All> ",
+ "<Don't show all>");
+ if (res == 0)
+ show_all_items = 1;
+ else if (res == 1)
+ show_all_items = 0;
+
+ return;
+}
+
+/* back */
+static void handle_f5(int *key, struct menu *current_item)
+{
+ *key = KEY_LEFT;
+ return;
+}
+
+/* save */
+static void handle_f6(int *key, struct menu *current_item)
+{
+ conf_save();
+ return;
+}
+
+/* load */
+static void handle_f7(int *key, struct menu *current_item)
+{
+ conf_load();
+ return;
+}
+
+/* search */
+static void handle_f8(int *key, struct menu *current_item)
+{
+ search_conf();
+ return;
+}
+
+/* exit */
+static void handle_f9(int *key, struct menu *current_item)
+{
+ do_exit();
+ return;
+}
+
+/* return != 0 to indicate the key was handles */
+static int process_special_keys(int *key, struct menu *menu)
+{
+ int i;
+
+ if (*key == KEY_RESIZE) {
+ setup_windows();
+ return 1;
+ }
+
+ for (i = 0; i < function_keys_num; i++) {
+ if (*key == KEY_F(function_keys[i].key) ||
+ *key == '0' + function_keys[i].key){
+ function_keys[i].handler(key, menu);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void clean_items(void)
+{
+ int i;
+ for (i = 0; curses_menu_items[i]; i++)
+ free_item(curses_menu_items[i]);
+ bzero(curses_menu_items, sizeof(curses_menu_items));
+ bzero(k_menu_items, sizeof(k_menu_items));
+ items_num = 0;
+}
+
+typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
+ FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
+
+/* return the index of the matched item, or -1 if no such item exists */
+static int get_mext_match(const char *match_str, match_f flag)
+{
+ int match_start = item_index(current_item(curses_menu));
+ int index;
+
+ if (flag == FIND_NEXT_MATCH_DOWN)
+ ++match_start;
+ else if (flag == FIND_NEXT_MATCH_UP)
+ --match_start;
+
+ index = match_start;
+ index = (index + items_num) % items_num;
+ while (true) {
+ char *str = k_menu_items[index].str;
+ if (strcasestr(str, match_str) != 0)
+ return index;
+ if (flag == FIND_NEXT_MATCH_UP ||
+ flag == MATCH_TINKER_PATTERN_UP)
+ --index;
+ else
+ ++index;
+ index = (index + items_num) % items_num;
+ if (index == match_start)
+ return -1;
+ }
+}
+
+/* Make a new item. */
+static void item_make(struct menu *menu, char tag, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (items_num > MAX_MENU_ITEMS-1)
+ return;
+
+ bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
+ k_menu_items[items_num].tag = tag;
+ k_menu_items[items_num].usrptr = menu;
+ if (menu != NULL)
+ k_menu_items[items_num].is_visible =
+ menu_is_visible(menu);
+ else
+ k_menu_items[items_num].is_visible = 1;
+
+ va_start(ap, fmt);
+ vsnprintf(k_menu_items[items_num].str,
+ sizeof(k_menu_items[items_num].str),
+ fmt, ap);
+ va_end(ap);
+
+ if (!k_menu_items[items_num].is_visible)
+ memcpy(k_menu_items[items_num].str, "XXX", 3);
+
+ curses_menu_items[items_num] = new_item(
+ k_menu_items[items_num].str,
+ k_menu_items[items_num].str);
+ set_item_userptr(curses_menu_items[items_num],
+ &k_menu_items[items_num]);
+ /*
+ if (!k_menu_items[items_num].is_visible)
+ item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
+ */
+
+ items_num++;
+ curses_menu_items[items_num] = NULL;
+}
+
+/* very hackish. adds a string to the last item added */
+static void item_add_str(const char *fmt, ...)
+{
+ va_list ap;
+ int index = items_num-1;
+ char new_str[256];
+ char tmp_str[256];
+
+ if (index < 0)
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(new_str, sizeof(new_str), fmt, ap);
+ va_end(ap);
+ snprintf(tmp_str, sizeof(tmp_str), "%s%s",
+ k_menu_items[index].str, new_str);
+ strncpy(k_menu_items[index].str,
+ tmp_str,
+ sizeof(k_menu_items[index].str));
+
+ free_item(curses_menu_items[index]);
+ curses_menu_items[index] = new_item(
+ k_menu_items[index].str,
+ k_menu_items[index].str);
+ set_item_userptr(curses_menu_items[index],
+ &k_menu_items[index]);
+}
+
+/* get the tag of the currently selected item */
+static char item_tag(void)
+{
+ ITEM *cur;
+ struct mitem *mcur;
+
+ cur = current_item(curses_menu);
+ if (cur == NULL)
+ return 0;
+ mcur = (struct mitem *) item_userptr(cur);
+ return mcur->tag;
+}
+
+static int curses_item_index(void)
+{
+ return item_index(current_item(curses_menu));
+}
+
+static void *item_data(void)
+{
+ ITEM *cur;
+ struct mitem *mcur;
+
+ cur = current_item(curses_menu);
+ if (!cur)
+ return NULL;
+ mcur = (struct mitem *) item_userptr(cur);
+ return mcur->usrptr;
+
+}
+
+static int item_is_tag(char tag)
+{
+ return item_tag() == tag;
+}
+
+static char filename[PATH_MAX+1];
+static char menu_backtitle[PATH_MAX+128];
+static const char *set_config_filename(const char *config_filename)
+{
+ int size;
+
+ size = snprintf(menu_backtitle, sizeof(menu_backtitle),
+ "%s - %s", config_filename, rootmenu.prompt->text);
+ if (size >= sizeof(menu_backtitle))
+ menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
+
+ size = snprintf(filename, sizeof(filename), "%s", config_filename);
+ if (size >= sizeof(filename))
+ filename[sizeof(filename)-1] = '\0';
+ return menu_backtitle;
+}
+
+/* return = 0 means we are successful.
+ * -1 means go on doing what you were doing
+ */
+static int do_exit(void)
+{
+ int res;
+ if (!conf_get_changed()) {
+ global_exit = 1;
+ return 0;
+ }
+ res = btn_dialog(main_window,
+ _("Do you wish to save your new configuration?\n"
+ "<ESC> to cancel and resume nconfig."),
+ 2,
+ " <save> ",
+ "<don't save>");
+ if (res == KEY_EXIT) {
+ global_exit = 0;
+ return -1;
+ }
+
+ /* if we got here, the user really wants to exit */
+ switch (res) {
+ case 0:
+ res = conf_write(filename);
+ if (res)
+ btn_dialog(
+ main_window,
+ _("Error during writing of configuration.\n"
+ "Your configuration changes were NOT saved."),
+ 1,
+ "<OK>");
+ break;
+ default:
+ btn_dialog(
+ main_window,
+ _("Your configuration changes were NOT saved."),
+ 1,
+ "<OK>");
+ break;
+ }
+ global_exit = 1;
+ return 0;
+}
+
+
+static void search_conf(void)
+{
+ struct symbol **sym_arr;
+ struct gstr res;
+ struct gstr title;
+ char *dialog_input;
+ int dres;
+
+ title = str_new();
+ str_printf( &title, _("Enter %s (sub)string to search for "
+ "(with or without \"%s\")"), CONFIG_, CONFIG_);
+
+again:
+ dres = dialog_inputbox(main_window,
+ _("Search Configuration Parameter"),
+ str_get(&title),
+ "", &dialog_input_result, &dialog_input_result_len);
+ switch (dres) {
+ case 0:
+ break;
+ case 1:
+ show_scroll_win(main_window,
+ _("Search Configuration"), search_help);
+ goto again;
+ default:
+ str_free(&title);
+ return;
+ }
+
+ /* strip the prefix if necessary */
+ dialog_input = dialog_input_result;
+ if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
+ dialog_input += strlen(CONFIG_);
+
+ sym_arr = sym_re_search(dialog_input);
+ res = get_relations_str(sym_arr, NULL);
+ free(sym_arr);
+ show_scroll_win(main_window,
+ _("Search Results"), str_get(&res));
+ str_free(&res);
+ str_free(&title);
+}
+
+
+static void build_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+ int type, tmp, doint = 2;
+ tristate val;
+ char ch;
+
+ if (!menu || (!show_all_items && !menu_is_visible(menu)))
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (!sym) {
+ if (prop && menu != current_menu) {
+ const char *prompt = menu_get_prompt(menu);
+ enum prop_type ptype;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ switch (ptype) {
+ case P_MENU:
+ child_count++;
+ prompt = _(prompt);
+ if (single_menu_mode) {
+ item_make(menu, 'm',
+ "%s%*c%s",
+ menu->data ? "-->" : "++>",
+ indent + 1, ' ', prompt);
+ } else
+ item_make(menu, 'm',
+ " %*c%s --->",
+ indent + 1,
+ ' ', prompt);
+
+ if (single_menu_mode && menu->data)
+ goto conf_childs;
+ return;
+ case P_COMMENT:
+ if (prompt) {
+ child_count++;
+ item_make(menu, ':',
+ " %*c*** %s ***",
+ indent + 1, ' ',
+ _(prompt));
+ }
+ break;
+ default:
+ if (prompt) {
+ child_count++;
+ item_make(menu, ':', "---%*c%s",
+ indent + 1, ' ',
+ _(prompt));
+ }
+ }
+ } else
+ doint = 0;
+ goto conf_childs;
+ }
+
+ type = sym_get_type(sym);
+ if (sym_is_choice(sym)) {
+ struct symbol *def_sym = sym_get_choice_value(sym);
+ struct menu *def_menu = NULL;
+
+ child_count++;
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child) && child->sym == def_sym)
+ def_menu = child;
+ }
+
+ val = sym_get_tristate_value(sym);
+ if (sym_is_changable(sym)) {
+ switch (type) {
+ case S_BOOLEAN:
+ item_make(menu, 't', "[%c]",
+ val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes:
+ ch = '*';
+ break;
+ case mod:
+ ch = 'M';
+ break;
+ default:
+ ch = ' ';
+ break;
+ }
+ item_make(menu, 't', "<%c>", ch);
+ break;
+ }
+ } else {
+ item_make(menu, def_menu ? 't' : ':', " ");
+ }
+
+ item_add_str("%*c%s", indent + 1,
+ ' ', _(menu_get_prompt(menu)));
+ if (val == yes) {
+ if (def_menu) {
+ item_add_str(" (%s)",
+ _(menu_get_prompt(def_menu)));
+ item_add_str(" --->");
+ if (def_menu->list) {
+ indent += 2;
+ build_conf(def_menu);
+ indent -= 2;
+ }
+ }
+ return;
+ }
+ } else {
+ if (menu == current_menu) {
+ item_make(menu, ':',
+ "---%*c%s", indent + 1,
+ ' ', _(menu_get_prompt(menu)));
+ goto conf_childs;
+ }
+ child_count++;
+ val = sym_get_tristate_value(sym);
+ if (sym_is_choice_value(sym) && val == yes) {
+ item_make(menu, ':', " ");
+ } else {
+ switch (type) {
+ case S_BOOLEAN:
+ if (sym_is_changable(sym))
+ item_make(menu, 't', "[%c]",
+ val == no ? ' ' : '*');
+ else
+ item_make(menu, 't', "-%c-",
+ val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes:
+ ch = '*';
+ break;
+ case mod:
+ ch = 'M';
+ break;
+ default:
+ ch = ' ';
+ break;
+ }
+ if (sym_is_changable(sym)) {
+ if (sym->rev_dep.tri == mod)
+ item_make(menu,
+ 't', "{%c}", ch);
+ else
+ item_make(menu,
+ 't', "<%c>", ch);
+ } else
+ item_make(menu, 't', "-%c-", ch);
+ break;
+ default:
+ tmp = 2 + strlen(sym_get_string_value(sym));
+ item_make(menu, 's', " (%s)",
+ sym_get_string_value(sym));
+ tmp = indent - tmp + 4;
+ if (tmp < 0)
+ tmp = 0;
+ item_add_str("%*c%s%s", tmp, ' ',
+ _(menu_get_prompt(menu)),
+ (sym_has_value(sym) ||
+ !sym_is_changable(sym)) ? "" :
+ _(" (NEW)"));
+ goto conf_childs;
+ }
+ }
+ item_add_str("%*c%s%s", indent + 1, ' ',
+ _(menu_get_prompt(menu)),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : _(" (NEW)"));
+ if (menu->prompt && menu->prompt->type == P_MENU) {
+ item_add_str(" --->");
+ return;
+ }
+ }
+
+conf_childs:
+ indent += doint;
+ for (child = menu->list; child; child = child->next)
+ build_conf(child);
+ indent -= doint;
+}
+
+static void reset_menu(void)
+{
+ unpost_menu(curses_menu);
+ clean_items();
+}
+
+/* adjust the menu to show this item.
+ * prefer not to scroll the menu if possible*/
+static void center_item(int selected_index, int *last_top_row)
+{
+ int toprow;
+
+ set_top_row(curses_menu, *last_top_row);
+ toprow = top_row(curses_menu);
+ if (selected_index < toprow ||
+ selected_index >= toprow+mwin_max_lines) {
+ toprow = max(selected_index-mwin_max_lines/2, 0);
+ if (toprow >= item_count(curses_menu)-mwin_max_lines)
+ toprow = item_count(curses_menu)-mwin_max_lines;
+ set_top_row(curses_menu, toprow);
+ }
+ set_current_item(curses_menu,
+ curses_menu_items[selected_index]);
+ *last_top_row = toprow;
+ post_menu(curses_menu);
+ refresh_all_windows(main_window);
+}
+
+/* this function assumes reset_menu has been called before */
+static void show_menu(const char *prompt, const char *instructions,
+ int selected_index, int *last_top_row)
+{
+ int maxx, maxy;
+ WINDOW *menu_window;
+
+ current_instructions = instructions;
+
+ clear();
+ (void) wattrset(main_window, attributes[NORMAL]);
+ print_in_middle(stdscr, 1, 0, COLS,
+ menu_backtitle,
+ attributes[MAIN_HEADING]);
+
+ (void) wattrset(main_window, attributes[MAIN_MENU_BOX]);
+ box(main_window, 0, 0);
+ (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]);
+ mvwprintw(main_window, 0, 3, " %s ", prompt);
+ (void) wattrset(main_window, attributes[NORMAL]);
+
+ set_menu_items(curses_menu, curses_menu_items);
+
+ /* position the menu at the middle of the screen */
+ scale_menu(curses_menu, &maxy, &maxx);
+ maxx = min(maxx, mwin_max_cols-2);
+ maxy = mwin_max_lines;
+ menu_window = derwin(main_window,
+ maxy,
+ maxx,
+ 2,
+ (mwin_max_cols-maxx)/2);
+ keypad(menu_window, TRUE);
+ set_menu_win(curses_menu, menu_window);
+ set_menu_sub(curses_menu, menu_window);
+
+ /* must reassert this after changing items, otherwise returns to a
+ * default of 16
+ */
+ set_menu_format(curses_menu, maxy, 1);
+ center_item(selected_index, last_top_row);
+ set_menu_format(curses_menu, maxy, 1);
+
+ print_function_line();
+
+ /* Post the menu */
+ post_menu(curses_menu);
+ refresh_all_windows(main_window);
+}
+
+static void adj_match_dir(match_f *match_direction)
+{
+ if (*match_direction == FIND_NEXT_MATCH_DOWN)
+ *match_direction =
+ MATCH_TINKER_PATTERN_DOWN;
+ else if (*match_direction == FIND_NEXT_MATCH_UP)
+ *match_direction =
+ MATCH_TINKER_PATTERN_UP;
+ /* else, do no change.. */
+}
+
+struct match_state
+{
+ int in_search;
+ match_f match_direction;
+ char pattern[256];
+};
+
+/* Return 0 means I have handled the key. In such a case, ans should hold the
+ * item to center, or -1 otherwise.
+ * Else return -1 .
+ */
+static int do_match(int key, struct match_state *state, int *ans)
+{
+ char c = (char) key;
+ int terminate_search = 0;
+ *ans = -1;
+ if (key == '/' || (state->in_search && key == 27)) {
+ move(0, 0);
+ refresh();
+ clrtoeol();
+ state->in_search = 1-state->in_search;
+ bzero(state->pattern, sizeof(state->pattern));
+ state->match_direction = MATCH_TINKER_PATTERN_DOWN;
+ return 0;
+ } else if (!state->in_search)
+ return 1;
+
+ if (isalnum(c) || isgraph(c) || c == ' ') {
+ state->pattern[strlen(state->pattern)] = c;
+ state->pattern[strlen(state->pattern)] = '\0';
+ adj_match_dir(&state->match_direction);
+ *ans = get_mext_match(state->pattern,
+ state->match_direction);
+ } else if (key == KEY_DOWN) {
+ state->match_direction = FIND_NEXT_MATCH_DOWN;
+ *ans = get_mext_match(state->pattern,
+ state->match_direction);
+ } else if (key == KEY_UP) {
+ state->match_direction = FIND_NEXT_MATCH_UP;
+ *ans = get_mext_match(state->pattern,
+ state->match_direction);
+ } else if (key == KEY_BACKSPACE || key == 127) {
+ state->pattern[strlen(state->pattern)-1] = '\0';
+ adj_match_dir(&state->match_direction);
+ } else
+ terminate_search = 1;
+
+ if (terminate_search) {
+ state->in_search = 0;
+ bzero(state->pattern, sizeof(state->pattern));
+ move(0, 0);
+ refresh();
+ clrtoeol();
+ return -1;
+ }
+ return 0;
+}
+
+static void conf(struct menu *menu)
+{
+ struct menu *submenu = 0;
+ const char *prompt = menu_get_prompt(menu);
+ struct symbol *sym;
+ int res;
+ int current_index = 0;
+ int last_top_row = 0;
+ struct match_state match_state = {
+ .in_search = 0,
+ .match_direction = MATCH_TINKER_PATTERN_DOWN,
+ .pattern = "",
+ };
+
+ while (!global_exit) {
+ reset_menu();
+ current_menu = menu;
+ build_conf(menu);
+ if (!child_count)
+ break;
+
+ show_menu(prompt ? _(prompt) : _("Main Menu"),
+ _(menu_instructions),
+ current_index, &last_top_row);
+ keypad((menu_win(curses_menu)), TRUE);
+ while (!global_exit) {
+ if (match_state.in_search) {
+ mvprintw(0, 0,
+ "searching: %s", match_state.pattern);
+ clrtoeol();
+ }
+ refresh_all_windows(main_window);
+ res = wgetch(menu_win(curses_menu));
+ if (!res)
+ break;
+ if (do_match(res, &match_state, ¤t_index) == 0) {
+ if (current_index != -1)
+ center_item(current_index,
+ &last_top_row);
+ continue;
+ }
+ if (process_special_keys(&res,
+ (struct menu *) item_data()))
+ break;
+ switch (res) {
+ case KEY_DOWN:
+ menu_driver(curses_menu, REQ_DOWN_ITEM);
+ break;
+ case KEY_UP:
+ menu_driver(curses_menu, REQ_UP_ITEM);
+ break;
+ case KEY_NPAGE:
+ menu_driver(curses_menu, REQ_SCR_DPAGE);
+ break;
+ case KEY_PPAGE:
+ menu_driver(curses_menu, REQ_SCR_UPAGE);
+ break;
+ case KEY_HOME:
+ menu_driver(curses_menu, REQ_FIRST_ITEM);
+ break;
+ case KEY_END:
+ menu_driver(curses_menu, REQ_LAST_ITEM);
+ break;
+ case 'h':
+ case '?':
+ show_help((struct menu *) item_data());
+ break;
+ }
+ if (res == 10 || res == 27 ||
+ res == 32 || res == 'n' || res == 'y' ||
+ res == KEY_LEFT || res == KEY_RIGHT ||
+ res == 'm')
+ break;
+ refresh_all_windows(main_window);
+ }
+
+ refresh_all_windows(main_window);
+ /* if ESC or left*/
+ if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
+ break;
+
+ /* remember location in the menu */
+ last_top_row = top_row(curses_menu);
+ current_index = curses_item_index();
+
+ if (!item_tag())
+ continue;
+
+ submenu = (struct menu *) item_data();
+ if (!submenu || !menu_is_visible(submenu))
+ continue;
+ sym = submenu->sym;
+
+ switch (res) {
+ case ' ':
+ if (item_is_tag('t'))
+ sym_toggle_tristate_value(sym);
+ else if (item_is_tag('m'))
+ conf(submenu);
+ break;
+ case KEY_RIGHT:
+ case 10: /* ENTER WAS PRESSED */
+ switch (item_tag()) {
+ case 'm':
+ if (single_menu_mode)
+ submenu->data =
+ (void *) (long) !submenu->data;
+ else
+ conf(submenu);
+ break;
+ case 't':
+ if (sym_is_choice(sym) &&
+ sym_get_tristate_value(sym) == yes)
+ conf_choice(submenu);
+ else if (submenu->prompt &&
+ submenu->prompt->type == P_MENU)
+ conf(submenu);
+ else if (res == 10)
+ sym_toggle_tristate_value(sym);
+ break;
+ case 's':
+ conf_string(submenu);
+ break;
+ }
+ break;
+ case 'y':
+ if (item_is_tag('t')) {
+ if (sym_set_tristate_value(sym, yes))
+ break;
+ if (sym_set_tristate_value(sym, mod))
+ btn_dialog(main_window, setmod_text, 0);
+ }
+ break;
+ case 'n':
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, no);
+ break;
+ case 'm':
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, mod);
+ break;
+ }
+ }
+}
+
+static void conf_message_callback(const char *fmt, va_list ap)
+{
+ char buf[1024];
+
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ btn_dialog(main_window, buf, 1, "<OK>");
+}
+
+static void show_help(struct menu *menu)
+{
+ struct gstr help;
+
+ if (!menu)
+ return;
+
+ help = str_new();
+ menu_get_ext_help(menu, &help);
+ show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
+ str_free(&help);
+}
+
+static void conf_choice(struct menu *menu)
+{
+ const char *prompt = _(menu_get_prompt(menu));
+ struct menu *child = 0;
+ struct symbol *active;
+ int selected_index = 0;
+ int last_top_row = 0;
+ int res, i = 0;
+ struct match_state match_state = {
+ .in_search = 0,
+ .match_direction = MATCH_TINKER_PATTERN_DOWN,
+ .pattern = "",
+ };
+
+ active = sym_get_choice_value(menu->sym);
+ /* this is mostly duplicated from the conf() function. */
+ while (!global_exit) {
+ reset_menu();
+
+ for (i = 0, child = menu->list; child; child = child->next) {
+ if (!show_all_items && !menu_is_visible(child))
+ continue;
+
+ if (child->sym == sym_get_choice_value(menu->sym))
+ item_make(child, ':', "<X> %s",
+ _(menu_get_prompt(child)));
+ else if (child->sym)
+ item_make(child, ':', " %s",
+ _(menu_get_prompt(child)));
+ else
+ item_make(child, ':', "*** %s ***",
+ _(menu_get_prompt(child)));
+
+ if (child->sym == active){
+ last_top_row = top_row(curses_menu);
+ selected_index = i;
+ }
+ i++;
+ }
+ show_menu(prompt ? _(prompt) : _("Choice Menu"),
+ _(radiolist_instructions),
+ selected_index,
+ &last_top_row);
+ while (!global_exit) {
+ if (match_state.in_search) {
+ mvprintw(0, 0, "searching: %s",
+ match_state.pattern);
+ clrtoeol();
+ }
+ refresh_all_windows(main_window);
+ res = wgetch(menu_win(curses_menu));
+ if (!res)
+ break;
+ if (do_match(res, &match_state, &selected_index) == 0) {
+ if (selected_index != -1)
+ center_item(selected_index,
+ &last_top_row);
+ continue;
+ }
+ if (process_special_keys(
+ &res,
+ (struct menu *) item_data()))
+ break;
+ switch (res) {
+ case KEY_DOWN:
+ menu_driver(curses_menu, REQ_DOWN_ITEM);
+ break;
+ case KEY_UP:
+ menu_driver(curses_menu, REQ_UP_ITEM);
+ break;
+ case KEY_NPAGE:
+ menu_driver(curses_menu, REQ_SCR_DPAGE);
+ break;
+ case KEY_PPAGE:
+ menu_driver(curses_menu, REQ_SCR_UPAGE);
+ break;
+ case KEY_HOME:
+ menu_driver(curses_menu, REQ_FIRST_ITEM);
+ break;
+ case KEY_END:
+ menu_driver(curses_menu, REQ_LAST_ITEM);
+ break;
+ case 'h':
+ case '?':
+ show_help((struct menu *) item_data());
+ break;
+ }
+ if (res == 10 || res == 27 || res == ' ' ||
+ res == KEY_LEFT){
+ break;
+ }
+ refresh_all_windows(main_window);
+ }
+ /* if ESC or left */
+ if (res == 27 || res == KEY_LEFT)
+ break;
+
+ child = item_data();
+ if (!child || !menu_is_visible(child) || !child->sym)
+ continue;
+ switch (res) {
+ case ' ':
+ case 10:
+ case KEY_RIGHT:
+ sym_set_tristate_value(child->sym, yes);
+ return;
+ case 'h':
+ case '?':
+ show_help(child);
+ active = child->sym;
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+static void conf_string(struct menu *menu)
+{
+ const char *prompt = menu_get_prompt(menu);
+
+ while (1) {
+ int res;
+ const char *heading;
+
+ switch (sym_get_type(menu->sym)) {
+ case S_INT:
+ heading = _(inputbox_instructions_int);
+ break;
+ case S_HEX:
+ heading = _(inputbox_instructions_hex);
+ break;
+ case S_STRING:
+ heading = _(inputbox_instructions_string);
+ break;
+ default:
+ heading = _("Internal nconf error!");
+ }
+ res = dialog_inputbox(main_window,
+ prompt ? _(prompt) : _("Main Menu"),
+ heading,
+ sym_get_string_value(menu->sym),
+ &dialog_input_result,
+ &dialog_input_result_len);
+ switch (res) {
+ case 0:
+ if (sym_set_string_value(menu->sym,
+ dialog_input_result))
+ return;
+ btn_dialog(main_window,
+ _("You have made an invalid entry."), 0);
+ break;
+ case 1:
+ show_help(menu);
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+static void conf_load(void)
+{
+ while (1) {
+ int res;
+ res = dialog_inputbox(main_window,
+ NULL, load_config_text,
+ filename,
+ &dialog_input_result,
+ &dialog_input_result_len);
+ switch (res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ if (!conf_read(dialog_input_result)) {
+ set_config_filename(dialog_input_result);
+ sym_set_change_count(1);
+ return;
+ }
+ btn_dialog(main_window, _("File does not exist!"), 0);
+ break;
+ case 1:
+ show_scroll_win(main_window,
+ _("Load Alternate Configuration"),
+ load_config_help);
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+static void conf_save(void)
+{
+ while (1) {
+ int res;
+ res = dialog_inputbox(main_window,
+ NULL, save_config_text,
+ filename,
+ &dialog_input_result,
+ &dialog_input_result_len);
+ switch (res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ res = conf_write(dialog_input_result);
+ if (!res) {
+ set_config_filename(dialog_input_result);
+ return;
+ }
+ btn_dialog(main_window, _("Can't create file! "
+ "Probably a nonexistent directory."),
+ 1, "<OK>");
+ break;
+ case 1:
+ show_scroll_win(main_window,
+ _("Save Alternate Configuration"),
+ save_config_help);
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+void setup_windows(void)
+{
+ if (main_window != NULL)
+ delwin(main_window);
+
+ /* set up the menu and menu window */
+ main_window = newwin(LINES-2, COLS-2, 2, 1);
+ keypad(main_window, TRUE);
+ mwin_max_lines = LINES-7;
+ mwin_max_cols = COLS-6;
+
+ /* panels order is from bottom to top */
+ new_panel(main_window);
+}
+
+int main(int ac, char **av)
+{
+ char *mode;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ conf_parse(av[1]);
+ conf_read(NULL);
+
+ mode = getenv("NCONFIG_MODE");
+ if (mode) {
+ if (!strcasecmp(mode, "single_menu"))
+ single_menu_mode = 1;
+ }
+
+ /* Initialize curses */
+ initscr();
+ /* set color theme */
+ set_colors();
+
+ cbreak();
+ noecho();
+ keypad(stdscr, TRUE);
+ curs_set(0);
+
+ if (COLS < 75 || LINES < 20) {
+ endwin();
+ printf("Your terminal should have at "
+ "least 20 lines and 75 columns\n");
+ return 1;
+ }
+
+ notimeout(stdscr, FALSE);
+#if NCURSES_REENTRANT
+ set_escdelay(1);
+#else
+ ESCDELAY = 1;
+#endif
+
+ /* set btns menu */
+ curses_menu = new_menu(curses_menu_items);
+ menu_opts_off(curses_menu, O_SHOWDESC);
+ menu_opts_on(curses_menu, O_SHOWMATCH);
+ menu_opts_on(curses_menu, O_ONEVALUE);
+ menu_opts_on(curses_menu, O_NONCYCLIC);
+ menu_opts_on(curses_menu, O_IGNORECASE);
+ set_menu_mark(curses_menu, " ");
+ set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
+ set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
+ set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);
+
+ set_config_filename(conf_get_configname());
+ setup_windows();
+
+ /* check for KEY_FUNC(1) */
+ if (has_key(KEY_F(1)) == FALSE) {
+ show_scroll_win(main_window,
+ _("Instructions"),
+ _(menu_no_f_instructions));
+ }
+
+ conf_set_message_callback(conf_message_callback);
+ /* do the work */
+ while (!global_exit) {
+ conf(&rootmenu);
+ if (!global_exit && do_exit() == 0)
+ break;
+ }
+ /* ok, we are done */
+ unpost_menu(curses_menu);
+ free_menu(curses_menu);
+ delwin(main_window);
+ clear();
+ refresh();
+ endwin();
+ return 0;
+}
+
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
new file mode 100644
index 0000000..9f8c44e
--- /dev/null
+++ b/scripts/kconfig/nconf.gui.c
@@ -0,0 +1,654 @@
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar at gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+#include "nconf.h"
+
+/* a list of all the different widgets we use */
+attributes_t attributes[ATTR_MAX+1] = {0};
+
+/* available colors:
+ COLOR_BLACK 0
+ COLOR_RED 1
+ COLOR_GREEN 2
+ COLOR_YELLOW 3
+ COLOR_BLUE 4
+ COLOR_MAGENTA 5
+ COLOR_CYAN 6
+ COLOR_WHITE 7
+ */
+static void set_normal_colors(void)
+{
+ init_pair(NORMAL, -1, -1);
+ init_pair(MAIN_HEADING, COLOR_MAGENTA, -1);
+
+ /* FORE is for the selected item */
+ init_pair(MAIN_MENU_FORE, -1, -1);
+ /* BACK for all the rest */
+ init_pair(MAIN_MENU_BACK, -1, -1);
+ init_pair(MAIN_MENU_GREY, -1, -1);
+ init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);
+ init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);
+
+ init_pair(SCROLLWIN_TEXT, -1, -1);
+ init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);
+ init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);
+
+ init_pair(DIALOG_TEXT, -1, -1);
+ init_pair(DIALOG_BOX, COLOR_YELLOW, -1);
+ init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);
+ init_pair(DIALOG_MENU_FORE, COLOR_RED, -1);
+
+ init_pair(INPUT_BOX, COLOR_YELLOW, -1);
+ init_pair(INPUT_HEADING, COLOR_GREEN, -1);
+ init_pair(INPUT_TEXT, -1, -1);
+ init_pair(INPUT_FIELD, -1, -1);
+
+ init_pair(FUNCTION_HIGHLIGHT, -1, -1);
+ init_pair(FUNCTION_TEXT, COLOR_YELLOW, -1);
+}
+
+/* available attributes:
+ A_NORMAL Normal display (no highlight)
+ A_STANDOUT Best highlighting mode of the terminal.
+ A_UNDERLINE Underlining
+ A_REVERSE Reverse video
+ A_BLINK Blinking
+ A_DIM Half bright
+ A_BOLD Extra bright or bold
+ A_PROTECT Protected mode
+ A_INVIS Invisible or blank mode
+ A_ALTCHARSET Alternate character set
+ A_CHARTEXT Bit-mask to extract a character
+ COLOR_PAIR(n) Color-pair number n
+ */
+static void normal_color_theme(void)
+{
+ /* automatically add color... */
+#define mkattr(name, attr) do { \
+attributes[name] = attr | COLOR_PAIR(name); } while (0)
+ mkattr(NORMAL, NORMAL);
+ mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);
+
+ mkattr(MAIN_MENU_FORE, A_REVERSE);
+ mkattr(MAIN_MENU_BACK, A_NORMAL);
+ mkattr(MAIN_MENU_GREY, A_NORMAL);
+ mkattr(MAIN_MENU_HEADING, A_BOLD);
+ mkattr(MAIN_MENU_BOX, A_NORMAL);
+
+ mkattr(SCROLLWIN_TEXT, A_NORMAL);
+ mkattr(SCROLLWIN_HEADING, A_BOLD);
+ mkattr(SCROLLWIN_BOX, A_BOLD);
+
+ mkattr(DIALOG_TEXT, A_BOLD);
+ mkattr(DIALOG_BOX, A_BOLD);
+ mkattr(DIALOG_MENU_FORE, A_STANDOUT);
+ mkattr(DIALOG_MENU_BACK, A_NORMAL);
+
+ mkattr(INPUT_BOX, A_NORMAL);
+ mkattr(INPUT_HEADING, A_BOLD);
+ mkattr(INPUT_TEXT, A_NORMAL);
+ mkattr(INPUT_FIELD, A_UNDERLINE);
+
+ mkattr(FUNCTION_HIGHLIGHT, A_BOLD);
+ mkattr(FUNCTION_TEXT, A_REVERSE);
+}
+
+static void no_colors_theme(void)
+{
+ /* automatically add highlight, no color */
+#define mkattrn(name, attr) { attributes[name] = attr; }
+
+ mkattrn(NORMAL, NORMAL);
+ mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);
+
+ mkattrn(MAIN_MENU_FORE, A_STANDOUT);
+ mkattrn(MAIN_MENU_BACK, A_NORMAL);
+ mkattrn(MAIN_MENU_GREY, A_NORMAL);
+ mkattrn(MAIN_MENU_HEADING, A_BOLD);
+ mkattrn(MAIN_MENU_BOX, A_NORMAL);
+
+ mkattrn(SCROLLWIN_TEXT, A_NORMAL);
+ mkattrn(SCROLLWIN_HEADING, A_BOLD);
+ mkattrn(SCROLLWIN_BOX, A_BOLD);
+
+ mkattrn(DIALOG_TEXT, A_NORMAL);
+ mkattrn(DIALOG_BOX, A_BOLD);
+ mkattrn(DIALOG_MENU_FORE, A_STANDOUT);
+ mkattrn(DIALOG_MENU_BACK, A_NORMAL);
+
+ mkattrn(INPUT_BOX, A_BOLD);
+ mkattrn(INPUT_HEADING, A_BOLD);
+ mkattrn(INPUT_TEXT, A_NORMAL);
+ mkattrn(INPUT_FIELD, A_UNDERLINE);
+
+ mkattrn(FUNCTION_HIGHLIGHT, A_BOLD);
+ mkattrn(FUNCTION_TEXT, A_REVERSE);
+}
+
+void set_colors()
+{
+ start_color();
+ use_default_colors();
+ set_normal_colors();
+ if (has_colors()) {
+ normal_color_theme();
+ } else {
+ /* give defaults */
+ no_colors_theme();
+ }
+}
+
+
+/* this changes the windows attributes !!! */
+void print_in_middle(WINDOW *win,
+ int starty,
+ int startx,
+ int width,
+ const char *string,
+ chtype color)
+{ int length, x, y;
+ float temp;
+
+
+ if (win == NULL)
+ win = stdscr;
+ getyx(win, y, x);
+ if (startx != 0)
+ x = startx;
+ if (starty != 0)
+ y = starty;
+ if (width == 0)
+ width = 80;
+
+ length = strlen(string);
+ temp = (width - length) / 2;
+ x = startx + (int)temp;
+ (void) wattrset(win, color);
+ mvwprintw(win, y, x, "%s", string);
+ refresh();
+}
+
+int get_line_no(const char *text)
+{
+ int i;
+ int total = 1;
+
+ if (!text)
+ return 0;
+
+ for (i = 0; text[i] != '\0'; i++)
+ if (text[i] == '\n')
+ total++;
+ return total;
+}
+
+const char *get_line(const char *text, int line_no)
+{
+ int i;
+ int lines = 0;
+
+ if (!text)
+ return 0;
+
+ for (i = 0; text[i] != '\0' && lines < line_no; i++)
+ if (text[i] == '\n')
+ lines++;
+ return text+i;
+}
+
+int get_line_length(const char *line)
+{
+ int res = 0;
+ while (*line != '\0' && *line != '\n') {
+ line++;
+ res++;
+ }
+ return res;
+}
+
+/* print all lines to the window. */
+void fill_window(WINDOW *win, const char *text)
+{
+ int x, y;
+ int total_lines = get_line_no(text);
+ int i;
+
+ getmaxyx(win, y, x);
+ /* do not go over end of line */
+ total_lines = min(total_lines, y);
+ for (i = 0; i < total_lines; i++) {
+ char tmp[x+10];
+ const char *line = get_line(text, i);
+ int len = get_line_length(line);
+ strncpy(tmp, line, min(len, x));
+ tmp[len] = '\0';
+ mvwprintw(win, i, 0, "%s", tmp);
+ }
+}
+
+/* get the message, and buttons.
+ * each button must be a char*
+ * return the selected button
+ *
+ * this dialog is used for 2 different things:
+ * 1) show a text box, no buttons.
+ * 2) show a dialog, with horizontal buttons
+ */
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
+{
+ va_list ap;
+ char *btn;
+ int btns_width = 0;
+ int msg_lines = 0;
+ int msg_width = 0;
+ int total_width;
+ int win_rows = 0;
+ WINDOW *win;
+ WINDOW *msg_win;
+ WINDOW *menu_win;
+ MENU *menu;
+ ITEM *btns[btn_num+1];
+ int i, x, y;
+ int res = -1;
+
+
+ va_start(ap, btn_num);
+ for (i = 0; i < btn_num; i++) {
+ btn = va_arg(ap, char *);
+ btns[i] = new_item(btn, "");
+ btns_width += strlen(btn)+1;
+ }
+ va_end(ap);
+ btns[btn_num] = NULL;
+
+ /* find the widest line of msg: */
+ msg_lines = get_line_no(msg);
+ for (i = 0; i < msg_lines; i++) {
+ const char *line = get_line(msg, i);
+ int len = get_line_length(line);
+ if (msg_width < len)
+ msg_width = len;
+ }
+
+ total_width = max(msg_width, btns_width);
+ /* place dialog in middle of screen */
+ y = (LINES-(msg_lines+4))/2;
+ x = (COLS-(total_width+4))/2;
+
+
+ /* create the windows */
+ if (btn_num > 0)
+ win_rows = msg_lines+4;
+ else
+ win_rows = msg_lines+2;
+
+ win = newwin(win_rows, total_width+4, y, x);
+ keypad(win, TRUE);
+ menu_win = derwin(win, 1, btns_width, win_rows-2,
+ 1+(total_width+2-btns_width)/2);
+ menu = new_menu(btns);
+ msg_win = derwin(win, win_rows-2, msg_width, 1,
+ 1+(total_width+2-msg_width)/2);
+
+ set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
+ set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
+
+ (void) wattrset(win, attributes[DIALOG_BOX]);
+ box(win, 0, 0);
+
+ /* print message */
+ (void) wattrset(msg_win, attributes[DIALOG_TEXT]);
+ fill_window(msg_win, msg);
+
+ set_menu_win(menu, win);
+ set_menu_sub(menu, menu_win);
+ set_menu_format(menu, 1, btn_num);
+ menu_opts_off(menu, O_SHOWDESC);
+ menu_opts_off(menu, O_SHOWMATCH);
+ menu_opts_on(menu, O_ONEVALUE);
+ menu_opts_on(menu, O_NONCYCLIC);
+ set_menu_mark(menu, "");
+ post_menu(menu);
+
+
+ touchwin(win);
+ refresh_all_windows(main_window);
+ while ((res = wgetch(win))) {
+ switch (res) {
+ case KEY_LEFT:
+ menu_driver(menu, REQ_LEFT_ITEM);
+ break;
+ case KEY_RIGHT:
+ menu_driver(menu, REQ_RIGHT_ITEM);
+ break;
+ case 10: /* ENTER */
+ case 27: /* ESCAPE */
+ case ' ':
+ case KEY_F(F_BACK):
+ case KEY_F(F_EXIT):
+ break;
+ }
+ touchwin(win);
+ refresh_all_windows(main_window);
+
+ if (res == 10 || res == ' ') {
+ res = item_index(current_item(menu));
+ break;
+ } else if (res == 27 || res == KEY_F(F_BACK) ||
+ res == KEY_F(F_EXIT)) {
+ res = KEY_EXIT;
+ break;
+ }
+ }
+
+ unpost_menu(menu);
+ free_menu(menu);
+ for (i = 0; i < btn_num; i++)
+ free_item(btns[i]);
+
+ delwin(win);
+ return res;
+}
+
+int dialog_inputbox(WINDOW *main_window,
+ const char *title, const char *prompt,
+ const char *init, char **resultp, int *result_len)
+{
+ int prompt_lines = 0;
+ int prompt_width = 0;
+ WINDOW *win;
+ WINDOW *prompt_win;
+ WINDOW *form_win;
+ PANEL *panel;
+ int i, x, y;
+ int res = -1;
+ int cursor_position = strlen(init);
+ int cursor_form_win;
+ char *result = *resultp;
+
+ if (strlen(init)+1 > *result_len) {
+ *result_len = strlen(init)+1;
+ *resultp = result = realloc(result, *result_len);
+ }
+
+ /* find the widest line of msg: */
+ prompt_lines = get_line_no(prompt);
+ for (i = 0; i < prompt_lines; i++) {
+ const char *line = get_line(prompt, i);
+ int len = get_line_length(line);
+ prompt_width = max(prompt_width, len);
+ }
+
+ if (title)
+ prompt_width = max(prompt_width, strlen(title));
+
+ /* place dialog in middle of screen */
+ y = (LINES-(prompt_lines+4))/2;
+ x = (COLS-(prompt_width+4))/2;
+
+ strncpy(result, init, *result_len);
+
+ /* create the windows */
+ win = newwin(prompt_lines+6, prompt_width+7, y, x);
+ prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
+ form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
+ keypad(form_win, TRUE);
+
+ (void) wattrset(form_win, attributes[INPUT_FIELD]);
+
+ (void) wattrset(win, attributes[INPUT_BOX]);
+ box(win, 0, 0);
+ (void) wattrset(win, attributes[INPUT_HEADING]);
+ if (title)
+ mvwprintw(win, 0, 3, "%s", title);
+
+ /* print message */
+ (void) wattrset(prompt_win, attributes[INPUT_TEXT]);
+ fill_window(prompt_win, prompt);
+
+ mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
+ cursor_form_win = min(cursor_position, prompt_width-1);
+ mvwprintw(form_win, 0, 0, "%s",
+ result + cursor_position-cursor_form_win);
+
+ /* create panels */
+ panel = new_panel(win);
+
+ /* show the cursor */
+ curs_set(1);
+
+ touchwin(win);
+ refresh_all_windows(main_window);
+ while ((res = wgetch(form_win))) {
+ int len = strlen(result);
+ switch (res) {
+ case 10: /* ENTER */
+ case 27: /* ESCAPE */
+ case KEY_F(F_HELP):
+ case KEY_F(F_EXIT):
+ case KEY_F(F_BACK):
+ break;
+ case 127:
+ case KEY_BACKSPACE:
+ if (cursor_position > 0) {
+ memmove(&result[cursor_position-1],
+ &result[cursor_position],
+ len-cursor_position+1);
+ cursor_position--;
+ cursor_form_win--;
+ len--;
+ }
+ break;
+ case KEY_DC:
+ if (cursor_position >= 0 && cursor_position < len) {
+ memmove(&result[cursor_position],
+ &result[cursor_position+1],
+ len-cursor_position+1);
+ len--;
+ }
+ break;
+ case KEY_UP:
+ case KEY_RIGHT:
+ if (cursor_position < len) {
+ cursor_position++;
+ cursor_form_win++;
+ }
+ break;
+ case KEY_DOWN:
+ case KEY_LEFT:
+ if (cursor_position > 0) {
+ cursor_position--;
+ cursor_form_win--;
+ }
+ break;
+ case KEY_HOME:
+ cursor_position = 0;
+ cursor_form_win = 0;
+ break;
+ case KEY_END:
+ cursor_position = len;
+ cursor_form_win = min(cursor_position, prompt_width-1);
+ break;
+ default:
+ if ((isgraph(res) || isspace(res))) {
+ /* one for new char, one for '\0' */
+ if (len+2 > *result_len) {
+ *result_len = len+2;
+ *resultp = result = realloc(result,
+ *result_len);
+ }
+ /* insert the char at the proper position */
+ memmove(&result[cursor_position+1],
+ &result[cursor_position],
+ len-cursor_position+1);
+ result[cursor_position] = res;
+ cursor_position++;
+ cursor_form_win++;
+ len++;
+ } else {
+ mvprintw(0, 0, "unknown key: %d\n", res);
+ }
+ break;
+ }
+ if (cursor_form_win < 0)
+ cursor_form_win = 0;
+ else if (cursor_form_win > prompt_width-1)
+ cursor_form_win = prompt_width-1;
+
+ wmove(form_win, 0, 0);
+ wclrtoeol(form_win);
+ mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
+ mvwprintw(form_win, 0, 0, "%s",
+ result + cursor_position-cursor_form_win);
+ wmove(form_win, 0, cursor_form_win);
+ touchwin(win);
+ refresh_all_windows(main_window);
+
+ if (res == 10) {
+ res = 0;
+ break;
+ } else if (res == 27 || res == KEY_F(F_BACK) ||
+ res == KEY_F(F_EXIT)) {
+ res = KEY_EXIT;
+ break;
+ } else if (res == KEY_F(F_HELP)) {
+ res = 1;
+ break;
+ }
+ }
+
+ /* hide the cursor */
+ curs_set(0);
+ del_panel(panel);
+ delwin(prompt_win);
+ delwin(form_win);
+ delwin(win);
+ return res;
+}
+
+/* refresh all windows in the correct order */
+void refresh_all_windows(WINDOW *main_window)
+{
+ update_panels();
+ touchwin(main_window);
+ refresh();
+}
+
+/* layman's scrollable window... */
+void show_scroll_win(WINDOW *main_window,
+ const char *title,
+ const char *text)
+{
+ int res;
+ int total_lines = get_line_no(text);
+ int x, y;
+ int start_x = 0, start_y = 0;
+ int text_lines = 0, text_cols = 0;
+ int total_cols = 0;
+ int win_cols = 0;
+ int win_lines = 0;
+ int i = 0;
+ WINDOW *win;
+ WINDOW *pad;
+ PANEL *panel;
+
+ /* find the widest line of msg: */
+ total_lines = get_line_no(text);
+ for (i = 0; i < total_lines; i++) {
+ const char *line = get_line(text, i);
+ int len = get_line_length(line);
+ total_cols = max(total_cols, len+2);
+ }
+
+ /* create the pad */
+ pad = newpad(total_lines+10, total_cols+10);
+ (void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
+ fill_window(pad, text);
+
+ win_lines = min(total_lines+4, LINES-2);
+ win_cols = min(total_cols+2, COLS-2);
+ text_lines = max(win_lines-4, 0);
+ text_cols = max(win_cols-2, 0);
+
+ /* place window in middle of screen */
+ y = (LINES-win_lines)/2;
+ x = (COLS-win_cols)/2;
+
+ win = newwin(win_lines, win_cols, y, x);
+ keypad(win, TRUE);
+ /* show the help in the help window, and show the help panel */
+ (void) wattrset(win, attributes[SCROLLWIN_BOX]);
+ box(win, 0, 0);
+ (void) wattrset(win, attributes[SCROLLWIN_HEADING]);
+ mvwprintw(win, 0, 3, " %s ", title);
+ panel = new_panel(win);
+
+ /* handle scrolling */
+ do {
+
+ copywin(pad, win, start_y, start_x, 2, 2, text_lines,
+ text_cols, 0);
+ print_in_middle(win,
+ text_lines+2,
+ 0,
+ text_cols,
+ "<OK>",
+ attributes[DIALOG_MENU_FORE]);
+ wrefresh(win);
+
+ res = wgetch(win);
+ switch (res) {
+ case KEY_NPAGE:
+ case ' ':
+ case 'd':
+ start_y += text_lines-2;
+ break;
+ case KEY_PPAGE:
+ case 'u':
+ start_y -= text_lines+2;
+ break;
+ case KEY_HOME:
+ start_y = 0;
+ break;
+ case KEY_END:
+ start_y = total_lines-text_lines;
+ break;
+ case KEY_DOWN:
+ case 'j':
+ start_y++;
+ break;
+ case KEY_UP:
+ case 'k':
+ start_y--;
+ break;
+ case KEY_LEFT:
+ case 'h':
+ start_x--;
+ break;
+ case KEY_RIGHT:
+ case 'l':
+ start_x++;
+ break;
+ }
+ if (res == 10 || res == 27 || res == 'q' ||
+ res == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||
+ res == KEY_F(F_EXIT))
+ break;
+ if (start_y < 0)
+ start_y = 0;
+ if (start_y >= total_lines-text_lines)
+ start_y = total_lines-text_lines;
+ if (start_x < 0)
+ start_x = 0;
+ if (start_x >= total_cols-text_cols)
+ start_x = total_cols-text_cols;
+ } while (res);
+
+ del_panel(panel);
+ delwin(win);
+ refresh_all_windows(main_window);
+}
diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h
new file mode 100644
index 0000000..0d52617
--- /dev/null
+++ b/scripts/kconfig/nconf.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar at gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <locale.h>
+#include <curses.h>
+#include <menu.h>
+#include <panel.h>
+#include <form.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "ncurses.h"
+
+#define max(a, b) ({\
+ typeof(a) _a = a;\
+ typeof(b) _b = b;\
+ _a > _b ? _a : _b; })
+
+#define min(a, b) ({\
+ typeof(a) _a = a;\
+ typeof(b) _b = b;\
+ _a < _b ? _a : _b; })
+
+typedef enum {
+ NORMAL = 1,
+ MAIN_HEADING,
+ MAIN_MENU_BOX,
+ MAIN_MENU_FORE,
+ MAIN_MENU_BACK,
+ MAIN_MENU_GREY,
+ MAIN_MENU_HEADING,
+ SCROLLWIN_TEXT,
+ SCROLLWIN_HEADING,
+ SCROLLWIN_BOX,
+ DIALOG_TEXT,
+ DIALOG_MENU_FORE,
+ DIALOG_MENU_BACK,
+ DIALOG_BOX,
+ INPUT_BOX,
+ INPUT_HEADING,
+ INPUT_TEXT,
+ INPUT_FIELD,
+ FUNCTION_TEXT,
+ FUNCTION_HIGHLIGHT,
+ ATTR_MAX
+} attributes_t;
+extern attributes_t attributes[];
+
+typedef enum {
+ F_HELP = 1,
+ F_SYMBOL = 2,
+ F_INSTS = 3,
+ F_CONF = 4,
+ F_BACK = 5,
+ F_SAVE = 6,
+ F_LOAD = 7,
+ F_SEARCH = 8,
+ F_EXIT = 9,
+} function_key;
+
+void set_colors(void);
+
+/* this changes the windows attributes !!! */
+void print_in_middle(WINDOW *win,
+ int starty,
+ int startx,
+ int width,
+ const char *string,
+ chtype color);
+int get_line_length(const char *line);
+int get_line_no(const char *text);
+const char *get_line(const char *text, int line_no);
+void fill_window(WINDOW *win, const char *text);
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...);
+int dialog_inputbox(WINDOW *main_window,
+ const char *title, const char *prompt,
+ const char *init, char **resultp, int *result_len);
+void refresh_all_windows(WINDOW *main_window);
+void show_scroll_win(WINDOW *main_window,
+ const char *title,
+ const char *text);
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
new file mode 100644
index 0000000..1500c38
--- /dev/null
+++ b/scripts/kconfig/qconf.cc
@@ -0,0 +1,1790 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <qglobal.h>
+
+#if QT_VERSION < 0x040000
+#include <stddef.h>
+#include <qmainwindow.h>
+#include <qvbox.h>
+#include <qvaluelist.h>
+#include <qtextbrowser.h>
+#include <qaction.h>
+#include <qheader.h>
+#include <qfiledialog.h>
+#include <qdragobject.h>
+#include <qpopupmenu.h>
+#else
+#include <q3mainwindow.h>
+#include <q3vbox.h>
+#include <q3valuelist.h>
+#include <q3textbrowser.h>
+#include <q3action.h>
+#include <q3header.h>
+#include <q3filedialog.h>
+#include <q3dragobject.h>
+#include <q3popupmenu.h>
+#endif
+
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qtoolbar.h>
+#include <qlayout.h>
+#include <qsplitter.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qmenubar.h>
+#include <qmessagebox.h>
+#include <qregexp.h>
+#include <qevent.h>
+
+#include <stdlib.h>
+
+#include "lkc.h"
+#include "qconf.h"
+
+#include "qconf.moc"
+#include "images.c"
+
+#ifdef _
+# undef _
+# define _ qgettext
+#endif
+
+static QApplication *configApp;
+static ConfigSettings *configSettings;
+
+Q3Action *ConfigMainWindow::saveAction;
+
+static inline QString qgettext(const char* str)
+{
+ return QString::fromLocal8Bit(gettext(str));
+}
+
+static inline QString qgettext(const QString& str)
+{
+ return QString::fromLocal8Bit(gettext(str.latin1()));
+}
+
+/**
+ * Reads a list of integer values from the application settings.
+ */
+Q3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
+{
+ Q3ValueList<int> result;
+ QStringList entryList = readListEntry(key, ok);
+ QStringList::Iterator it;
+
+ for (it = entryList.begin(); it != entryList.end(); ++it)
+ result.push_back((*it).toInt());
+
+ return result;
+}
+
+/**
+ * Writes a list of integer values to the application settings.
+ */
+bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& value)
+{
+ QStringList stringList;
+ Q3ValueList<int>::ConstIterator it;
+
+ for (it = value.begin(); it != value.end(); ++it)
+ stringList.push_back(QString::number(*it));
+ return writeEntry(key, stringList);
+}
+
+
+/*
+ * set the new data
+ * TODO check the value
+ */
+void ConfigItem::okRename(int col)
+{
+ Parent::okRename(col);
+ sym_set_string_value(menu->sym, text(dataColIdx).latin1());
+ listView()->updateList(this);
+}
+
+/*
+ * update the displayed of a menu entry
+ */
+void ConfigItem::updateMenu(void)
+{
+ ConfigList* list;
+ struct symbol* sym;
+ struct property *prop;
+ QString prompt;
+ int type;
+ tristate expr;
+
+ list = listView();
+ if (goParent) {
+ setPixmap(promptColIdx, list->menuBackPix);
+ prompt = "..";
+ goto set_prompt;
+ }
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ prompt = _(menu_get_prompt(menu));
+
+ if (prop) switch (prop->type) {
+ case P_MENU:
+ if (list->mode == singleMode || list->mode == symbolMode) {
+ /* a menuconfig entry is displayed differently
+ * depending whether it's at the view root or a child.
+ */
+ if (sym && list->rootEntry == menu)
+ break;
+ setPixmap(promptColIdx, list->menuPix);
+ } else {
+ if (sym)
+ break;
+ setPixmap(promptColIdx, 0);
+ }
+ goto set_prompt;
+ case P_COMMENT:
+ setPixmap(promptColIdx, 0);
+ goto set_prompt;
+ default:
+ ;
+ }
+ if (!sym)
+ goto set_prompt;
+
+ setText(nameColIdx, QString::fromLocal8Bit(sym->name));
+
+ type = sym_get_type(sym);
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ char ch;
+
+ if (!sym_is_changable(sym) && list->optMode == normalOpt) {
+ setPixmap(promptColIdx, 0);
+ setText(noColIdx, QString::null);
+ setText(modColIdx, QString::null);
+ setText(yesColIdx, QString::null);
+ break;
+ }
+ expr = sym_get_tristate_value(sym);
+ switch (expr) {
+ case yes:
+ if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ setPixmap(promptColIdx, list->choiceYesPix);
+ else
+ setPixmap(promptColIdx, list->symbolYesPix);
+ setText(yesColIdx, "Y");
+ ch = 'Y';
+ break;
+ case mod:
+ setPixmap(promptColIdx, list->symbolModPix);
+ setText(modColIdx, "M");
+ ch = 'M';
+ break;
+ default:
+ if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ setPixmap(promptColIdx, list->choiceNoPix);
+ else
+ setPixmap(promptColIdx, list->symbolNoPix);
+ setText(noColIdx, "N");
+ ch = 'N';
+ break;
+ }
+ if (expr != no)
+ setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
+ if (expr != mod)
+ setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
+ if (expr != yes)
+ setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
+
+ setText(dataColIdx, QChar(ch));
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ const char* data;
+
+ data = sym_get_string_value(sym);
+
+ int i = list->mapIdx(dataColIdx);
+ if (i >= 0)
+ setRenameEnabled(i, TRUE);
+ setText(dataColIdx, data);
+ if (type == S_STRING)
+ prompt = QString("%1: %2").arg(prompt).arg(data);
+ else
+ prompt = QString("(%2) %1").arg(prompt).arg(data);
+ break;
+ }
+ if (!sym_has_value(sym) && visible)
+ prompt += _(" (NEW)");
+set_prompt:
+ setText(promptColIdx, prompt);
+}
+
+void ConfigItem::testUpdateMenu(bool v)
+{
+ ConfigItem* i;
+
+ visible = v;
+ if (!menu)
+ return;
+
+ sym_calc_value(menu->sym);
+ if (menu->flags & MENU_CHANGED) {
+ /* the menu entry changed, so update all list items */
+ menu->flags &= ~MENU_CHANGED;
+ for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
+ i->updateMenu();
+ } else if (listView()->updateAll)
+ updateMenu();
+}
+
+void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
+{
+ ConfigList* list = listView();
+
+ if (visible) {
+ if (isSelected() && !list->hasFocus() && list->mode == menuMode)
+ Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
+ else
+ Parent::paintCell(p, cg, column, width, align);
+ } else
+ Parent::paintCell(p, list->disabledColorGroup, column, width, align);
+}
+
+/*
+ * construct a menu entry
+ */
+void ConfigItem::init(void)
+{
+ if (menu) {
+ ConfigList* list = listView();
+ nextItem = (ConfigItem*)menu->data;
+ menu->data = this;
+
+ if (list->mode != fullMode)
+ setOpen(TRUE);
+ sym_calc_value(menu->sym);
+ }
+ updateMenu();
+}
+
+/*
+ * destruct a menu entry
+ */
+ConfigItem::~ConfigItem(void)
+{
+ if (menu) {
+ ConfigItem** ip = (ConfigItem**)&menu->data;
+ for (; *ip; ip = &(*ip)->nextItem) {
+ if (*ip == this) {
+ *ip = nextItem;
+ break;
+ }
+ }
+ }
+}
+
+ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
+ : Parent(parent)
+{
+ connect(this, SIGNAL(lostFocus()), SLOT(hide()));
+}
+
+void ConfigLineEdit::show(ConfigItem* i)
+{
+ item = i;
+ if (sym_get_string_value(item->menu->sym))
+ setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
+ else
+ setText(QString::null);
+ Parent::show();
+ setFocus();
+}
+
+void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
+{
+ switch (e->key()) {
+ case Qt::Key_Escape:
+ break;
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ sym_set_string_value(item->menu->sym, text().latin1());
+ parent()->updateList(item);
+ break;
+ default:
+ Parent::keyPressEvent(e);
+ return;
+ }
+ e->accept();
+ parent()->list->setFocus();
+ hide();
+}
+
+ConfigList::ConfigList(ConfigView* p, const char *name)
+ : Parent(p, name),
+ updateAll(false),
+ symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
+ choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
+ menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
+ showName(false), showRange(false), showData(false), optMode(normalOpt),
+ rootEntry(0), headerPopup(0)
+{
+ int i;
+
+ setSorting(-1);
+ setRootIsDecorated(TRUE);
+ disabledColorGroup = palette().active();
+ disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
+ inactivedColorGroup = palette().active();
+ inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
+
+ connect(this, SIGNAL(selectionChanged(void)),
+ SLOT(updateSelection(void)));
+
+ if (name) {
+ configSettings->beginGroup(name);
+ showName = configSettings->readBoolEntry("/showName", false);
+ showRange = configSettings->readBoolEntry("/showRange", false);
+ showData = configSettings->readBoolEntry("/showData", false);
+ optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false);
+ configSettings->endGroup();
+ connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+ }
+
+ for (i = 0; i < colNr; i++)
+ colMap[i] = colRevMap[i] = -1;
+ addColumn(promptColIdx, _("Option"));
+
+ reinit();
+}
+
+bool ConfigList::menuSkip(struct menu *menu)
+{
+ if (optMode == normalOpt && menu_is_visible(menu))
+ return false;
+ if (optMode == promptOpt && menu_has_prompt(menu))
+ return false;
+ if (optMode == allOpt)
+ return false;
+ return true;
+}
+
+void ConfigList::reinit(void)
+{
+ removeColumn(dataColIdx);
+ removeColumn(yesColIdx);
+ removeColumn(modColIdx);
+ removeColumn(noColIdx);
+ removeColumn(nameColIdx);
+
+ if (showName)
+ addColumn(nameColIdx, _("Name"));
+ if (showRange) {
+ addColumn(noColIdx, "N");
+ addColumn(modColIdx, "M");
+ addColumn(yesColIdx, "Y");
+ }
+ if (showData)
+ addColumn(dataColIdx, _("Value"));
+
+ updateListAll();
+}
+
+void ConfigList::saveSettings(void)
+{
+ if (name()) {
+ configSettings->beginGroup(name());
+ configSettings->writeEntry("/showName", showName);
+ configSettings->writeEntry("/showRange", showRange);
+ configSettings->writeEntry("/showData", showData);
+ configSettings->writeEntry("/optionMode", (int)optMode);
+ configSettings->endGroup();
+ }
+}
+
+ConfigItem* ConfigList::findConfigItem(struct menu *menu)
+{
+ ConfigItem* item = (ConfigItem*)menu->data;
+
+ for (; item; item = item->nextItem) {
+ if (this == item->listView())
+ break;
+ }
+
+ return item;
+}
+
+void ConfigList::updateSelection(void)
+{
+ struct menu *menu;
+ enum prop_type type;
+
+ ConfigItem* item = (ConfigItem*)selectedItem();
+ if (!item)
+ return;
+
+ menu = item->menu;
+ emit menuChanged(menu);
+ if (!menu)
+ return;
+ type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (mode == menuMode && type == P_MENU)
+ emit menuSelected(menu);
+}
+
+void ConfigList::updateList(ConfigItem* item)
+{
+ ConfigItem* last = 0;
+
+ if (!rootEntry) {
+ if (mode != listMode)
+ goto update;
+ Q3ListViewItemIterator it(this);
+ ConfigItem* item;
+
+ for (; it.current(); ++it) {
+ item = (ConfigItem*)it.current();
+ if (!item->menu)
+ continue;
+ item->testUpdateMenu(menu_is_visible(item->menu));
+ }
+ return;
+ }
+
+ if (rootEntry != &rootmenu && (mode == singleMode ||
+ (mode == symbolMode && rootEntry->parent != &rootmenu))) {
+ item = firstChild();
+ if (!item)
+ item = new ConfigItem(this, 0, true);
+ last = item;
+ }
+ if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
+ rootEntry->sym && rootEntry->prompt) {
+ item = last ? last->nextSibling() : firstChild();
+ if (!item)
+ item = new ConfigItem(this, last, rootEntry, true);
+ else
+ item->testUpdateMenu(true);
+
+ updateMenuList(item, rootEntry);
+ triggerUpdate();
+ return;
+ }
+update:
+ updateMenuList(this, rootEntry);
+ triggerUpdate();
+}
+
+void ConfigList::setValue(ConfigItem* item, tristate val)
+{
+ struct symbol* sym;
+ int type;
+ tristate oldval;
+
+ sym = item->menu ? item->menu->sym : 0;
+ if (!sym)
+ return;
+
+ type = sym_get_type(sym);
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ oldval = sym_get_tristate_value(sym);
+
+ if (!sym_set_tristate_value(sym, val))
+ return;
+ if (oldval == no && item->menu->list)
+ item->setOpen(TRUE);
+ parent()->updateList(item);
+ break;
+ }
+}
+
+void ConfigList::changeValue(ConfigItem* item)
+{
+ struct symbol* sym;
+ struct menu* menu;
+ int type, oldexpr, newexpr;
+
+ menu = item->menu;
+ if (!menu)
+ return;
+ sym = menu->sym;
+ if (!sym) {
+ if (item->menu->list)
+ item->setOpen(!item->isOpen());
+ return;
+ }
+
+ type = sym_get_type(sym);
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ oldexpr = sym_get_tristate_value(sym);
+ newexpr = sym_toggle_tristate_value(sym);
+ if (item->menu->list) {
+ if (oldexpr == newexpr)
+ item->setOpen(!item->isOpen());
+ else if (oldexpr == no)
+ item->setOpen(TRUE);
+ }
+ if (oldexpr != newexpr)
+ parent()->updateList(item);
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ if (colMap[dataColIdx] >= 0)
+ item->startRename(colMap[dataColIdx]);
+ else
+ parent()->lineEdit->show(item);
+ break;
+ }
+}
+
+void ConfigList::setRootMenu(struct menu *menu)
+{
+ enum prop_type type;
+
+ if (rootEntry == menu)
+ return;
+ type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (type != P_MENU)
+ return;
+ updateMenuList(this, 0);
+ rootEntry = menu;
+ updateListAll();
+ setSelected(currentItem(), hasFocus());
+ ensureItemVisible(currentItem());
+}
+
+void ConfigList::setParentMenu(void)
+{
+ ConfigItem* item;
+ struct menu *oldroot;
+
+ oldroot = rootEntry;
+ if (rootEntry == &rootmenu)
+ return;
+ setRootMenu(menu_get_parent_menu(rootEntry->parent));
+
+ Q3ListViewItemIterator it(this);
+ for (; (item = (ConfigItem*)it.current()); it++) {
+ if (item->menu == oldroot) {
+ setCurrentItem(item);
+ ensureItemVisible(item);
+ break;
+ }
+ }
+}
+
+/*
+ * update all the children of a menu entry
+ * removes/adds the entries from the parent widget as necessary
+ *
+ * parent: either the menu list widget or a menu entry widget
+ * menu: entry to be updated
+ */
+template <class P>
+void ConfigList::updateMenuList(P* parent, struct menu* menu)
+{
+ struct menu* child;
+ ConfigItem* item;
+ ConfigItem* last;
+ bool visible;
+ enum prop_type type;
+
+ if (!menu) {
+ while ((item = parent->firstChild()))
+ delete item;
+ return;
+ }
+
+ last = parent->firstChild();
+ if (last && !last->goParent)
+ last = 0;
+ for (child = menu->list; child; child = child->next) {
+ item = last ? last->nextSibling() : parent->firstChild();
+ type = child->prompt ? child->prompt->type : P_UNKNOWN;
+
+ switch (mode) {
+ case menuMode:
+ if (!(child->flags & MENU_ROOT))
+ goto hide;
+ break;
+ case symbolMode:
+ if (child->flags & MENU_ROOT)
+ goto hide;
+ break;
+ default:
+ break;
+ }
+
+ visible = menu_is_visible(child);
+ if (!menuSkip(child)) {
+ if (!child->sym && !child->list && !child->prompt)
+ continue;
+ if (!item || item->menu != child)
+ item = new ConfigItem(parent, last, child, visible);
+ else
+ item->testUpdateMenu(visible);
+
+ if (mode == fullMode || mode == menuMode || type != P_MENU)
+ updateMenuList(item, child);
+ else
+ updateMenuList(item, 0);
+ last = item;
+ continue;
+ }
+ hide:
+ if (item && item->menu == child) {
+ last = parent->firstChild();
+ if (last == item)
+ last = 0;
+ else while (last->nextSibling() != item)
+ last = last->nextSibling();
+ delete item;
+ }
+ }
+}
+
+void ConfigList::keyPressEvent(QKeyEvent* ev)
+{
+ Q3ListViewItem* i = currentItem();
+ ConfigItem* item;
+ struct menu *menu;
+ enum prop_type type;
+
+ if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
+ emit parentSelected();
+ ev->accept();
+ return;
+ }
+
+ if (!i) {
+ Parent::keyPressEvent(ev);
+ return;
+ }
+ item = (ConfigItem*)i;
+
+ switch (ev->key()) {
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ if (item->goParent) {
+ emit parentSelected();
+ break;
+ }
+ menu = item->menu;
+ if (!menu)
+ break;
+ type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (type == P_MENU && rootEntry != menu &&
+ mode != fullMode && mode != menuMode) {
+ emit menuSelected(menu);
+ break;
+ }
+ case Qt::Key_Space:
+ changeValue(item);
+ break;
+ case Qt::Key_N:
+ setValue(item, no);
+ break;
+ case Qt::Key_M:
+ setValue(item, mod);
+ break;
+ case Qt::Key_Y:
+ setValue(item, yes);
+ break;
+ default:
+ Parent::keyPressEvent(ev);
+ return;
+ }
+ ev->accept();
+}
+
+void ConfigList::contentsMousePressEvent(QMouseEvent* e)
+{
+ //QPoint p(contentsToViewport(e->pos()));
+ //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
+ Parent::contentsMousePressEvent(e);
+}
+
+void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
+{
+ QPoint p(contentsToViewport(e->pos()));
+ ConfigItem* item = (ConfigItem*)itemAt(p);
+ struct menu *menu;
+ enum prop_type ptype;
+ const QPixmap* pm;
+ int idx, x;
+
+ if (!item)
+ goto skip;
+
+ menu = item->menu;
+ x = header()->offset() + p.x();
+ idx = colRevMap[header()->sectionAt(x)];
+ switch (idx) {
+ case promptColIdx:
+ pm = item->pixmap(promptColIdx);
+ if (pm) {
+ int off = header()->sectionPos(0) + itemMargin() +
+ treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
+ if (x >= off && x < off + pm->width()) {
+ if (item->goParent) {
+ emit parentSelected();
+ break;
+ } else if (!menu)
+ break;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (ptype == P_MENU && rootEntry != menu &&
+ mode != fullMode && mode != menuMode)
+ emit menuSelected(menu);
+ else
+ changeValue(item);
+ }
+ }
+ break;
+ case noColIdx:
+ setValue(item, no);
+ break;
+ case modColIdx:
+ setValue(item, mod);
+ break;
+ case yesColIdx:
+ setValue(item, yes);
+ break;
+ case dataColIdx:
+ changeValue(item);
+ break;
+ }
+
+skip:
+ //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
+ Parent::contentsMouseReleaseEvent(e);
+}
+
+void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
+{
+ //QPoint p(contentsToViewport(e->pos()));
+ //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
+ Parent::contentsMouseMoveEvent(e);
+}
+
+void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
+{
+ QPoint p(contentsToViewport(e->pos()));
+ ConfigItem* item = (ConfigItem*)itemAt(p);
+ struct menu *menu;
+ enum prop_type ptype;
+
+ if (!item)
+ goto skip;
+ if (item->goParent) {
+ emit parentSelected();
+ goto skip;
+ }
+ menu = item->menu;
+ if (!menu)
+ goto skip;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
+ emit menuSelected(menu);
+ else if (menu->sym)
+ changeValue(item);
+
+skip:
+ //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
+ Parent::contentsMouseDoubleClickEvent(e);
+}
+
+void ConfigList::focusInEvent(QFocusEvent *e)
+{
+ struct menu *menu = NULL;
+
+ Parent::focusInEvent(e);
+
+ ConfigItem* item = (ConfigItem *)currentItem();
+ if (item) {
+ setSelected(item, TRUE);
+ menu = item->menu;
+ }
+ emit gotFocus(menu);
+}
+
+void ConfigList::contextMenuEvent(QContextMenuEvent *e)
+{
+ if (e->y() <= header()->geometry().bottom()) {
+ if (!headerPopup) {
+ Q3Action *action;
+
+ headerPopup = new Q3PopupMenu(this);
+ action = new Q3Action(NULL, _("Show Name"), 0, this);
+ action->setToggleAction(TRUE);
+ connect(action, SIGNAL(toggled(bool)),
+ parent(), SLOT(setShowName(bool)));
+ connect(parent(), SIGNAL(showNameChanged(bool)),
+ action, SLOT(setOn(bool)));
+ action->setOn(showName);
+ action->addTo(headerPopup);
+ action = new Q3Action(NULL, _("Show Range"), 0, this);
+ action->setToggleAction(TRUE);
+ connect(action, SIGNAL(toggled(bool)),
+ parent(), SLOT(setShowRange(bool)));
+ connect(parent(), SIGNAL(showRangeChanged(bool)),
+ action, SLOT(setOn(bool)));
+ action->setOn(showRange);
+ action->addTo(headerPopup);
+ action = new Q3Action(NULL, _("Show Data"), 0, this);
+ action->setToggleAction(TRUE);
+ connect(action, SIGNAL(toggled(bool)),
+ parent(), SLOT(setShowData(bool)));
+ connect(parent(), SIGNAL(showDataChanged(bool)),
+ action, SLOT(setOn(bool)));
+ action->setOn(showData);
+ action->addTo(headerPopup);
+ }
+ headerPopup->exec(e->globalPos());
+ e->accept();
+ } else
+ e->ignore();
+}
+
+ConfigView*ConfigView::viewList;
+QAction *ConfigView::showNormalAction;
+QAction *ConfigView::showAllAction;
+QAction *ConfigView::showPromptAction;
+
+ConfigView::ConfigView(QWidget* parent, const char *name)
+ : Parent(parent, name)
+{
+ list = new ConfigList(this, name);
+ lineEdit = new ConfigLineEdit(this);
+ lineEdit->hide();
+
+ this->nextView = viewList;
+ viewList = this;
+}
+
+ConfigView::~ConfigView(void)
+{
+ ConfigView** vp;
+
+ for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
+ if (*vp == this) {
+ *vp = nextView;
+ break;
+ }
+ }
+}
+
+void ConfigView::setOptionMode(QAction *act)
+{
+ if (act == showNormalAction)
+ list->optMode = normalOpt;
+ else if (act == showAllAction)
+ list->optMode = allOpt;
+ else
+ list->optMode = promptOpt;
+
+ list->updateListAll();
+}
+
+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)
+{
+ Q3ListViewItemIterator it(this);
+
+ for (; it.current(); it++)
+ it.current()->setOpen(open);
+}
+
+void ConfigView::updateList(ConfigItem* item)
+{
+ ConfigView* v;
+
+ for (v = viewList; v; v = v->nextView)
+ v->list->updateList(item);
+}
+
+void ConfigView::updateListAll(void)
+{
+ ConfigView* v;
+
+ for (v = viewList; v; v = v->nextView)
+ v->list->updateListAll();
+}
+
+ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
+ : Parent(parent, name), sym(0), _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;
+ sym = NULL;
+ if (!_menu)
+ clear();
+ else
+ menuInfo();
+}
+
+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);
+
+ struct gstr help_gstr = str_new();
+ menu_get_ext_help(_menu, &help_gstr);
+ help = print_filter(str_get(&help_gstr));
+ str_free(&help_gstr);
+ } 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 += " 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:
+ case P_SELECT:
+ case P_RANGE:
+ case P_ENV:
+ debug += prop_get_type_name(prop->type);
+ debug += ": ";
+ 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;
+ default:
+ debug += "unknown property: ";
+ debug += prop_get_type_name(prop->type);
+ debug += "<br>";
+ }
+ if (prop->visible.expr) {
+ debug += " 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, "<");
+ i += 4;
+ break;
+ case '>':
+ res.replace(i, 1, ">");
+ i += 4;
+ break;
+ case '&':
+ res.replace(i, 1, "&");
+ i += 5;
+ break;
+ case '"':
+ res.replace(i, 1, """);
+ 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;
+}
+
+Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
+{
+ Q3PopupMenu* popup = Parent::createPopupMenu(pos);
+ Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup);
+ action->setToggleAction(TRUE);
+ connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
+ connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
+ action->setOn(showDebug());
+ popup->insertSeparator();
+ action->addTo(popup);
+ return popup;
+}
+
+void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
+{
+ Parent::contentsContextMenuEvent(e);
+}
+
+ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* 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(Qt::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 *)));
+ connect(list->list, SIGNAL(menuChanged(struct menu *)),
+ parent, SLOT(setMenuLink(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);
+ Q3ValueList<int> sizes = configSettings->readSizes("/split", &ok);
+ if (ok)
+ split->setSizes(sizes);
+ configSettings->endGroup();
+ connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+ }
+}
+
+void ConfigSearchWindow::saveSettings(void)
+{
+ if (name()) {
+ configSettings->beginGroup(name());
+ configSettings->writeEntry("/window x", pos().x());
+ configSettings->writeEntry("/window y", pos().y());
+ configSettings->writeEntry("/window width", size().width());
+ configSettings->writeEntry("/window height", size().height());
+ configSettings->writeSizes("/split", split->sizes());
+ configSettings->endGroup();
+ }
+}
+
+void ConfigSearchWindow::search(void)
+{
+ struct symbol **p;
+ struct property *prop;
+ ConfigItem *lastItem = NULL;
+
+ free(result);
+ list->list->clear();
+ info->clear();
+
+ result = sym_re_search(editField->text().latin1());
+ if (!result)
+ return;
+ for (p = result; *p; p++) {
+ for_all_prompts((*p), prop)
+ lastItem = new ConfigItem(list->list, lastItem, prop->menu,
+ menu_is_visible(prop->menu));
+ }
+}
+
+/*
+ * Construct the complete config widget
+ */
+ConfigMainWindow::ConfigMainWindow(void)
+ : searchWindow(0)
+{
+ QMenuBar* menu;
+ bool ok;
+ int x, y, width, height;
+ char title[256];
+
+ QDesktopWidget *d = configApp->desktop();
+ snprintf(title, sizeof(title), "%s%s",
+ rootmenu.prompt->text,
+#if QT_VERSION < 0x040000
+ " (Qt3)"
+#else
+ ""
+#endif
+ );
+ setCaption(title);
+
+ width = configSettings->readNumEntry("/window width", d->width() - 64);
+ height = configSettings->readNumEntry("/window height", d->height() - 64);
+ resize(width, height);
+ x = configSettings->readNumEntry("/window x", 0, &ok);
+ if (ok)
+ y = configSettings->readNumEntry("/window y", 0, &ok);
+ if (ok)
+ move(x, y);
+
+ split1 = new QSplitter(this);
+ split1->setOrientation(Qt::Horizontal);
+ setCentralWidget(split1);
+
+ menuView = new ConfigView(split1, "menu");
+ menuList = menuView->list;
+
+ split2 = new QSplitter(split1);
+ split2->setOrientation(Qt::Vertical);
+
+ // create config tree
+ configView = new ConfigView(split2, "config");
+ configList = configView->list;
+
+ helpText = new ConfigInfoView(split2, "help");
+ helpText->setTextFormat(Qt::RichText);
+
+ setTabOrder(configList, helpText);
+ configList->setFocus();
+
+ menu = menuBar();
+ toolBar = new Q3ToolBar("Tools", this);
+
+ backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this);
+ connect(backAction, SIGNAL(activated()), SLOT(goBack()));
+ backAction->setEnabled(FALSE);
+ Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
+ connect(quitAction, SIGNAL(activated()), SLOT(close()));
+ Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
+ connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
+ saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
+ connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
+ conf_set_changed_callback(conf_changed);
+ // Set saveAction's initial state
+ conf_changed();
+ Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this);
+ connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
+ Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
+ connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
+ Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
+ connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
+ Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
+ connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
+ Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
+ connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
+
+ Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this);
+ showNameAction->setToggleAction(TRUE);
+ connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
+ connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
+ showNameAction->setOn(configView->showName());
+ Q3Action *showRangeAction = new Q3Action(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);
+ Q3Action *showDataAction = new Q3Action(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);
+
+ QActionGroup *optGroup = new QActionGroup(this);
+ optGroup->setExclusive(TRUE);
+ connect(optGroup, SIGNAL(selected(QAction *)), configView,
+ SLOT(setOptionMode(QAction *)));
+ connect(optGroup, SIGNAL(selected(QAction *)), menuView,
+ SLOT(setOptionMode(QAction *)));
+
+#if QT_VERSION >= 0x040000
+ configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup);
+ configView->showAllAction = new QAction(_("Show All Options"), optGroup);
+ configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup);
+#else
+ configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup);
+ configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup);
+ configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup);
+#endif
+ configView->showNormalAction->setToggleAction(TRUE);
+ configView->showNormalAction->setOn(configList->optMode == normalOpt);
+ configView->showAllAction->setToggleAction(TRUE);
+ configView->showAllAction->setOn(configList->optMode == allOpt);
+ configView->showPromptAction->setToggleAction(TRUE);
+ configView->showPromptAction->setOn(configList->optMode == promptOpt);
+
+ Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this);
+ showDebugAction->setToggleAction(TRUE);
+ connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
+ connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
+ showDebugAction->setOn(helpText->showDebug());
+
+ Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this);
+ connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
+ Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this);
+ connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
+
+ // init tool bar
+ backAction->addTo(toolBar);
+ toolBar->addSeparator();
+ loadAction->addTo(toolBar);
+ saveAction->addTo(toolBar);
+ toolBar->addSeparator();
+ singleViewAction->addTo(toolBar);
+ splitViewAction->addTo(toolBar);
+ fullViewAction->addTo(toolBar);
+
+ // create config menu
+ Q3PopupMenu* config = new Q3PopupMenu(this);
+ menu->insertItem(_("&File"), config);
+ loadAction->addTo(config);
+ saveAction->addTo(config);
+ saveAsAction->addTo(config);
+ config->insertSeparator();
+ quitAction->addTo(config);
+
+ // create edit menu
+ Q3PopupMenu* editMenu = new Q3PopupMenu(this);
+ menu->insertItem(_("&Edit"), editMenu);
+ searchAction->addTo(editMenu);
+
+ // create options menu
+ Q3PopupMenu* optionMenu = new Q3PopupMenu(this);
+ menu->insertItem(_("&Option"), optionMenu);
+ showNameAction->addTo(optionMenu);
+ showRangeAction->addTo(optionMenu);
+ showDataAction->addTo(optionMenu);
+ optionMenu->insertSeparator();
+ optGroup->addTo(optionMenu);
+ optionMenu->insertSeparator();
+
+ // create help menu
+ Q3PopupMenu* helpMenu = new Q3PopupMenu(this);
+ menu->insertSeparator();
+ menu->insertItem(_("&Help"), helpMenu);
+ showIntroAction->addTo(helpMenu);
+ showAboutAction->addTo(helpMenu);
+
+ connect(configList, SIGNAL(menuChanged(struct menu *)),
+ helpText, SLOT(setInfo(struct menu *)));
+ connect(configList, SIGNAL(menuSelected(struct menu *)),
+ SLOT(changeMenu(struct menu *)));
+ connect(configList, SIGNAL(parentSelected()),
+ SLOT(goBack()));
+ connect(menuList, SIGNAL(menuChanged(struct menu *)),
+ helpText, SLOT(setInfo(struct menu *)));
+ connect(menuList, SIGNAL(menuSelected(struct menu *)),
+ SLOT(changeMenu(struct menu *)));
+
+ connect(configList, SIGNAL(gotFocus(struct menu *)),
+ helpText, SLOT(setInfo(struct menu *)));
+ connect(menuList, SIGNAL(gotFocus(struct menu *)),
+ helpText, SLOT(setInfo(struct menu *)));
+ connect(menuList, SIGNAL(gotFocus(struct menu *)),
+ SLOT(listFocusChanged(void)));
+ connect(helpText, SIGNAL(menuSelected(struct menu *)),
+ SLOT(setMenuLink(struct menu *)));
+
+ QString listMode = configSettings->readEntry("/listMode", "symbol");
+ if (listMode == "single")
+ showSingleView();
+ else if (listMode == "full")
+ showFullView();
+ else /*if (listMode == "split")*/
+ showSplitView();
+
+ // UI setup done, restore splitter positions
+ Q3ValueList<int> sizes = configSettings->readSizes("/split1", &ok);
+ if (ok)
+ split1->setSizes(sizes);
+
+ sizes = configSettings->readSizes("/split2", &ok);
+ if (ok)
+ split2->setSizes(sizes);
+}
+
+void ConfigMainWindow::loadConfig(void)
+{
+ QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);
+ if (s.isNull())
+ return;
+ if (conf_read(QFile::encodeName(s)))
+ QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
+ ConfigView::updateListAll();
+}
+
+bool ConfigMainWindow::saveConfig(void)
+{
+ if (conf_write(NULL)) {
+ QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
+ return false;
+ }
+ return true;
+}
+
+void ConfigMainWindow::saveConfigAs(void)
+{
+ QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);
+ if (s.isNull())
+ return;
+ saveConfig();
+}
+
+void ConfigMainWindow::searchConfig(void)
+{
+ if (!searchWindow)
+ searchWindow = new ConfigSearchWindow(this, "search");
+ searchWindow->show();
+}
+
+void ConfigMainWindow::changeMenu(struct menu *menu)
+{
+ configList->setRootMenu(menu);
+ if (configList->rootEntry->parent == &rootmenu)
+ backAction->setEnabled(FALSE);
+ else
+ backAction->setEnabled(TRUE);
+}
+
+void ConfigMainWindow::setMenuLink(struct menu *menu)
+{
+ struct menu *parent;
+ ConfigList* list = NULL;
+ ConfigItem* item;
+
+ if (configList->menuSkip(menu))
+ return;
+
+ switch (configList->mode) {
+ case singleMode:
+ list = configList;
+ parent = menu_get_parent_menu(menu);
+ if (!parent)
+ return;
+ list->setRootMenu(parent);
+ break;
+ case symbolMode:
+ if (menu->flags & MENU_ROOT) {
+ configList->setRootMenu(menu);
+ configList->clearSelection();
+ list = menuList;
+ } else {
+ list = configList;
+ parent = menu_get_parent_menu(menu->parent);
+ if (!parent)
+ return;
+ item = menuList->findConfigItem(parent);
+ if (item) {
+ menuList->setSelected(item, TRUE);
+ menuList->ensureItemVisible(item);
+ }
+ list->setRootMenu(parent);
+ }
+ break;
+ case fullMode:
+ list = configList;
+ break;
+ default:
+ break;
+ }
+
+ if (list) {
+ item = list->findConfigItem(menu);
+ if (item) {
+ list->setSelected(item, TRUE);
+ list->ensureItemVisible(item);
+ list->setFocus();
+ }
+ }
+}
+
+void ConfigMainWindow::listFocusChanged(void)
+{
+ if (menuList->mode == menuMode)
+ configList->clearSelection();
+}
+
+void ConfigMainWindow::goBack(void)
+{
+ ConfigItem* item;
+
+ configList->setParentMenu();
+ if (configList->rootEntry == &rootmenu)
+ backAction->setEnabled(FALSE);
+ item = (ConfigItem*)menuList->selectedItem();
+ while (item) {
+ if (item->menu == configList->rootEntry) {
+ menuList->setSelected(item, TRUE);
+ break;
+ }
+ item = (ConfigItem*)item->parent();
+ }
+}
+
+void ConfigMainWindow::showSingleView(void)
+{
+ menuView->hide();
+ menuList->setRootMenu(0);
+ configList->mode = singleMode;
+ if (configList->rootEntry == &rootmenu)
+ configList->updateListAll();
+ else
+ configList->setRootMenu(&rootmenu);
+ configList->setAllOpen(TRUE);
+ configList->setFocus();
+}
+
+void ConfigMainWindow::showSplitView(void)
+{
+ configList->mode = symbolMode;
+ if (configList->rootEntry == &rootmenu)
+ configList->updateListAll();
+ else
+ configList->setRootMenu(&rootmenu);
+ configList->setAllOpen(TRUE);
+ configApp->processEvents();
+ menuList->mode = menuMode;
+ menuList->setRootMenu(&rootmenu);
+ menuList->setAllOpen(TRUE);
+ menuView->show();
+ menuList->setFocus();
+}
+
+void ConfigMainWindow::showFullView(void)
+{
+ menuView->hide();
+ menuList->setRootMenu(0);
+ configList->mode = fullMode;
+ if (configList->rootEntry == &rootmenu)
+ configList->updateListAll();
+ else
+ configList->setRootMenu(&rootmenu);
+ configList->setAllOpen(FALSE);
+ configList->setFocus();
+}
+
+/*
+ * ask for saving configuration before quitting
+ * TODO ask only when something changed
+ */
+void ConfigMainWindow::closeEvent(QCloseEvent* e)
+{
+ if (!conf_get_changed()) {
+ e->accept();
+ return;
+ }
+ QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
+ QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
+ mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
+ mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
+ mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
+ switch (mb.exec()) {
+ case QMessageBox::Yes:
+ if (saveConfig())
+ e->accept();
+ else
+ e->ignore();
+ break;
+ case QMessageBox::No:
+ e->accept();
+ break;
+ case QMessageBox::Cancel:
+ e->ignore();
+ break;
+ }
+}
+
+void ConfigMainWindow::showIntro(void)
+{
+ static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
+ "For each option, a blank box indicates the feature is disabled, a check\n"
+ "indicates it is enabled, and a dot indicates that it is to be compiled\n"
+ "as a module. Clicking on the box will cycle through the three states.\n\n"
+ "If you do not see an option (e.g., a device driver) that you believe\n"
+ "should be present, try turning on Show All Options under the Options menu.\n"
+ "Although there is no cross reference yet to help you figure out what other\n"
+ "options must be enabled to support the option you are interested in, you can\n"
+ "still view the help of a grayed-out option.\n\n"
+ "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
+ "which you can then match by examining other options.\n\n");
+
+ QMessageBox::information(this, "qconf", str);
+}
+
+void ConfigMainWindow::showAbout(void)
+{
+ static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>.\n\n"
+ "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
+
+ QMessageBox::information(this, "qconf", str);
+}
+
+void ConfigMainWindow::saveSettings(void)
+{
+ configSettings->writeEntry("/window x", pos().x());
+ configSettings->writeEntry("/window y", pos().y());
+ configSettings->writeEntry("/window width", size().width());
+ configSettings->writeEntry("/window height", size().height());
+
+ QString entry;
+ switch(configList->mode) {
+ case singleMode :
+ entry = "single";
+ break;
+
+ case symbolMode :
+ entry = "split";
+ break;
+
+ case fullMode :
+ entry = "full";
+ break;
+
+ default:
+ break;
+ }
+ configSettings->writeEntry("/listMode", entry);
+
+ configSettings->writeSizes("/split1", split1->sizes());
+ configSettings->writeSizes("/split2", split2->sizes());
+}
+
+void ConfigMainWindow::conf_changed(void)
+{
+ if (saveAction)
+ saveAction->setEnabled(conf_get_changed());
+}
+
+void fixup_rootmenu(struct menu *menu)
+{
+ struct menu *child;
+ static int menu_cnt = 0;
+
+ menu->flags |= MENU_ROOT;
+ for (child = menu->list; child; child = child->next) {
+ if (child->prompt && child->prompt->type == P_MENU) {
+ menu_cnt++;
+ fixup_rootmenu(child);
+ menu_cnt--;
+ } else if (!menu_cnt)
+ fixup_rootmenu(child);
+ }
+}
+
+static const char *progname;
+
+static void usage(void)
+{
+ printf(_("%s <config>\n"), progname);
+ exit(0);
+}
+
+int main(int ac, char** av)
+{
+ ConfigMainWindow* v;
+ const char *name;
+
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ progname = av[0];
+ configApp = new QApplication(ac, av);
+ if (ac > 1 && av[1][0] == '-') {
+ switch (av[1][1]) {
+ case 'h':
+ case '?':
+ usage();
+ }
+ name = av[2];
+ } else
+ name = av[1];
+ if (!name)
+ usage();
+
+ conf_parse(name);
+ fixup_rootmenu(&rootmenu);
+ conf_read(NULL);
+ //zconfdump(stdout);
+
+ configSettings = new ConfigSettings();
+ configSettings->beginGroup("/kconfig/qconf");
+ v = new ConfigMainWindow();
+
+ //zconfdump(stdout);
+ configApp->setMainWidget(v);
+ configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
+ configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
+ v->show();
+ configApp->exec();
+
+ configSettings->endGroup();
+ delete configSettings;
+
+ return 0;
+}
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
new file mode 100644
index 0000000..3715b3e
--- /dev/null
+++ b/scripts/kconfig/qconf.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#if QT_VERSION < 0x040000
+#include <qlistview.h>
+#else
+#include <q3listview.h>
+#endif
+#include <qsettings.h>
+
+#if QT_VERSION < 0x040000
+#define Q3ValueList QValueList
+#define Q3PopupMenu QPopupMenu
+#define Q3ListView QListView
+#define Q3ListViewItem QListViewItem
+#define Q3VBox QVBox
+#define Q3TextBrowser QTextBrowser
+#define Q3MainWindow QMainWindow
+#define Q3Action QAction
+#define Q3ToolBar QToolBar
+#define Q3ListViewItemIterator QListViewItemIterator
+#define Q3FileDialog QFileDialog
+#endif
+
+class ConfigView;
+class ConfigList;
+class ConfigItem;
+class ConfigLineEdit;
+class ConfigMainWindow;
+
+class ConfigSettings : public QSettings {
+public:
+ Q3ValueList<int> readSizes(const QString& key, bool *ok);
+ bool writeSizes(const QString& key, const Q3ValueList<int>& value);
+};
+
+enum colIdx {
+ promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
+};
+enum listMode {
+ singleMode, menuMode, symbolMode, fullMode, listMode
+};
+enum optionMode {
+ normalOpt = 0, allOpt, promptOpt
+};
+
+class ConfigList : public Q3ListView {
+ Q_OBJECT
+ typedef class Q3ListView Parent;
+public:
+ ConfigList(ConfigView* p, const char *name = 0);
+ void reinit(void);
+ ConfigView* parent(void) const
+ {
+ return (ConfigView*)Parent::parent();
+ }
+ ConfigItem* findConfigItem(struct menu *);
+
+protected:
+ void keyPressEvent(QKeyEvent *e);
+ void contentsMousePressEvent(QMouseEvent *e);
+ void contentsMouseReleaseEvent(QMouseEvent *e);
+ void contentsMouseMoveEvent(QMouseEvent *e);
+ void contentsMouseDoubleClickEvent(QMouseEvent *e);
+ void focusInEvent(QFocusEvent *e);
+ void contextMenuEvent(QContextMenuEvent *e);
+
+public slots:
+ void setRootMenu(struct menu *menu);
+
+ void updateList(ConfigItem *item);
+ void setValue(ConfigItem* item, tristate val);
+ void changeValue(ConfigItem* item);
+ void updateSelection(void);
+ void saveSettings(void);
+signals:
+ void menuChanged(struct menu *menu);
+ void menuSelected(struct menu *menu);
+ void parentSelected(void);
+ void gotFocus(struct menu *);
+
+public:
+ void updateListAll(void)
+ {
+ updateAll = true;
+ updateList(NULL);
+ updateAll = false;
+ }
+ ConfigList* listView()
+ {
+ return this;
+ }
+ ConfigItem* firstChild() const
+ {
+ return (ConfigItem *)Parent::firstChild();
+ }
+ int mapIdx(colIdx idx)
+ {
+ return colMap[idx];
+ }
+ void addColumn(colIdx idx, const QString& label)
+ {
+ colMap[idx] = Parent::addColumn(label);
+ colRevMap[colMap[idx]] = idx;
+ }
+ void removeColumn(colIdx idx)
+ {
+ int col = colMap[idx];
+ if (col >= 0) {
+ Parent::removeColumn(col);
+ colRevMap[col] = colMap[idx] = -1;
+ }
+ }
+ void setAllOpen(bool open);
+ void setParentMenu(void);
+
+ bool menuSkip(struct menu *);
+
+ template <class P>
+ void updateMenuList(P*, struct menu*);
+
+ bool updateAll;
+
+ QPixmap symbolYesPix, symbolModPix, symbolNoPix;
+ QPixmap choiceYesPix, choiceNoPix;
+ QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
+
+ bool showName, showRange, showData;
+ enum listMode mode;
+ enum optionMode optMode;
+ struct menu *rootEntry;
+ QColorGroup disabledColorGroup;
+ QColorGroup inactivedColorGroup;
+ Q3PopupMenu* headerPopup;
+
+private:
+ int colMap[colNr];
+ int colRevMap[colNr];
+};
+
+class ConfigItem : public Q3ListViewItem {
+ typedef class Q3ListViewItem Parent;
+public:
+ ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v)
+ : Parent(parent, after), menu(m), visible(v), goParent(false)
+ {
+ init();
+ }
+ ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
+ : Parent(parent, after), menu(m), visible(v), goParent(false)
+ {
+ init();
+ }
+ ConfigItem(Q3ListView *parent, ConfigItem *after, bool v)
+ : Parent(parent, after), menu(0), visible(v), goParent(true)
+ {
+ init();
+ }
+ ~ConfigItem(void);
+ void init(void);
+ void okRename(int col);
+ void updateMenu(void);
+ void testUpdateMenu(bool v);
+ ConfigList* listView() const
+ {
+ return (ConfigList*)Parent::listView();
+ }
+ ConfigItem* firstChild() const
+ {
+ return (ConfigItem *)Parent::firstChild();
+ }
+ ConfigItem* nextSibling() const
+ {
+ return (ConfigItem *)Parent::nextSibling();
+ }
+ void setText(colIdx idx, const QString& text)
+ {
+ Parent::setText(listView()->mapIdx(idx), text);
+ }
+ QString text(colIdx idx) const
+ {
+ return Parent::text(listView()->mapIdx(idx));
+ }
+ void setPixmap(colIdx idx, const QPixmap& pm)
+ {
+ Parent::setPixmap(listView()->mapIdx(idx), pm);
+ }
+ const QPixmap* pixmap(colIdx idx) const
+ {
+ return Parent::pixmap(listView()->mapIdx(idx));
+ }
+ void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
+
+ ConfigItem* nextItem;
+ struct menu *menu;
+ bool visible;
+ bool goParent;
+};
+
+class ConfigLineEdit : public QLineEdit {
+ Q_OBJECT
+ typedef class QLineEdit Parent;
+public:
+ ConfigLineEdit(ConfigView* parent);
+ ConfigView* parent(void) const
+ {
+ return (ConfigView*)Parent::parent();
+ }
+ void show(ConfigItem *i);
+ void keyPressEvent(QKeyEvent *e);
+
+public:
+ ConfigItem *item;
+};
+
+class ConfigView : public Q3VBox {
+ Q_OBJECT
+ typedef class Q3VBox Parent;
+public:
+ ConfigView(QWidget* parent, const char *name = 0);
+ ~ConfigView(void);
+ static void updateList(ConfigItem* item);
+ static void updateListAll(void);
+
+ bool showName(void) const { return list->showName; }
+ bool showRange(void) const { return list->showRange; }
+ bool showData(void) const { return list->showData; }
+public slots:
+ void setShowName(bool);
+ void setShowRange(bool);
+ void setShowData(bool);
+ void setOptionMode(QAction *);
+signals:
+ void showNameChanged(bool);
+ void showRangeChanged(bool);
+ void showDataChanged(bool);
+public:
+ ConfigList* list;
+ ConfigLineEdit* lineEdit;
+
+ static ConfigView* viewList;
+ ConfigView* nextView;
+
+ static QAction *showNormalAction;
+ static QAction *showAllAction;
+ static QAction *showPromptAction;
+};
+
+class ConfigInfoView : public Q3TextBrowser {
+ Q_OBJECT
+ typedef class Q3TextBrowser 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 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);
+ Q3PopupMenu* 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(ConfigMainWindow* 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 Q3MainWindow {
+ Q_OBJECT
+
+ static Q3Action *saveAction;
+ static void conf_changed(void);
+public:
+ ConfigMainWindow(void);
+public slots:
+ void changeMenu(struct menu *);
+ void setMenuLink(struct menu *);
+ void listFocusChanged(void);
+ void goBack(void);
+ void loadConfig(void);
+ bool saveConfig(void);
+ void saveConfigAs(void);
+ void searchConfig(void);
+ void showSingleView(void);
+ void showSplitView(void);
+ void showFullView(void);
+ void showIntro(void);
+ void showAbout(void);
+ void saveSettings(void);
+
+protected:
+ void closeEvent(QCloseEvent *e);
+
+ ConfigSearchWindow *searchWindow;
+ ConfigView *menuView;
+ ConfigList *menuList;
+ ConfigView *configView;
+ ConfigList *configList;
+ ConfigInfoView *helpText;
+ Q3ToolBar *toolBar;
+ Q3Action *backAction;
+ QSplitter* split1;
+ QSplitter* split2;
+};
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
new file mode 100644
index 0000000..3368939
--- /dev/null
+++ b/scripts/kconfig/streamline_config.pl
@@ -0,0 +1,634 @@
+#!/usr/bin/perl -w
+#
+# Copyright 2005-2009 - Steven Rostedt
+# Licensed under the terms of the GNU GPL License version 2
+#
+# It's simple enough to figure out how this works.
+# If not, then you can ask me at stripconfig at goodmis.org
+#
+# What it does?
+#
+# If you have installed a Linux kernel from a distribution
+# that turns on way too many modules than you need, and
+# you only want the modules you use, then this program
+# is perfect for you.
+#
+# It gives you the ability to turn off all the modules that are
+# not loaded on your system.
+#
+# Howto:
+#
+# 1. Boot up the kernel that you want to stream line the config on.
+# 2. Change directory to the directory holding the source of the
+# kernel that you just booted.
+# 3. Copy the configuraton file to this directory as .config
+# 4. Have all your devices that you need modules for connected and
+# operational (make sure that their corresponding modules are loaded)
+# 5. Run this script redirecting the output to some other file
+# like config_strip.
+# 6. Back up your old config (if you want too).
+# 7. copy the config_strip file to .config
+# 8. Run "make oldconfig"
+#
+# Now your kernel is ready to be built with only the modules that
+# are loaded.
+#
+# Here's what I did with my Debian distribution.
+#
+# cd /usr/src/linux-2.6.10
+# cp /boot/config-2.6.10-1-686-smp .config
+# ~/bin/streamline_config > config_strip
+# mv .config config_sav
+# mv config_strip .config
+# make oldconfig
+#
+use strict;
+use Getopt::Long;
+
+# set the environment variable LOCALMODCONFIG_DEBUG to get
+# debug output.
+my $debugprint = 0;
+$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG}));
+
+sub dprint {
+ return if (!$debugprint);
+ print STDERR @_;
+}
+
+my $config = ".config";
+
+my $uname = `uname -r`;
+chomp $uname;
+
+my @searchconfigs = (
+ {
+ "file" => ".config",
+ "exec" => "cat",
+ },
+ {
+ "file" => "/proc/config.gz",
+ "exec" => "zcat",
+ },
+ {
+ "file" => "/boot/config-$uname",
+ "exec" => "cat",
+ },
+ {
+ "file" => "/boot/vmlinuz-$uname",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+ {
+ "file" => "vmlinux",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+ {
+ "file" => "/lib/modules/$uname/kernel/kernel/configs.ko",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+ {
+ "file" => "kernel/configs.ko",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+ {
+ "file" => "kernel/configs.o",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+);
+
+sub read_config {
+ foreach my $conf (@searchconfigs) {
+ my $file = $conf->{"file"};
+
+ next if ( ! -f "$file");
+
+ if (defined($conf->{"test"})) {
+ `$conf->{"test"} $conf->{"file"} 2>/dev/null`;
+ next if ($?);
+ }
+
+ my $exec = $conf->{"exec"};
+
+ print STDERR "using config: '$file'\n";
+
+ open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file";
+ my @x = <$infile>;
+ close $infile;
+ return @x;
+ }
+ die "No config file found";
+}
+
+my @config_file = read_config;
+
+# Parse options
+my $localmodconfig = 0;
+my $localyesconfig = 0;
+
+GetOptions("localmodconfig" => \$localmodconfig,
+ "localyesconfig" => \$localyesconfig);
+
+# Get the build source and top level Kconfig file (passed in)
+my $ksource = ($ARGV[0] ? $ARGV[0] : '.');
+my $kconfig = $ARGV[1];
+my $lsmod_file = $ENV{'LSMOD'};
+
+my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
+chomp @makefiles;
+
+my %depends;
+my %selects;
+my %prompts;
+my %objects;
+my $var;
+my $iflevel = 0;
+my @ifdeps;
+
+# prevent recursion
+my %read_kconfigs;
+
+sub read_kconfig {
+ my ($kconfig) = @_;
+
+ my $state = "NONE";
+ my $config;
+ my @kconfigs;
+
+ my $cont = 0;
+ my $line;
+
+ my $source = "$ksource/$kconfig";
+ my $last_source = "";
+
+ # Check for any environment variables used
+ while ($source =~ /\$(\w+)/ && $last_source ne $source) {
+ my $env = $1;
+ $last_source = $source;
+ $source =~ s/\$$env/$ENV{$env}/;
+ }
+
+ open(my $kinfile, '<', $source) || die "Can't open $kconfig";
+ while (<$kinfile>) {
+ chomp;
+
+ # Make sure that lines ending with \ continue
+ if ($cont) {
+ $_ = $line . " " . $_;
+ }
+
+ if (s/\\$//) {
+ $cont = 1;
+ $line = $_;
+ next;
+ }
+
+ $cont = 0;
+
+ # collect any Kconfig sources
+ if (/^source\s*"(.*)"/) {
+ $kconfigs[$#kconfigs+1] = $1;
+ }
+
+ # configs found
+ if (/^\s*(menu)?config\s+(\S+)\s*$/) {
+ $state = "NEW";
+ $config = $2;
+
+ # Add depends for 'if' nesting
+ for (my $i = 0; $i < $iflevel; $i++) {
+ if ($i) {
+ $depends{$config} .= " " . $ifdeps[$i];
+ } else {
+ $depends{$config} = $ifdeps[$i];
+ }
+ $state = "DEP";
+ }
+
+ # collect the depends for the config
+ } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
+ $state = "DEP";
+ $depends{$config} = $1;
+ } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
+ $depends{$config} .= " " . $1;
+
+ # Get the configs that select this config
+ } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
+ my $conf = $1;
+ if (defined($selects{$conf})) {
+ $selects{$conf} .= " " . $config;
+ } else {
+ $selects{$conf} = $config;
+ }
+
+ # configs without prompts must be selected
+ } elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
+ # note if the config has a prompt
+ $prompts{$config} = 1;
+
+ # Check for if statements
+ } elsif (/^if\s+(.*\S)\s*$/) {
+ my $deps = $1;
+ # remove beginning and ending non text
+ $deps =~ s/^[^a-zA-Z0-9_]*//;
+ $deps =~ s/[^a-zA-Z0-9_]*$//;
+
+ my @deps = split /[^a-zA-Z0-9_]+/, $deps;
+
+ $ifdeps[$iflevel++] = join ':', @deps;
+
+ } elsif (/^endif/) {
+
+ $iflevel-- if ($iflevel);
+
+ # stop on "help"
+ } elsif (/^\s*help\s*$/) {
+ $state = "NONE";
+ }
+ }
+ close($kinfile);
+
+ # read in any configs that were found.
+ foreach my $kconfig (@kconfigs) {
+ if (!defined($read_kconfigs{$kconfig})) {
+ $read_kconfigs{$kconfig} = 1;
+ read_kconfig($kconfig);
+ }
+ }
+}
+
+if ($kconfig) {
+ read_kconfig($kconfig);
+}
+
+# Makefiles can use variables to define their dependencies
+sub convert_vars {
+ my ($line, %vars) = @_;
+
+ my $process = "";
+
+ while ($line =~ s/^(.*?)(\$\((.*?)\))//) {
+ my $start = $1;
+ my $variable = $2;
+ my $var = $3;
+
+ if (defined($vars{$var})) {
+ $process .= $start . $vars{$var};
+ } else {
+ $process .= $start . $variable;
+ }
+ }
+
+ $process .= $line;
+
+ return $process;
+}
+
+# Read all Makefiles to map the configs to the objects
+foreach my $makefile (@makefiles) {
+
+ my $line = "";
+ my %make_vars;
+
+ open(my $infile, '<', $makefile) || die "Can't open $makefile";
+ while (<$infile>) {
+ # if this line ends with a backslash, continue
+ chomp;
+ if (/^(.*)\\$/) {
+ $line .= $1;
+ next;
+ }
+
+ $line .= $_;
+ $_ = $line;
+ $line = "";
+
+ my $objs;
+
+ # Convert variables in a line (could define configs)
+ $_ = convert_vars($_, %make_vars);
+
+ # collect objects after obj-$(CONFIG_FOO_BAR)
+ if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
+ $var = $1;
+ $objs = $2;
+
+ # check if variables are set
+ } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) {
+ $make_vars{$1} = $2;
+ }
+ if (defined($objs)) {
+ foreach my $obj (split /\s+/,$objs) {
+ $obj =~ s/-/_/g;
+ if ($obj =~ /(.*)\.o$/) {
+ # Objects may be enabled by more than one config.
+ # Store configs in an array.
+ my @arr;
+
+ if (defined($objects{$1})) {
+ @arr = @{$objects{$1}};
+ }
+
+ $arr[$#arr+1] = $var;
+
+ # The objects have a hash mapping to a reference
+ # of an array of configs.
+ $objects{$1} = \@arr;
+ }
+ }
+ }
+ }
+ close($infile);
+}
+
+my %modules;
+my $linfile;
+
+if (defined($lsmod_file)) {
+ if ( ! -f $lsmod_file) {
+ if ( -f $ENV{'objtree'}."/".$lsmod_file) {
+ $lsmod_file = $ENV{'objtree'}."/".$lsmod_file;
+ } else {
+ die "$lsmod_file not found";
+ }
+ }
+
+ my $otype = ( -x $lsmod_file) ? '-|' : '<';
+ open($linfile, $otype, $lsmod_file);
+
+} else {
+
+ # see what modules are loaded on this system
+ my $lsmod;
+
+ foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
+ if ( -x "$dir/lsmod" ) {
+ $lsmod = "$dir/lsmod";
+ last;
+ }
+}
+ if (!defined($lsmod)) {
+ # try just the path
+ $lsmod = "lsmod";
+ }
+
+ open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod";
+}
+
+while (<$linfile>) {
+ next if (/^Module/); # Skip the first line.
+ if (/^(\S+)/) {
+ $modules{$1} = 1;
+ }
+}
+close ($linfile);
+
+# add to the configs hash all configs that are needed to enable
+# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o
+# where we know we need bar.o so we add FOO to the list.
+my %configs;
+foreach my $module (keys(%modules)) {
+ if (defined($objects{$module})) {
+ my @arr = @{$objects{$module}};
+ foreach my $conf (@arr) {
+ $configs{$conf} = $module;
+ dprint "$conf added by direct ($module)\n";
+ }
+ } else {
+ # Most likely, someone has a custom (binary?) module loaded.
+ print STDERR "$module config not found!!\n";
+ }
+}
+
+# Read the current config, and see what is enabled. We want to
+# ignore configs that we would not enable anyway.
+
+my %orig_configs;
+my $valid = "A-Za-z_0-9";
+
+foreach my $line (@config_file) {
+ $_ = $line;
+
+ if (/(CONFIG_[$valid]*)=(m|y)/) {
+ $orig_configs{$1} = $2;
+ }
+}
+
+my $repeat = 1;
+
+my $depconfig;
+
+#
+# Note, we do not care about operands (like: &&, ||, !) we want to add any
+# config that is in the depend list of another config. This script does
+# not enable configs that are not already enabled. If we come across a
+# config A that depends on !B, we can still add B to the list of depends
+# to keep on. If A was on in the original config, B would not have been
+# and B would not be turned on by this script.
+#
+sub parse_config_depends
+{
+ my ($p) = @_;
+
+ while ($p =~ /[$valid]/) {
+
+ if ($p =~ /^[^$valid]*([$valid]+)/) {
+ my $conf = "CONFIG_" . $1;
+
+ $p =~ s/^[^$valid]*[$valid]+//;
+
+ # We only need to process if the depend config is a module
+ if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq "m") {
+ next;
+ }
+
+ if (!defined($configs{$conf})) {
+ # We must make sure that this config has its
+ # dependencies met.
+ $repeat = 1; # do again
+ dprint "$conf selected by depend $depconfig\n";
+ $configs{$conf} = 1;
+ }
+ } else {
+ die "this should never happen";
+ }
+ }
+}
+
+# Select is treated a bit differently than depends. We call this
+# when a config has no prompt and requires another config to be
+# selected. We use to just select all configs that selected this
+# config, but found that that can balloon into enabling hundreds
+# of configs that we do not care about.
+#
+# The idea is we look at all the configs that select it. If one
+# is already in our list of configs to enable, then there's nothing
+# else to do. If there isn't, we pick the first config that was
+# enabled in the orignal config and use that.
+sub parse_config_selects
+{
+ my ($config, $p) = @_;
+
+ my $next_config;
+
+ while ($p =~ /[$valid]/) {
+
+ if ($p =~ /^[^$valid]*([$valid]+)/) {
+ my $conf = "CONFIG_" . $1;
+
+ $p =~ s/^[^$valid]*[$valid]+//;
+
+ # Make sure that this config exists in the current .config file
+ if (!defined($orig_configs{$conf})) {
+ dprint "$conf not set for $config select\n";
+ next;
+ }
+
+ # Check if something other than a module selects this config
+ if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") {
+ dprint "$conf (non module) selects config, we are good\n";
+ # we are good with this
+ return;
+ }
+ if (defined($configs{$conf})) {
+ dprint "$conf selects $config so we are good\n";
+ # A set config selects this config, we are good
+ return;
+ }
+ # Set this config to be selected
+ if (!defined($next_config)) {
+ $next_config = $conf;
+ }
+ } else {
+ die "this should never happen";
+ }
+ }
+
+ # If no possible config selected this, then something happened.
+ if (!defined($next_config)) {
+ print STDERR "WARNING: $config is required, but nothing in the\n";
+ print STDERR " current config selects it.\n";
+ return;
+ }
+
+ # If we are here, then we found no config that is set and
+ # selects this config. Repeat.
+ $repeat = 1;
+ # Make this config need to be selected
+ $configs{$next_config} = 1;
+ dprint "$next_config selected by select $config\n";
+}
+
+my %process_selects;
+
+# loop through all configs, select their dependencies.
+sub loop_depend {
+ $repeat = 1;
+
+ while ($repeat) {
+ $repeat = 0;
+
+ forloop:
+ foreach my $config (keys %configs) {
+
+ # If this config is not a module, we do not need to process it
+ if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") {
+ next forloop;
+ }
+
+ $config =~ s/^CONFIG_//;
+ $depconfig = $config;
+
+ if (defined($depends{$config})) {
+ # This config has dependencies. Make sure they are also included
+ parse_config_depends $depends{$config};
+ }
+
+ # If the config has no prompt, then we need to check if a config
+ # that is enabled selected it. Or if we need to enable one.
+ if (!defined($prompts{$config}) && defined($selects{$config})) {
+ $process_selects{$config} = 1;
+ }
+ }
+ }
+}
+
+sub loop_select {
+
+ foreach my $config (keys %process_selects) {
+ $config =~ s/^CONFIG_//;
+
+ dprint "Process select $config\n";
+
+ # config has no prompt and must be selected.
+ parse_config_selects $config, $selects{$config};
+ }
+}
+
+while ($repeat) {
+ # Get the first set of configs and their dependencies.
+ loop_depend;
+
+ $repeat = 0;
+
+ # Now we need to see if we have to check selects;
+ loop_select;
+}
+
+my %setconfigs;
+
+# Finally, read the .config file and turn off any module enabled that
+# we could not find a reason to keep enabled.
+foreach my $line (@config_file) {
+ $_ = $line;
+
+ if (/CONFIG_IKCONFIG/) {
+ if (/# CONFIG_IKCONFIG is not set/) {
+ # enable IKCONFIG at least as a module
+ print "CONFIG_IKCONFIG=m\n";
+ # don't ask about PROC
+ print "# CONFIG_IKCONFIG_PROC is not set\n";
+ } else {
+ print;
+ }
+ next;
+ }
+
+ if (/^(CONFIG.*)=(m|y)/) {
+ if (defined($configs{$1})) {
+ if ($localyesconfig) {
+ $setconfigs{$1} = 'y';
+ print "$1=y\n";
+ next;
+ } else {
+ $setconfigs{$1} = $2;
+ }
+ } elsif ($2 eq "m") {
+ print "# $1 is not set\n";
+ next;
+ }
+ }
+ print;
+}
+
+# Integrity check, make sure all modules that we want enabled do
+# indeed have their configs set.
+loop:
+foreach my $module (keys(%modules)) {
+ if (defined($objects{$module})) {
+ my @arr = @{$objects{$module}};
+ foreach my $conf (@arr) {
+ if (defined($setconfigs{$conf})) {
+ next loop;
+ }
+ }
+ print STDERR "module $module did not have configs";
+ foreach my $conf (@arr) {
+ print STDERR " " , $conf;
+ }
+ print STDERR "\n";
+ }
+}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
new file mode 100644
index 0000000..ecc5aa5
--- /dev/null
+++ b/scripts/kconfig/symbol.c
@@ -0,0 +1,1310 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+#include <sys/utsname.h>
+
+#include "lkc.h"
+
+struct symbol symbol_yes = {
+ .name = "y",
+ .curr = { "y", yes },
+ .flags = SYMBOL_CONST|SYMBOL_VALID,
+}, symbol_mod = {
+ .name = "m",
+ .curr = { "m", mod },
+ .flags = SYMBOL_CONST|SYMBOL_VALID,
+}, symbol_no = {
+ .name = "n",
+ .curr = { "n", no },
+ .flags = SYMBOL_CONST|SYMBOL_VALID,
+}, symbol_empty = {
+ .name = "",
+ .curr = { "", no },
+ .flags = SYMBOL_VALID,
+};
+
+struct symbol *sym_defconfig_list;
+struct symbol *modules_sym;
+tristate modules_val;
+
+struct expr *sym_env_list;
+
+static void sym_add_default(struct symbol *sym, const char *def)
+{
+ struct property *prop = prop_alloc(P_DEFAULT, sym);
+
+ prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
+}
+
+void sym_init(void)
+{
+ struct symbol *sym;
+ struct utsname uts;
+ static bool inited = false;
+
+ if (inited)
+ return;
+ inited = true;
+
+ uname(&uts);
+
+ sym = sym_lookup("UNAME_RELEASE", 0);
+ sym->type = S_STRING;
+ sym->flags |= SYMBOL_AUTO;
+ sym_add_default(sym, uts.release);
+}
+
+enum symbol_type sym_get_type(struct symbol *sym)
+{
+ enum symbol_type type = sym->type;
+
+ if (type == S_TRISTATE) {
+ if (sym_is_choice_value(sym) && sym->visible == yes)
+ type = S_BOOLEAN;
+ else if (modules_val == no)
+ type = S_BOOLEAN;
+ }
+ return type;
+}
+
+const char *sym_type_name(enum symbol_type type)
+{
+ switch (type) {
+ case S_BOOLEAN:
+ return "boolean";
+ case S_TRISTATE:
+ return "tristate";
+ case S_INT:
+ return "integer";
+ case S_HEX:
+ return "hex";
+ case S_STRING:
+ return "string";
+ case S_UNKNOWN:
+ return "unknown";
+ case S_OTHER:
+ break;
+ }
+ return "???";
+}
+
+struct property *sym_get_choice_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_choices(sym, prop)
+ return prop;
+ return NULL;
+}
+
+struct property *sym_get_env_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_properties(sym, prop, P_ENV)
+ return prop;
+ return NULL;
+}
+
+struct property *sym_get_default_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_defaults(sym, prop) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ if (prop->visible.tri != no)
+ return prop;
+ }
+ return NULL;
+}
+
+static struct property *sym_get_range_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_properties(sym, prop, P_RANGE) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ if (prop->visible.tri != no)
+ return prop;
+ }
+ return NULL;
+}
+
+static int sym_get_range_val(struct symbol *sym, int base)
+{
+ sym_calc_value(sym);
+ switch (sym->type) {
+ case S_INT:
+ base = 10;
+ break;
+ case S_HEX:
+ base = 16;
+ break;
+ default:
+ break;
+ }
+ return strtol(sym->curr.val, NULL, base);
+}
+
+static void sym_validate_range(struct symbol *sym)
+{
+ struct property *prop;
+ int base, val, val2;
+ char str[64];
+
+ switch (sym->type) {
+ case S_INT:
+ base = 10;
+ break;
+ case S_HEX:
+ base = 16;
+ break;
+ default:
+ return;
+ }
+ prop = sym_get_range_prop(sym);
+ if (!prop)
+ return;
+ val = strtol(sym->curr.val, NULL, base);
+ val2 = sym_get_range_val(prop->expr->left.sym, base);
+ if (val >= val2) {
+ val2 = sym_get_range_val(prop->expr->right.sym, base);
+ if (val <= val2)
+ return;
+ }
+ if (sym->type == S_INT)
+ sprintf(str, "%d", val2);
+ else
+ sprintf(str, "0x%x", val2);
+ sym->curr.val = strdup(str);
+}
+
+static void sym_calc_visibility(struct symbol *sym)
+{
+ struct property *prop;
+ tristate tri;
+
+ /* any prompt visible? */
+ tri = no;
+ for_all_prompts(sym, prop) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ tri = EXPR_OR(tri, prop->visible.tri);
+ }
+ if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
+ tri = yes;
+ if (sym->visible != tri) {
+ sym->visible = tri;
+ sym_set_changed(sym);
+ }
+ if (sym_is_choice_value(sym))
+ return;
+ /* defaulting to "yes" if no explicit "depends on" are given */
+ tri = yes;
+ if (sym->dir_dep.expr)
+ tri = expr_calc_value(sym->dir_dep.expr);
+ if (tri == mod)
+ tri = yes;
+ if (sym->dir_dep.tri != tri) {
+ sym->dir_dep.tri = tri;
+ sym_set_changed(sym);
+ }
+ tri = no;
+ if (sym->rev_dep.expr)
+ tri = expr_calc_value(sym->rev_dep.expr);
+ if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ tri = yes;
+ if (sym->rev_dep.tri != tri) {
+ sym->rev_dep.tri = tri;
+ sym_set_changed(sym);
+ }
+}
+
+/*
+ * Find the default symbol for a choice.
+ * First try the default values for the choice symbol
+ * Next locate the first visible choice value
+ * Return NULL if none was found
+ */
+struct symbol *sym_choice_default(struct symbol *sym)
+{
+ struct symbol *def_sym;
+ struct property *prop;
+ struct expr *e;
+
+ /* any of the defaults visible? */
+ for_all_defaults(sym, prop) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ if (prop->visible.tri == no)
+ continue;
+ def_sym = prop_get_symbol(prop);
+ if (def_sym->visible != no)
+ return def_sym;
+ }
+
+ /* just get the first visible value */
+ prop = sym_get_choice_prop(sym);
+ expr_list_for_each_sym(prop->expr, e, def_sym)
+ if (def_sym->visible != no)
+ return def_sym;
+
+ /* failed to locate any defaults */
+ return NULL;
+}
+
+static struct symbol *sym_calc_choice(struct symbol *sym)
+{
+ struct symbol *def_sym;
+ struct property *prop;
+ struct expr *e;
+ int flags;
+
+ /* first calculate all choice values' visibilities */
+ flags = sym->flags;
+ prop = sym_get_choice_prop(sym);
+ expr_list_for_each_sym(prop->expr, e, def_sym) {
+ sym_calc_visibility(def_sym);
+ if (def_sym->visible != no)
+ flags &= def_sym->flags;
+ }
+
+ sym->flags &= flags | ~SYMBOL_DEF_USER;
+
+ /* is the user choice visible? */
+ def_sym = sym->def[S_DEF_USER].val;
+ if (def_sym && def_sym->visible != no)
+ return def_sym;
+
+ def_sym = sym_choice_default(sym);
+
+ if (def_sym == NULL)
+ /* no choice? reset tristate value */
+ sym->curr.tri = no;
+
+ return def_sym;
+}
+
+void sym_calc_value(struct symbol *sym)
+{
+ struct symbol_value newval, oldval;
+ struct property *prop;
+ struct expr *e;
+
+ if (!sym)
+ return;
+
+ if (sym->flags & SYMBOL_VALID)
+ return;
+ sym->flags |= SYMBOL_VALID;
+
+ oldval = sym->curr;
+
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ newval = symbol_empty.curr;
+ break;
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ newval = symbol_no.curr;
+ break;
+ default:
+ sym->curr.val = sym->name;
+ sym->curr.tri = no;
+ return;
+ }
+ if (!sym_is_choice_value(sym))
+ sym->flags &= ~SYMBOL_WRITE;
+
+ sym_calc_visibility(sym);
+
+ /* set default if recursively called */
+ sym->curr = newval;
+
+ switch (sym_get_type(sym)) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (sym_is_choice_value(sym) && sym->visible == yes) {
+ prop = sym_get_choice_prop(sym);
+ newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
+ } else {
+ if (sym->visible != no) {
+ /* if the symbol is visible use the user value
+ * if available, otherwise try the default value
+ */
+ sym->flags |= SYMBOL_WRITE;
+ if (sym_has_value(sym)) {
+ newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
+ sym->visible);
+ goto calc_newval;
+ }
+ }
+ if (sym->rev_dep.tri != no)
+ sym->flags |= SYMBOL_WRITE;
+ if (!sym_is_choice(sym)) {
+ prop = sym_get_default_prop(sym);
+ if (prop) {
+ sym->flags |= SYMBOL_WRITE;
+ newval.tri = EXPR_AND(expr_calc_value(prop->expr),
+ prop->visible.tri);
+ }
+ }
+ calc_newval:
+ if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
+ struct expr *e;
+ e = expr_simplify_unmet_dep(sym->rev_dep.expr,
+ sym->dir_dep.expr);
+ fprintf(stderr, "warning: (");
+ expr_fprint(e, stderr);
+ fprintf(stderr, ") selects %s which has unmet direct dependencies (",
+ sym->name);
+ expr_fprint(sym->dir_dep.expr, stderr);
+ fprintf(stderr, ")\n");
+ expr_free(e);
+ }
+ newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
+ }
+ if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ newval.tri = yes;
+ break;
+ case S_STRING:
+ case S_HEX:
+ case S_INT:
+ if (sym->visible != no) {
+ sym->flags |= SYMBOL_WRITE;
+ if (sym_has_value(sym)) {
+ newval.val = sym->def[S_DEF_USER].val;
+ break;
+ }
+ }
+ prop = sym_get_default_prop(sym);
+ if (prop) {
+ struct symbol *ds = prop_get_symbol(prop);
+ if (ds) {
+ sym->flags |= SYMBOL_WRITE;
+ sym_calc_value(ds);
+ newval.val = ds->curr.val;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+
+ sym->curr = newval;
+ if (sym_is_choice(sym) && newval.tri == yes)
+ sym->curr.val = sym_calc_choice(sym);
+ sym_validate_range(sym);
+
+ if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
+ sym_set_changed(sym);
+ if (modules_sym == sym) {
+ sym_set_all_changed();
+ modules_val = modules_sym->curr.tri;
+ }
+ }
+
+ if (sym_is_choice(sym)) {
+ struct symbol *choice_sym;
+
+ prop = sym_get_choice_prop(sym);
+ expr_list_for_each_sym(prop->expr, e, choice_sym) {
+ if ((sym->flags & SYMBOL_WRITE) &&
+ choice_sym->visible != no)
+ choice_sym->flags |= SYMBOL_WRITE;
+ if (sym->flags & SYMBOL_CHANGED)
+ sym_set_changed(choice_sym);
+ }
+ }
+
+ if (sym->flags & SYMBOL_AUTO)
+ sym->flags &= ~SYMBOL_WRITE;
+}
+
+void sym_clear_all_valid(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym)
+ sym->flags &= ~SYMBOL_VALID;
+ sym_add_change_count(1);
+ if (modules_sym)
+ sym_calc_value(modules_sym);
+}
+
+void sym_set_changed(struct symbol *sym)
+{
+ struct property *prop;
+
+ sym->flags |= SYMBOL_CHANGED;
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->menu)
+ prop->menu->flags |= MENU_CHANGED;
+ }
+}
+
+void sym_set_all_changed(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym)
+ sym_set_changed(sym);
+}
+
+bool sym_tristate_within_range(struct symbol *sym, tristate val)
+{
+ int type = sym_get_type(sym);
+
+ if (sym->visible == no)
+ return false;
+
+ if (type != S_BOOLEAN && type != S_TRISTATE)
+ return false;
+
+ if (type == S_BOOLEAN && val == mod)
+ return false;
+ if (sym->visible <= sym->rev_dep.tri)
+ return false;
+ if (sym_is_choice_value(sym) && sym->visible == yes)
+ return val == yes;
+ return val >= sym->rev_dep.tri && val <= sym->visible;
+}
+
+bool sym_set_tristate_value(struct symbol *sym, tristate val)
+{
+ tristate oldval = sym_get_tristate_value(sym);
+
+ if (oldval != val && !sym_tristate_within_range(sym, val))
+ return false;
+
+ if (!(sym->flags & SYMBOL_DEF_USER)) {
+ sym->flags |= SYMBOL_DEF_USER;
+ sym_set_changed(sym);
+ }
+ /*
+ * setting a choice value also resets the new flag of the choice
+ * symbol and all other choice values.
+ */
+ if (sym_is_choice_value(sym) && val == yes) {
+ struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
+ struct property *prop;
+ struct expr *e;
+
+ cs->def[S_DEF_USER].val = sym;
+ cs->flags |= SYMBOL_DEF_USER;
+ prop = sym_get_choice_prop(cs);
+ for (e = prop->expr; e; e = e->left.expr) {
+ if (e->right.sym->visible != no)
+ e->right.sym->flags |= SYMBOL_DEF_USER;
+ }
+ }
+
+ sym->def[S_DEF_USER].tri = val;
+ if (oldval != val)
+ sym_clear_all_valid();
+
+ return true;
+}
+
+tristate sym_toggle_tristate_value(struct symbol *sym)
+{
+ tristate oldval, newval;
+
+ oldval = newval = sym_get_tristate_value(sym);
+ do {
+ switch (newval) {
+ case no:
+ newval = mod;
+ break;
+ case mod:
+ newval = yes;
+ break;
+ case yes:
+ newval = no;
+ break;
+ }
+ if (sym_set_tristate_value(sym, newval))
+ break;
+ } while (oldval != newval);
+ return newval;
+}
+
+bool sym_string_valid(struct symbol *sym, const char *str)
+{
+ signed char ch;
+
+ switch (sym->type) {
+ case S_STRING:
+ return true;
+ case S_INT:
+ ch = *str++;
+ if (ch == '-')
+ ch = *str++;
+ if (!isdigit(ch))
+ return false;
+ if (ch == '0' && *str != 0)
+ return false;
+ while ((ch = *str++)) {
+ if (!isdigit(ch))
+ return false;
+ }
+ return true;
+ case S_HEX:
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ str += 2;
+ ch = *str++;
+ do {
+ if (!isxdigit(ch))
+ return false;
+ } while ((ch = *str++));
+ return true;
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (str[0]) {
+ case 'y': case 'Y':
+ case 'm': case 'M':
+ case 'n': case 'N':
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+bool sym_string_within_range(struct symbol *sym, const char *str)
+{
+ struct property *prop;
+ int val;
+
+ switch (sym->type) {
+ case S_STRING:
+ return sym_string_valid(sym, str);
+ case S_INT:
+ if (!sym_string_valid(sym, str))
+ return false;
+ prop = sym_get_range_prop(sym);
+ if (!prop)
+ return true;
+ val = strtol(str, NULL, 10);
+ return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
+ val <= sym_get_range_val(prop->expr->right.sym, 10);
+ case S_HEX:
+ if (!sym_string_valid(sym, str))
+ return false;
+ prop = sym_get_range_prop(sym);
+ if (!prop)
+ return true;
+ val = strtol(str, NULL, 16);
+ return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
+ val <= sym_get_range_val(prop->expr->right.sym, 16);
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (str[0]) {
+ case 'y': case 'Y':
+ return sym_tristate_within_range(sym, yes);
+ case 'm': case 'M':
+ return sym_tristate_within_range(sym, mod);
+ case 'n': case 'N':
+ return sym_tristate_within_range(sym, no);
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+bool sym_set_string_value(struct symbol *sym, const char *newval)
+{
+ const char *oldval;
+ char *val;
+ int size;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (newval[0]) {
+ case 'y': case 'Y':
+ return sym_set_tristate_value(sym, yes);
+ case 'm': case 'M':
+ return sym_set_tristate_value(sym, mod);
+ case 'n': case 'N':
+ return sym_set_tristate_value(sym, no);
+ }
+ return false;
+ default:
+ ;
+ }
+
+ if (!sym_string_within_range(sym, newval))
+ return false;
+
+ if (!(sym->flags & SYMBOL_DEF_USER)) {
+ sym->flags |= SYMBOL_DEF_USER;
+ sym_set_changed(sym);
+ }
+
+ 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->def[S_DEF_USER].val = val = xmalloc(size);
+ *val++ = '0';
+ *val++ = 'x';
+ } else if (!oldval || strcmp(oldval, newval))
+ sym->def[S_DEF_USER].val = val = xmalloc(size);
+ else
+ return true;
+
+ strcpy(val, newval);
+ free((void *)oldval);
+ sym_clear_all_valid();
+
+ return true;
+}
+
+/*
+ * Find the default value associated to a symbol.
+ * For tristate symbol handle the modules=n case
+ * in which case "m" becomes "y".
+ * If the symbol does not have any default then fallback
+ * to the fixed default values.
+ */
+const char *sym_get_string_default(struct symbol *sym)
+{
+ struct property *prop;
+ struct symbol *ds;
+ const char *str;
+ tristate val;
+
+ sym_calc_visibility(sym);
+ sym_calc_value(modules_sym);
+ val = symbol_no.curr.tri;
+ str = symbol_empty.curr.val;
+
+ /* If symbol has a default value look it up */
+ prop = sym_get_default_prop(sym);
+ if (prop != NULL) {
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ /* The visibility may limit the value from yes => mod */
+ val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
+ break;
+ default:
+ /*
+ * The following fails to handle the situation
+ * where a default value is further limited by
+ * the valid range.
+ */
+ ds = prop_get_symbol(prop);
+ if (ds != NULL) {
+ sym_calc_value(ds);
+ str = (const char *)ds->curr.val;
+ }
+ }
+ }
+
+ /* Handle select statements */
+ val = EXPR_OR(val, sym->rev_dep.tri);
+
+ /* transpose mod to yes if modules are not enabled */
+ if (val == mod)
+ if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
+ val = yes;
+
+ /* transpose mod to yes if type is bool */
+ if (sym->type == S_BOOLEAN && val == mod)
+ val = yes;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (val) {
+ case no: return "n";
+ case mod: return "m";
+ case yes: return "y";
+ }
+ case S_INT:
+ case S_HEX:
+ return str;
+ case S_STRING:
+ return str;
+ case S_OTHER:
+ case S_UNKNOWN:
+ break;
+ }
+ return "";
+}
+
+const char *sym_get_string_value(struct symbol *sym)
+{
+ tristate val;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ val = sym_get_tristate_value(sym);
+ switch (val) {
+ case no:
+ return "n";
+ case mod:
+ sym_calc_value(modules_sym);
+ return (modules_sym->curr.tri == no) ? "n" : "m";
+ case yes:
+ return "y";
+ }
+ break;
+ default:
+ ;
+ }
+ return (const char *)sym->curr.val;
+}
+
+bool sym_is_changable(struct symbol *sym)
+{
+ return sym->visible > sym->rev_dep.tri;
+}
+
+static unsigned strhash(const char *s)
+{
+ /* fnv32 hash */
+ unsigned hash = 2166136261U;
+ for (; *s; s++)
+ hash = (hash ^ *s) * 0x01000193;
+ return hash;
+}
+
+struct symbol *sym_lookup(const char *name, int flags)
+{
+ struct symbol *symbol;
+ char *new_name;
+ int hash;
+
+ if (name) {
+ if (name[0] && !name[1]) {
+ switch (name[0]) {
+ case 'y': return &symbol_yes;
+ case 'm': return &symbol_mod;
+ case 'n': return &symbol_no;
+ }
+ }
+ hash = strhash(name) % SYMBOL_HASHSIZE;
+
+ for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ if (symbol->name &&
+ !strcmp(symbol->name, name) &&
+ (flags ? symbol->flags & flags
+ : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
+ return symbol;
+ }
+ new_name = strdup(name);
+ } else {
+ new_name = NULL;
+ hash = 0;
+ }
+
+ symbol = xmalloc(sizeof(*symbol));
+ memset(symbol, 0, sizeof(*symbol));
+ symbol->name = new_name;
+ symbol->type = S_UNKNOWN;
+ symbol->flags |= flags;
+
+ symbol->next = symbol_hash[hash];
+ symbol_hash[hash] = symbol;
+
+ return symbol;
+}
+
+struct symbol *sym_find(const char *name)
+{
+ struct symbol *symbol = NULL;
+ int hash = 0;
+
+ if (!name)
+ return NULL;
+
+ if (name[0] && !name[1]) {
+ switch (name[0]) {
+ case 'y': return &symbol_yes;
+ case 'm': return &symbol_mod;
+ case 'n': return &symbol_no;
+ }
+ }
+ hash = strhash(name) % SYMBOL_HASHSIZE;
+
+ for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ if (symbol->name &&
+ !strcmp(symbol->name, name) &&
+ !(symbol->flags & SYMBOL_CONST))
+ break;
+ }
+
+ return symbol;
+}
+
+/*
+ * Expand symbol's names embedded in the string given in argument. Symbols'
+ * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
+ * the empty string.
+ */
+const char *sym_expand_string_value(const char *in)
+{
+ const char *src;
+ char *res;
+ size_t reslen;
+
+ reslen = strlen(in) + 1;
+ res = xmalloc(reslen);
+ res[0] = '\0';
+
+ while ((src = strchr(in, '$'))) {
+ char *p, name[SYMBOL_MAXLENGTH];
+ const char *symval = "";
+ struct symbol *sym;
+ size_t newlen;
+
+ strncat(res, in, src - in);
+ src++;
+
+ p = name;
+ while (isalnum(*src) || *src == '_')
+ *p++ = *src++;
+ *p = '\0';
+
+ sym = sym_find(name);
+ if (sym != NULL) {
+ sym_calc_value(sym);
+ symval = sym_get_string_value(sym);
+ }
+
+ newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
+ if (newlen > reslen) {
+ reslen = newlen;
+ res = realloc(res, reslen);
+ }
+
+ strcat(res, symval);
+ in = src;
+ }
+ strcat(res, in);
+
+ return res;
+}
+
+const char *sym_escape_string_value(const char *in)
+{
+ const char *p;
+ size_t reslen;
+ char *res;
+ size_t l;
+
+ reslen = strlen(in) + strlen("\"\"") + 1;
+
+ p = in;
+ for (;;) {
+ l = strcspn(p, "\"\\");
+ p += l;
+
+ if (p[0] == '\0')
+ break;
+
+ reslen++;
+ p++;
+ }
+
+ res = xmalloc(reslen);
+ res[0] = '\0';
+
+ strcat(res, "\"");
+
+ p = in;
+ for (;;) {
+ l = strcspn(p, "\"\\");
+ strncat(res, p, l);
+ p += l;
+
+ if (p[0] == '\0')
+ break;
+
+ strcat(res, "\\");
+ strncat(res, p++, 1);
+ }
+
+ strcat(res, "\"");
+ return res;
+}
+
+struct symbol **sym_re_search(const char *pattern)
+{
+ struct symbol *sym, **sym_arr = NULL;
+ int i, cnt, size;
+ regex_t re;
+
+ cnt = size = 0;
+ /* Skip if empty */
+ if (strlen(pattern) == 0)
+ return NULL;
+ if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
+ return NULL;
+
+ for_all_symbols(i, sym) {
+ if (sym->flags & SYMBOL_CONST || !sym->name)
+ continue;
+ if (regexec(&re, sym->name, 0, NULL, 0))
+ continue;
+ if (cnt + 1 >= size) {
+ void *tmp = sym_arr;
+ size += 16;
+ sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
+ if (!sym_arr) {
+ free(tmp);
+ return NULL;
+ }
+ }
+ sym_calc_value(sym);
+ sym_arr[cnt++] = sym;
+ }
+ if (sym_arr)
+ sym_arr[cnt] = NULL;
+ regfree(&re);
+
+ return sym_arr;
+}
+
+/*
+ * When we check for recursive dependencies we use a stack to save
+ * current state so we can print out relevant info to user.
+ * The entries are located on the call stack so no need to free memory.
+ * Note inser() remove() must always match to properly clear the stack.
+ */
+static struct dep_stack {
+ struct dep_stack *prev, *next;
+ struct symbol *sym;
+ struct property *prop;
+ struct expr *expr;
+} *check_top;
+
+static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
+{
+ memset(stack, 0, sizeof(*stack));
+ if (check_top)
+ check_top->next = stack;
+ stack->prev = check_top;
+ stack->sym = sym;
+ check_top = stack;
+}
+
+static void dep_stack_remove(void)
+{
+ check_top = check_top->prev;
+ if (check_top)
+ check_top->next = NULL;
+}
+
+/*
+ * Called when we have detected a recursive dependency.
+ * check_top point to the top of the stact so we use
+ * the ->prev pointer to locate the bottom of the stack.
+ */
+static void sym_check_print_recursive(struct symbol *last_sym)
+{
+ struct dep_stack *stack;
+ struct symbol *sym, *next_sym;
+ struct menu *menu = NULL;
+ struct property *prop;
+ struct dep_stack cv_stack;
+
+ if (sym_is_choice_value(last_sym)) {
+ dep_stack_insert(&cv_stack, last_sym);
+ last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
+ }
+
+ for (stack = check_top; stack != NULL; stack = stack->prev)
+ if (stack->sym == last_sym)
+ break;
+ if (!stack) {
+ fprintf(stderr, "unexpected recursive dependency error\n");
+ return;
+ }
+
+ for (; stack; stack = stack->next) {
+ sym = stack->sym;
+ next_sym = stack->next ? stack->next->sym : last_sym;
+ prop = stack->prop;
+ if (prop == NULL)
+ prop = stack->sym->prop;
+
+ /* for choice values find the menu entry (used below) */
+ if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
+ for (prop = sym->prop; prop; prop = prop->next) {
+ menu = prop->menu;
+ if (prop->menu)
+ break;
+ }
+ }
+ if (stack->sym == last_sym)
+ fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
+ prop->file->name, prop->lineno);
+ if (stack->expr) {
+ fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
+ prop->file->name, prop->lineno,
+ sym->name ? sym->name : "<choice>",
+ prop_get_type_name(prop->type),
+ next_sym->name ? next_sym->name : "<choice>");
+ } else if (stack->prop) {
+ fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
+ prop->file->name, prop->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ } else if (sym_is_choice(sym)) {
+ fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
+ menu->file->name, menu->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ } else if (sym_is_choice_value(sym)) {
+ fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
+ menu->file->name, menu->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ } else {
+ fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
+ prop->file->name, prop->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ }
+ }
+
+ if (check_top == &cv_stack)
+ dep_stack_remove();
+}
+
+static struct symbol *sym_check_expr_deps(struct expr *e)
+{
+ struct symbol *sym;
+
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_OR:
+ case E_AND:
+ sym = sym_check_expr_deps(e->left.expr);
+ if (sym)
+ return sym;
+ return sym_check_expr_deps(e->right.expr);
+ case E_NOT:
+ return sym_check_expr_deps(e->left.expr);
+ case E_EQUAL:
+ case E_UNEQUAL:
+ sym = sym_check_deps(e->left.sym);
+ if (sym)
+ return sym;
+ return sym_check_deps(e->right.sym);
+ case E_SYMBOL:
+ return sym_check_deps(e->left.sym);
+ default:
+ break;
+ }
+ printf("Oops! How to check %d?\n", e->type);
+ return NULL;
+}
+
+/* return NULL when dependencies are OK */
+static struct symbol *sym_check_sym_deps(struct symbol *sym)
+{
+ struct symbol *sym2;
+ struct property *prop;
+ struct dep_stack stack;
+
+ dep_stack_insert(&stack, sym);
+
+ sym2 = sym_check_expr_deps(sym->rev_dep.expr);
+ if (sym2)
+ goto out;
+
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->type == P_CHOICE || prop->type == P_SELECT)
+ continue;
+ stack.prop = prop;
+ sym2 = sym_check_expr_deps(prop->visible.expr);
+ if (sym2)
+ break;
+ if (prop->type != P_DEFAULT || sym_is_choice(sym))
+ continue;
+ stack.expr = prop->expr;
+ sym2 = sym_check_expr_deps(prop->expr);
+ if (sym2)
+ break;
+ stack.expr = NULL;
+ }
+
+out:
+ dep_stack_remove();
+
+ return sym2;
+}
+
+static struct symbol *sym_check_choice_deps(struct symbol *choice)
+{
+ struct symbol *sym, *sym2;
+ struct property *prop;
+ struct expr *e;
+ struct dep_stack stack;
+
+ dep_stack_insert(&stack, choice);
+
+ prop = sym_get_choice_prop(choice);
+ expr_list_for_each_sym(prop->expr, e, sym)
+ sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+
+ choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+ sym2 = sym_check_sym_deps(choice);
+ choice->flags &= ~SYMBOL_CHECK;
+ if (sym2)
+ goto out;
+
+ expr_list_for_each_sym(prop->expr, e, sym) {
+ sym2 = sym_check_sym_deps(sym);
+ if (sym2)
+ break;
+ }
+out:
+ expr_list_for_each_sym(prop->expr, e, sym)
+ sym->flags &= ~SYMBOL_CHECK;
+
+ if (sym2 && sym_is_choice_value(sym2) &&
+ prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
+ sym2 = choice;
+
+ dep_stack_remove();
+
+ return sym2;
+}
+
+struct symbol *sym_check_deps(struct symbol *sym)
+{
+ struct symbol *sym2;
+ struct property *prop;
+
+ if (sym->flags & SYMBOL_CHECK) {
+ sym_check_print_recursive(sym);
+ return sym;
+ }
+ if (sym->flags & SYMBOL_CHECKED)
+ return NULL;
+
+ if (sym_is_choice_value(sym)) {
+ struct dep_stack stack;
+
+ /* for choice groups start the check with main choice symbol */
+ dep_stack_insert(&stack, sym);
+ prop = sym_get_choice_prop(sym);
+ sym2 = sym_check_deps(prop_get_symbol(prop));
+ dep_stack_remove();
+ } else if (sym_is_choice(sym)) {
+ sym2 = sym_check_choice_deps(sym);
+ } else {
+ sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+ sym2 = sym_check_sym_deps(sym);
+ sym->flags &= ~SYMBOL_CHECK;
+ }
+
+ if (sym2 && sym2 == sym)
+ sym2 = NULL;
+
+ return sym2;
+}
+
+struct property *prop_alloc(enum prop_type type, struct symbol *sym)
+{
+ struct property *prop;
+ struct property **propp;
+
+ prop = xmalloc(sizeof(*prop));
+ memset(prop, 0, sizeof(*prop));
+ prop->type = type;
+ prop->sym = sym;
+ prop->file = current_file;
+ prop->lineno = zconf_lineno();
+
+ /* append property to the prop list of symbol */
+ if (sym) {
+ for (propp = &sym->prop; *propp; propp = &(*propp)->next)
+ ;
+ *propp = prop;
+ }
+
+ return prop;
+}
+
+struct symbol *prop_get_symbol(struct property *prop)
+{
+ if (prop->expr && (prop->expr->type == E_SYMBOL ||
+ prop->expr->type == E_LIST))
+ return prop->expr->left.sym;
+ return NULL;
+}
+
+const char *prop_get_type_name(enum prop_type type)
+{
+ switch (type) {
+ case P_PROMPT:
+ return "prompt";
+ case P_ENV:
+ return "env";
+ case P_COMMENT:
+ return "comment";
+ case P_MENU:
+ return "menu";
+ case P_DEFAULT:
+ return "default";
+ case P_CHOICE:
+ return "choice";
+ case P_SELECT:
+ return "select";
+ case P_RANGE:
+ return "range";
+ case P_SYMBOL:
+ return "symbol";
+ case P_UNKNOWN:
+ break;
+ }
+ return "unknown";
+}
+
+static void prop_add_env(const char *env)
+{
+ struct symbol *sym, *sym2;
+ struct property *prop;
+ char *p;
+
+ sym = current_entry->sym;
+ sym->flags |= SYMBOL_AUTO;
+ for_all_properties(sym, prop, P_ENV) {
+ sym2 = prop_get_symbol(prop);
+ if (strcmp(sym2->name, env))
+ menu_warn(current_entry, "redefining environment symbol from %s",
+ sym2->name);
+ return;
+ }
+
+ prop = prop_alloc(P_ENV, sym);
+ prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
+
+ sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
+ sym_env_list->right.sym = sym;
+
+ p = getenv(env);
+ if (p)
+ sym_add_default(sym, p);
+ else
+ menu_warn(current_entry, "environment variable %s undefined", env);
+}
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
new file mode 100644
index 0000000..6e7fbf1
--- /dev/null
+++ b/scripts/kconfig/util.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2002-2005 Roman Zippel <zippel at linux-m68k.org>
+ * Copyright (C) 2002-2005 Sam Ravnborg <sam at ravnborg.org>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lkc.h"
+
+/* file already present in list? If not add it */
+struct file *file_lookup(const char *name)
+{
+ struct file *file;
+ const char *file_name = sym_expand_string_value(name);
+
+ for (file = file_list; file; file = file->next) {
+ if (!strcmp(name, file->name)) {
+ free((void *)file_name);
+ return file;
+ }
+ }
+
+ file = xmalloc(sizeof(*file));
+ memset(file, 0, sizeof(*file));
+ file->name = file_name;
+ file->next = file_list;
+ file_list = file;
+ return file;
+}
+
+/* write a dependency file as used by kbuild to track dependencies */
+int file_write_dep(const char *name)
+{
+ struct symbol *sym, *env_sym;
+ struct expr *e;
+ struct file *file;
+ FILE *out;
+
+ if (!name)
+ name = ".kconfig.d";
+ out = fopen("..config.tmp", "w");
+ if (!out)
+ return 1;
+ fprintf(out, "deps_config := \\\n");
+ for (file = file_list; file; file = file->next) {
+ if (file->next)
+ fprintf(out, "\t%s \\\n", file->name);
+ else
+ fprintf(out, "\t%s\n", file->name);
+ }
+ fprintf(out, "\n%s: \\\n"
+ "\t$(deps_config)\n\n", conf_get_autoconfig_name());
+
+ expr_list_for_each_sym(sym_env_list, e, sym) {
+ struct property *prop;
+ const char *value;
+
+ prop = sym_get_env_prop(sym);
+ env_sym = prop_get_symbol(prop);
+ if (!env_sym)
+ continue;
+ value = getenv(env_sym->name);
+ if (!value)
+ value = "";
+ fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value);
+ fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name());
+ fprintf(out, "endif\n");
+ }
+
+ fprintf(out, "\n$(deps_config): ;\n");
+ fclose(out);
+ rename("..config.tmp", name);
+ return 0;
+}
+
+
+/* Allocate initial growable string */
+struct gstr str_new(void)
+{
+ struct gstr gs;
+ gs.s = xmalloc(sizeof(char) * 64);
+ gs.len = 64;
+ gs.max_width = 0;
+ strcpy(gs.s, "\0");
+ return gs;
+}
+
+/* Allocate and assign growable string */
+struct gstr str_assign(const char *s)
+{
+ struct gstr gs;
+ gs.s = strdup(s);
+ gs.len = strlen(s) + 1;
+ gs.max_width = 0;
+ return gs;
+}
+
+/* Free storage for growable string */
+void str_free(struct gstr *gs)
+{
+ if (gs->s)
+ free(gs->s);
+ gs->s = NULL;
+ gs->len = 0;
+}
+
+/* Append to growable string */
+void str_append(struct gstr *gs, const char *s)
+{
+ size_t l;
+ if (s) {
+ l = strlen(gs->s) + strlen(s) + 1;
+ if (l > gs->len) {
+ gs->s = realloc(gs->s, l);
+ gs->len = l;
+ }
+ strcat(gs->s, s);
+ }
+}
+
+/* Append printf formatted string to growable string */
+void str_printf(struct gstr *gs, const char *fmt, ...)
+{
+ va_list ap;
+ char s[10000]; /* big enough... */
+ va_start(ap, fmt);
+ vsnprintf(s, sizeof(s), fmt, ap);
+ str_append(gs, s);
+ va_end(ap);
+}
+
+/* Retrieve value of growable string */
+const char *str_get(struct gstr *gs)
+{
+ return gs->s;
+}
+
+void *xmalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (p)
+ return p;
+ fprintf(stderr, "Out of memory.\n");
+ exit(1);
+}
+
+void *xcalloc(size_t nmemb, size_t size)
+{
+ void *p = calloc(nmemb, size);
+ if (p)
+ return p;
+ fprintf(stderr, "Out of memory.\n");
+ exit(1);
+}
+
+
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
new file mode 100644
index 0000000..f14ab41
--- /dev/null
+++ b/scripts/kconfig/zconf.gperf
@@ -0,0 +1,47 @@
+%language=ANSI-C
+%define hash-function-name kconf_id_hash
+%define lookup-function-name kconf_id_lookup
+%define string-pool-name kconf_id_strings
+%compare-strncmp
+%enum
+%pic
+%struct-type
+
+struct kconf_id;
+
+static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
+
+%%
+mainmenu, T_MAINMENU, TF_COMMAND
+menu, T_MENU, TF_COMMAND
+endmenu, T_ENDMENU, TF_COMMAND
+source, T_SOURCE, TF_COMMAND
+choice, T_CHOICE, TF_COMMAND
+endchoice, T_ENDCHOICE, TF_COMMAND
+comment, T_COMMENT, TF_COMMAND
+config, T_CONFIG, TF_COMMAND
+menuconfig, T_MENUCONFIG, TF_COMMAND
+help, T_HELP, TF_COMMAND
+if, T_IF, TF_COMMAND|TF_PARAM
+endif, T_ENDIF, TF_COMMAND
+depends, T_DEPENDS, TF_COMMAND
+optional, T_OPTIONAL, TF_COMMAND
+default, T_DEFAULT, TF_COMMAND, S_UNKNOWN
+prompt, T_PROMPT, TF_COMMAND
+tristate, T_TYPE, TF_COMMAND, S_TRISTATE
+def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE
+bool, T_TYPE, TF_COMMAND, S_BOOLEAN
+boolean, T_TYPE, TF_COMMAND, S_BOOLEAN
+def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN
+int, T_TYPE, TF_COMMAND, S_INT
+hex, T_TYPE, TF_COMMAND, S_HEX
+string, T_TYPE, TF_COMMAND, S_STRING
+select, T_SELECT, TF_COMMAND
+range, T_RANGE, TF_COMMAND
+visible, T_VISIBLE, 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
+env, T_OPT_ENV, TF_OPTION
+%%
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
new file mode 100644
index 0000000..40df000
--- /dev/null
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -0,0 +1,286 @@
+/* ANSI-C code produced by gperf version 3.0.4 */
+/* Command-line: gperf -t --output-file scripts/kconfig/zconf.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/kconfig/zconf.gperf */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf at gnu.org>."
+#endif
+
+#line 10 "scripts/kconfig/zconf.gperf"
+struct kconf_id;
+
+static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
+/* maximum key range = 71, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+kconf_id_hash (register const char *str, register unsigned int len)
+{
+ static const unsigned char asso_values[] =
+ {
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 25, 25,
+ 0, 0, 0, 5, 0, 0, 73, 73, 5, 0,
+ 10, 5, 45, 73, 20, 20, 0, 15, 15, 73,
+ 20, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[2]];
+ /*FALLTHROUGH*/
+ case 2:
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval + asso_values[(unsigned char)str[len - 1]];
+}
+
+struct kconf_id_strings_t
+ {
+ char kconf_id_strings_str2[sizeof("if")];
+ char kconf_id_strings_str3[sizeof("int")];
+ char kconf_id_strings_str5[sizeof("endif")];
+ char kconf_id_strings_str7[sizeof("default")];
+ char kconf_id_strings_str8[sizeof("tristate")];
+ char kconf_id_strings_str9[sizeof("endchoice")];
+ char kconf_id_strings_str12[sizeof("def_tristate")];
+ char kconf_id_strings_str13[sizeof("def_bool")];
+ char kconf_id_strings_str14[sizeof("defconfig_list")];
+ char kconf_id_strings_str17[sizeof("on")];
+ char kconf_id_strings_str18[sizeof("optional")];
+ char kconf_id_strings_str21[sizeof("option")];
+ char kconf_id_strings_str22[sizeof("endmenu")];
+ char kconf_id_strings_str23[sizeof("mainmenu")];
+ char kconf_id_strings_str25[sizeof("menuconfig")];
+ char kconf_id_strings_str27[sizeof("modules")];
+ char kconf_id_strings_str29[sizeof("menu")];
+ char kconf_id_strings_str31[sizeof("select")];
+ char kconf_id_strings_str32[sizeof("comment")];
+ char kconf_id_strings_str33[sizeof("env")];
+ char kconf_id_strings_str35[sizeof("range")];
+ char kconf_id_strings_str36[sizeof("choice")];
+ char kconf_id_strings_str39[sizeof("bool")];
+ char kconf_id_strings_str41[sizeof("source")];
+ char kconf_id_strings_str42[sizeof("visible")];
+ char kconf_id_strings_str43[sizeof("hex")];
+ char kconf_id_strings_str46[sizeof("config")];
+ char kconf_id_strings_str47[sizeof("boolean")];
+ char kconf_id_strings_str51[sizeof("string")];
+ char kconf_id_strings_str54[sizeof("help")];
+ char kconf_id_strings_str56[sizeof("prompt")];
+ char kconf_id_strings_str72[sizeof("depends")];
+ };
+static const struct kconf_id_strings_t kconf_id_strings_contents =
+ {
+ "if",
+ "int",
+ "endif",
+ "default",
+ "tristate",
+ "endchoice",
+ "def_tristate",
+ "def_bool",
+ "defconfig_list",
+ "on",
+ "optional",
+ "option",
+ "endmenu",
+ "mainmenu",
+ "menuconfig",
+ "modules",
+ "menu",
+ "select",
+ "comment",
+ "env",
+ "range",
+ "choice",
+ "bool",
+ "source",
+ "visible",
+ "hex",
+ "config",
+ "boolean",
+ "string",
+ "help",
+ "prompt",
+ "depends"
+ };
+#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
+#ifdef __GNUC__
+__inline
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct kconf_id *
+kconf_id_lookup (register const char *str, register unsigned int len)
+{
+ enum
+ {
+ TOTAL_KEYWORDS = 32,
+ MIN_WORD_LENGTH = 2,
+ MAX_WORD_LENGTH = 14,
+ MIN_HASH_VALUE = 2,
+ MAX_HASH_VALUE = 72
+ };
+
+ static const struct kconf_id wordlist[] =
+ {
+ {-1}, {-1},
+#line 25 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM},
+#line 36 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT},
+ {-1},
+#line 26 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND},
+ {-1},
+#line 29 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
+#line 31 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE},
+#line 20 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND},
+ {-1}, {-1},
+#line 32 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE},
+#line 35 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
+#line 45 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION},
+ {-1}, {-1},
+#line 43 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_ON, TF_PARAM},
+#line 28 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND},
+ {-1}, {-1},
+#line 42 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_OPTION, TF_COMMAND},
+#line 17 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND},
+#line 15 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_MAINMENU, TF_COMMAND},
+ {-1},
+#line 23 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25, T_MENUCONFIG, TF_COMMAND},
+ {-1},
+#line 44 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION},
+ {-1},
+#line 16 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND},
+ {-1},
+#line 39 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND},
+#line 21 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND},
+#line 46 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_OPT_ENV, TF_OPTION},
+ {-1},
+#line 40 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_RANGE, TF_COMMAND},
+#line 19 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_CHOICE, TF_COMMAND},
+ {-1}, {-1},
+#line 33 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {-1},
+#line 18 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND},
+#line 41 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_VISIBLE, TF_COMMAND},
+#line 37 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_TYPE, TF_COMMAND, S_HEX},
+ {-1}, {-1},
+#line 22 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_CONFIG, TF_COMMAND},
+#line 34 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {-1}, {-1}, {-1},
+#line 38 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_TYPE, TF_COMMAND, S_STRING},
+ {-1}, {-1},
+#line 24 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str54, T_HELP, TF_COMMAND},
+ {-1},
+#line 30 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str56, T_PROMPT, TF_COMMAND},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 27 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str72, T_DEPENDS, TF_COMMAND}
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = kconf_id_hash (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int o = wordlist[key].name;
+ if (o >= 0)
+ {
+ register const char *s = o + kconf_id_strings;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+ return &wordlist[key];
+ }
+ }
+ }
+ return 0;
+}
+#line 47 "scripts/kconfig/zconf.gperf"
+
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
new file mode 100644
index 0000000..6555a47
--- /dev/null
+++ b/scripts/kconfig/zconf.l
@@ -0,0 +1,364 @@
+%option nostdinit noyywrap never-interactive full ecs
+%option 8bit nodefault perf-report perf-report
+%option noinput
+%x COMMAND HELP STRING PARAM
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "lkc.h"
+
+#define START_STRSIZE 16
+
+static struct {
+ struct file *file;
+ int lineno;
+} current_pos;
+
+static char *text;
+static int text_size, text_asize;
+
+struct buffer {
+ struct buffer *parent;
+ YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+static int last_ts, first_ts;
+
+static void zconf_endhelp(void);
+static void zconf_endfile(void);
+
+static void new_string(void)
+{
+ text = xmalloc(START_STRSIZE);
+ text_asize = START_STRSIZE;
+ text_size = 0;
+ *text = 0;
+}
+
+static void append_string(const char *str, int size)
+{
+ int new_size = text_size + size + 1;
+ if (new_size > text_asize) {
+ new_size += START_STRSIZE - 1;
+ new_size &= -START_STRSIZE;
+ text = realloc(text, new_size);
+ text_asize = new_size;
+ }
+ memcpy(text + text_size, str, size);
+ text_size += size;
+ text[text_size] = 0;
+}
+
+static void alloc_string(const char *str, int size)
+{
+ text = xmalloc(size + 1);
+ memcpy(text, str, size);
+ text[size] = 0;
+}
+%}
+
+ws [ \n\t]
+n [A-Za-z0-9_]
+
+%%
+ int str = 0;
+ int ts, i;
+
+[ \t]*#.*\n |
+[ \t]*\n {
+ current_file->lineno++;
+ return T_EOL;
+}
+[ \t]*#.*
+
+
+[ \t]+ {
+ BEGIN(COMMAND);
+}
+
+. {
+ unput(yytext[0]);
+ BEGIN(COMMAND);
+}
+
+
+<COMMAND>{
+ {n}+ {
+ const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+ BEGIN(PARAM);
+ current_pos.file = current_file;
+ current_pos.lineno = current_file->lineno;
+ if (id && id->flags & TF_COMMAND) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ .
+ \n {
+ BEGIN(INITIAL);
+ current_file->lineno++;
+ return T_EOL;
+ }
+}
+
+<PARAM>{
+ "&&" return T_AND;
+ "||" return T_OR;
+ "(" return T_OPEN_PAREN;
+ ")" return T_CLOSE_PAREN;
+ "!" return T_NOT;
+ "=" return T_EQUAL;
+ "!=" return T_UNEQUAL;
+ \"|\' {
+ str = yytext[0];
+ new_string();
+ BEGIN(STRING);
+ }
+ \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+ --- /* ignore */
+ ({n}|[-/.])+ {
+ const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+ if (id && id->flags & TF_PARAM) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ #.* /* comment */
+ \\\n current_file->lineno++;
+ .
+ <<EOF>> {
+ BEGIN(INITIAL);
+ }
+}
+
+<STRING>{
+ [^'"\\\n]+/\n {
+ append_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ [^'"\\\n]+ {
+ append_string(yytext, yyleng);
+ }
+ \\.?/\n {
+ append_string(yytext + 1, yyleng - 1);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ \\.? {
+ append_string(yytext + 1, yyleng - 1);
+ }
+ \'|\" {
+ if (str == yytext[0]) {
+ BEGIN(PARAM);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ } else
+ append_string(yytext, 1);
+ }
+ \n {
+ printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
+ current_file->lineno++;
+ BEGIN(INITIAL);
+ return T_EOL;
+ }
+ <<EOF>> {
+ BEGIN(INITIAL);
+ }
+}
+
+<HELP>{
+ [ \t]+ {
+ ts = 0;
+ for (i = 0; i < yyleng; i++) {
+ if (yytext[i] == '\t')
+ ts = (ts & ~7) + 8;
+ else
+ ts++;
+ }
+ last_ts = ts;
+ if (first_ts) {
+ if (ts < first_ts) {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ ts -= first_ts;
+ while (ts > 8) {
+ append_string(" ", 8);
+ ts -= 8;
+ }
+ append_string(" ", ts);
+ }
+ }
+ [ \t]*\n/[^ \t\n] {
+ current_file->lineno++;
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ [ \t]*\n {
+ current_file->lineno++;
+ append_string("\n", 1);
+ }
+ [^ \t\n].* {
+ while (yyleng) {
+ if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
+ break;
+ yyleng--;
+ }
+ append_string(yytext, yyleng);
+ if (!first_ts)
+ first_ts = last_ts;
+ }
+ <<EOF>> {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+}
+
+<<EOF>> {
+ if (current_file) {
+ zconf_endfile();
+ return T_EOL;
+ }
+ fclose(yyin);
+ yyterminate();
+}
+
+%%
+void zconf_starthelp(void)
+{
+ new_string();
+ last_ts = first_ts = 0;
+ BEGIN(HELP);
+}
+
+static void zconf_endhelp(void)
+{
+ zconflval.string = text;
+ BEGIN(INITIAL);
+}
+
+
+/*
+ * Try to open specified file with following names:
+ * ./name
+ * $(srctree)/name
+ * The latter is used when srctree is separate from objtree
+ * when compiling the kernel.
+ * Return NULL if file is not found.
+ */
+FILE *zconf_fopen(const char *name)
+{
+ char *env, fullname[PATH_MAX+1];
+ FILE *f;
+
+ f = fopen(name, "r");
+ if (!f && name != NULL && name[0] != '/') {
+ env = getenv(SRCTREE);
+ if (env) {
+ sprintf(fullname, "%s/%s", env, name);
+ f = fopen(fullname, "r");
+ }
+ }
+ return f;
+}
+
+void zconf_initscan(const char *name)
+{
+ yyin = zconf_fopen(name);
+ if (!yyin) {
+ printf("can't find file %s\n", name);
+ exit(1);
+ }
+
+ current_buf = xmalloc(sizeof(*current_buf));
+ memset(current_buf, 0, sizeof(*current_buf));
+
+ current_file = file_lookup(name);
+ current_file->lineno = 1;
+}
+
+void zconf_nextfile(const char *name)
+{
+ struct file *iter;
+ struct file *file = file_lookup(name);
+ struct buffer *buf = xmalloc(sizeof(*buf));
+ memset(buf, 0, sizeof(*buf));
+
+ current_buf->state = YY_CURRENT_BUFFER;
+ yyin = zconf_fopen(file->name);
+ if (!yyin) {
+ printf("%s:%d: can't open file \"%s\"\n",
+ zconf_curname(), zconf_lineno(), file->name);
+ exit(1);
+ }
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+ buf->parent = current_buf;
+ current_buf = buf;
+
+ for (iter = current_file->parent; iter; iter = iter->parent ) {
+ if (!strcmp(current_file->name,iter->name) ) {
+ printf("%s:%d: recursive inclusion detected. "
+ "Inclusion path:\n current file : '%s'\n",
+ zconf_curname(), zconf_lineno(),
+ zconf_curname());
+ iter = current_file->parent;
+ while (iter && \
+ strcmp(iter->name,current_file->name)) {
+ printf(" included from: '%s:%d'\n",
+ iter->name, iter->lineno-1);
+ iter = iter->parent;
+ }
+ if (iter)
+ printf(" included from: '%s:%d'\n",
+ iter->name, iter->lineno+1);
+ exit(1);
+ }
+ }
+ file->lineno = 1;
+ file->parent = current_file;
+ current_file = file;
+}
+
+static void zconf_endfile(void)
+{
+ struct buffer *parent;
+
+ current_file = current_file->parent;
+
+ parent = current_buf->parent;
+ if (parent) {
+ fclose(yyin);
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(parent->state);
+ }
+ free(current_buf);
+ current_buf = parent;
+}
+
+int zconf_lineno(void)
+{
+ return current_pos.lineno;
+}
+
+const char *zconf_curname(void)
+{
+ return current_pos.file ? current_pos.file->name : "<none>";
+}
diff --git a/scripts/kconfig/zconf.lex.c_shipped b/scripts/kconfig/zconf.lex.c_shipped
new file mode 100644
index 0000000..a0521aa
--- /dev/null
+++ b/scripts/kconfig/zconf.lex.c_shipped
@@ -0,0 +1,2420 @@
+
+#line 3 "scripts/kconfig/zconf.lex.c_shipped"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer zconf_create_buffer
+#define yy_delete_buffer zconf_delete_buffer
+#define yy_flex_debug zconf_flex_debug
+#define yy_init_buffer zconf_init_buffer
+#define yy_flush_buffer zconf_flush_buffer
+#define yy_load_buffer_state zconf_load_buffer_state
+#define yy_switch_to_buffer zconf_switch_to_buffer
+#define yyin zconfin
+#define yyleng zconfleng
+#define yylex zconflex
+#define yylineno zconflineno
+#define yyout zconfout
+#define yyrestart zconfrestart
+#define yytext zconftext
+#define yywrap zconfwrap
+#define yyalloc zconfalloc
+#define yyrealloc zconfrealloc
+#define yyfree zconffree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __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;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE zconfrestart(zconfin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#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;
+#endif
+
+extern int zconfleng;
+
+extern FILE *zconfin, *zconfout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up zconftext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up zconftext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via zconfrestart()), so that the user can continue scanning by
+ * just pointing zconfin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when zconftext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int zconfleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+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
+ * instead of setting up a fresh zconfin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void zconfrestart (FILE *input_file );
+void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size );
+void zconf_delete_buffer (YY_BUFFER_STATE b );
+void zconf_flush_buffer (YY_BUFFER_STATE b );
+void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer );
+void zconfpop_buffer_state (void );
+
+static void zconfensure_buffer_stack (void );
+static void zconf_load_buffer_state (void );
+static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len );
+
+void *zconfalloc (yy_size_t );
+void *zconfrealloc (void *,yy_size_t );
+void zconffree (void * );
+
+#define yy_new_buffer zconf_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ zconfensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ zconfensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define zconfwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int zconflineno;
+
+int zconflineno = 1;
+
+extern char *zconftext;
+#define yytext_ptr zconftext
+static yyconst flex_int16_t yy_nxt[][17] =
+ {
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+ },
+
+ {
+ 11, 12, 13, 14, 12, 12, 15, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12
+ },
+
+ {
+ 11, 12, 13, 14, 12, 12, 15, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12
+ },
+
+ {
+ 11, 16, 16, 17, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 18, 16, 16, 16
+ },
+
+ {
+ 11, 16, 16, 17, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 18, 16, 16, 16
+
+ },
+
+ {
+ 11, 19, 20, 21, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19
+ },
+
+ {
+ 11, 19, 20, 21, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19
+ },
+
+ {
+ 11, 22, 22, 23, 22, 24, 22, 22, 24, 22,
+ 22, 22, 22, 22, 22, 25, 22
+ },
+
+ {
+ 11, 22, 22, 23, 22, 24, 22, 22, 24, 22,
+ 22, 22, 22, 22, 22, 25, 22
+ },
+
+ {
+ 11, 26, 26, 27, 28, 29, 30, 31, 29, 32,
+ 33, 34, 35, 35, 36, 37, 38
+
+ },
+
+ {
+ 11, 26, 26, 27, 28, 29, 30, 31, 29, 32,
+ 33, 34, 35, 35, 36, 37, 38
+ },
+
+ {
+ -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
+ -11, -11, -11, -11, -11, -11, -11
+ },
+
+ {
+ 11, -12, -12, -12, -12, -12, -12, -12, -12, -12,
+ -12, -12, -12, -12, -12, -12, -12
+ },
+
+ {
+ 11, -13, 39, 40, -13, -13, 41, -13, -13, -13,
+ -13, -13, -13, -13, -13, -13, -13
+ },
+
+ {
+ 11, -14, -14, -14, -14, -14, -14, -14, -14, -14,
+ -14, -14, -14, -14, -14, -14, -14
+
+ },
+
+ {
+ 11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42
+ },
+
+ {
+ 11, -16, -16, -16, -16, -16, -16, -16, -16, -16,
+ -16, -16, -16, -16, -16, -16, -16
+ },
+
+ {
+ 11, -17, -17, -17, -17, -17, -17, -17, -17, -17,
+ -17, -17, -17, -17, -17, -17, -17
+ },
+
+ {
+ 11, -18, -18, -18, -18, -18, -18, -18, -18, -18,
+ -18, -18, -18, 44, -18, -18, -18
+ },
+
+ {
+ 11, 45, 45, -19, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45
+
+ },
+
+ {
+ 11, -20, 46, 47, -20, -20, -20, -20, -20, -20,
+ -20, -20, -20, -20, -20, -20, -20
+ },
+
+ {
+ 11, 48, -21, -21, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48
+ },
+
+ {
+ 11, 49, 49, 50, 49, -22, 49, 49, -22, 49,
+ 49, 49, 49, 49, 49, -22, 49
+ },
+
+ {
+ 11, -23, -23, -23, -23, -23, -23, -23, -23, -23,
+ -23, -23, -23, -23, -23, -23, -23
+ },
+
+ {
+ 11, -24, -24, -24, -24, -24, -24, -24, -24, -24,
+ -24, -24, -24, -24, -24, -24, -24
+
+ },
+
+ {
+ 11, 51, 51, 52, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51
+ },
+
+ {
+ 11, -26, -26, -26, -26, -26, -26, -26, -26, -26,
+ -26, -26, -26, -26, -26, -26, -26
+ },
+
+ {
+ 11, -27, -27, -27, -27, -27, -27, -27, -27, -27,
+ -27, -27, -27, -27, -27, -27, -27
+ },
+
+ {
+ 11, -28, -28, -28, -28, -28, -28, -28, -28, -28,
+ -28, -28, -28, -28, 53, -28, -28
+ },
+
+ {
+ 11, -29, -29, -29, -29, -29, -29, -29, -29, -29,
+ -29, -29, -29, -29, -29, -29, -29
+
+ },
+
+ {
+ 11, 54, 54, -30, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54
+ },
+
+ {
+ 11, -31, -31, -31, -31, -31, -31, 55, -31, -31,
+ -31, -31, -31, -31, -31, -31, -31
+ },
+
+ {
+ 11, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, -32, -32
+ },
+
+ {
+ 11, -33, -33, -33, -33, -33, -33, -33, -33, -33,
+ -33, -33, -33, -33, -33, -33, -33
+ },
+
+ {
+ 11, -34, -34, -34, -34, -34, -34, -34, -34, -34,
+ -34, 56, 57, 57, -34, -34, -34
+
+ },
+
+ {
+ 11, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -35, 57, 57, 57, -35, -35, -35
+ },
+
+ {
+ 11, -36, -36, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -36, -36, -36, -36, -36
+ },
+
+ {
+ 11, -37, -37, 58, -37, -37, -37, -37, -37, -37,
+ -37, -37, -37, -37, -37, -37, -37
+ },
+
+ {
+ 11, -38, -38, -38, -38, -38, -38, -38, -38, -38,
+ -38, -38, -38, -38, -38, -38, 59
+ },
+
+ {
+ 11, -39, 39, 40, -39, -39, 41, -39, -39, -39,
+ -39, -39, -39, -39, -39, -39, -39
+
+ },
+
+ {
+ 11, -40, -40, -40, -40, -40, -40, -40, -40, -40,
+ -40, -40, -40, -40, -40, -40, -40
+ },
+
+ {
+ 11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42
+ },
+
+ {
+ 11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42
+ },
+
+ {
+ 11, -43, -43, -43, -43, -43, -43, -43, -43, -43,
+ -43, -43, -43, -43, -43, -43, -43
+ },
+
+ {
+ 11, -44, -44, -44, -44, -44, -44, -44, -44, -44,
+ -44, -44, -44, 44, -44, -44, -44
+
+ },
+
+ {
+ 11, 45, 45, -45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45
+ },
+
+ {
+ 11, -46, 46, 47, -46, -46, -46, -46, -46, -46,
+ -46, -46, -46, -46, -46, -46, -46
+ },
+
+ {
+ 11, 48, -47, -47, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48
+ },
+
+ {
+ 11, -48, -48, -48, -48, -48, -48, -48, -48, -48,
+ -48, -48, -48, -48, -48, -48, -48
+ },
+
+ {
+ 11, 49, 49, 50, 49, -49, 49, 49, -49, 49,
+ 49, 49, 49, 49, 49, -49, 49
+
+ },
+
+ {
+ 11, -50, -50, -50, -50, -50, -50, -50, -50, -50,
+ -50, -50, -50, -50, -50, -50, -50
+ },
+
+ {
+ 11, -51, -51, 52, -51, -51, -51, -51, -51, -51,
+ -51, -51, -51, -51, -51, -51, -51
+ },
+
+ {
+ 11, -52, -52, -52, -52, -52, -52, -52, -52, -52,
+ -52, -52, -52, -52, -52, -52, -52
+ },
+
+ {
+ 11, -53, -53, -53, -53, -53, -53, -53, -53, -53,
+ -53, -53, -53, -53, -53, -53, -53
+ },
+
+ {
+ 11, 54, 54, -54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54
+
+ },
+
+ {
+ 11, -55, -55, -55, -55, -55, -55, -55, -55, -55,
+ -55, -55, -55, -55, -55, -55, -55
+ },
+
+ {
+ 11, -56, -56, -56, -56, -56, -56, -56, -56, -56,
+ -56, 60, 57, 57, -56, -56, -56
+ },
+
+ {
+ 11, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, 57, 57, 57, -57, -57, -57
+ },
+
+ {
+ 11, -58, -58, -58, -58, -58, -58, -58, -58, -58,
+ -58, -58, -58, -58, -58, -58, -58
+ },
+
+ {
+ 11, -59, -59, -59, -59, -59, -59, -59, -59, -59,
+ -59, -59, -59, -59, -59, -59, -59
+
+ },
+
+ {
+ 11, -60, -60, -60, -60, -60, -60, -60, -60, -60,
+ -60, 57, 57, 57, -60, -60, -60
+ },
+
+ } ;
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up zconftext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ zconfleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 33
+#define YY_END_OF_BUFFER 34
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[61] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 34, 5, 4, 2, 3, 7, 8, 6, 32, 29,
+ 31, 24, 28, 27, 26, 22, 17, 13, 16, 20,
+ 22, 11, 12, 19, 19, 14, 22, 22, 4, 2,
+ 3, 3, 1, 6, 32, 29, 31, 30, 24, 23,
+ 26, 25, 15, 20, 9, 19, 19, 21, 10, 18
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 4, 5, 6, 1, 1, 7, 8, 9,
+ 10, 1, 1, 1, 11, 12, 12, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 1, 1, 1,
+ 14, 1, 1, 1, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 1, 15, 1, 1, 13, 1, 13, 13, 13, 13,
+
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 1, 16, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+extern int zconf_flex_debug;
+int zconf_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *zconftext;
+#define YY_NO_INPUT 1
+
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "lkc.h"
+
+#define START_STRSIZE 16
+
+static struct {
+ struct file *file;
+ int lineno;
+} current_pos;
+
+static char *text;
+static int text_size, text_asize;
+
+struct buffer {
+ struct buffer *parent;
+ YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+static int last_ts, first_ts;
+
+static void zconf_endhelp(void);
+static void zconf_endfile(void);
+
+static void new_string(void)
+{
+ text = xmalloc(START_STRSIZE);
+ text_asize = START_STRSIZE;
+ text_size = 0;
+ *text = 0;
+}
+
+static void append_string(const char *str, int size)
+{
+ int new_size = text_size + size + 1;
+ if (new_size > text_asize) {
+ new_size += START_STRSIZE - 1;
+ new_size &= -START_STRSIZE;
+ text = realloc(text, new_size);
+ text_asize = new_size;
+ }
+ memcpy(text + text_size, str, size);
+ text_size += size;
+ text[text_size] = 0;
+}
+
+static void alloc_string(const char *str, int size)
+{
+ text = xmalloc(size + 1);
+ memcpy(text, str, size);
+ text[size] = 0;
+}
+
+#define INITIAL 0
+#define COMMAND 1
+#define HELP 2
+#define STRING 3
+#define PARAM 4
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int zconflex_destroy (void );
+
+int zconfget_debug (void );
+
+void zconfset_debug (int debug_flag );
+
+YY_EXTRA_TYPE zconfget_extra (void );
+
+void zconfset_extra (YY_EXTRA_TYPE user_defined );
+
+FILE *zconfget_in (void );
+
+void zconfset_in (FILE * in_str );
+
+FILE *zconfget_out (void );
+
+void zconfset_out (FILE * out_str );
+
+int zconfget_leng (void );
+
+char *zconfget_text (void );
+
+int zconfget_lineno (void );
+
+void zconfset_lineno (int line_number );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int zconfwrap (void );
+#else
+extern int zconfwrap (void );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr );
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ errno=0; \
+ while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(zconfin); \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int zconflex (void);
+
+#define YY_DECL int zconflex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after zconftext and zconfleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+ int str = 0;
+ int ts, i;
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! zconfin )
+ zconfin = stdin;
+
+ if ( ! zconfout )
+ zconfout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ zconfensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ zconf_create_buffer(zconfin,YY_BUF_SIZE );
+ }
+
+ zconf_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of zconftext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+yy_match:
+ while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 )
+ ++yy_cp;
+
+ yy_current_state = -yy_current_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+case 1:
+/* rule 1 can match eol */
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+{
+ current_file->lineno++;
+ return T_EOL;
+}
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+{
+ BEGIN(COMMAND);
+}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+{
+ unput(zconftext[0]);
+ BEGIN(COMMAND);
+}
+ YY_BREAK
+
+case 6:
+YY_RULE_SETUP
+{
+ const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
+ BEGIN(PARAM);
+ current_pos.file = current_file;
+ current_pos.lineno = current_file->lineno;
+ if (id && id->flags & TF_COMMAND) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(zconftext, zconfleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+
+ YY_BREAK
+case 8:
+/* rule 8 can match eol */
+YY_RULE_SETUP
+{
+ BEGIN(INITIAL);
+ current_file->lineno++;
+ return T_EOL;
+ }
+ YY_BREAK
+
+case 9:
+YY_RULE_SETUP
+return T_AND;
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+return T_OR;
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+return T_OPEN_PAREN;
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+return T_CLOSE_PAREN;
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+return T_NOT;
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+return T_EQUAL;
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+return T_UNEQUAL;
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+{
+ str = zconftext[0];
+ new_string();
+ BEGIN(STRING);
+ }
+ YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+/* ignore */
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+{
+ const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
+ if (id && id->flags & TF_PARAM) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(zconftext, zconfleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+/* comment */
+ YY_BREAK
+case 21:
+/* rule 21 can match eol */
+YY_RULE_SETUP
+current_file->lineno++;
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+
+ YY_BREAK
+case YY_STATE_EOF(PARAM):
+{
+ BEGIN(INITIAL);
+ }
+ YY_BREAK
+
+case 23:
+/* rule 23 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+ append_string(zconftext, zconfleng);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+{
+ append_string(zconftext, zconfleng);
+ }
+ YY_BREAK
+case 25:
+/* rule 25 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+ append_string(zconftext + 1, zconfleng - 1);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+{
+ append_string(zconftext + 1, zconfleng - 1);
+ }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+{
+ if (str == zconftext[0]) {
+ BEGIN(PARAM);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ } else
+ append_string(zconftext, 1);
+ }
+ YY_BREAK
+case 28:
+/* rule 28 can match eol */
+YY_RULE_SETUP
+{
+ printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
+ current_file->lineno++;
+ BEGIN(INITIAL);
+ return T_EOL;
+ }
+ YY_BREAK
+case YY_STATE_EOF(STRING):
+{
+ BEGIN(INITIAL);
+ }
+ YY_BREAK
+
+case 29:
+YY_RULE_SETUP
+{
+ ts = 0;
+ for (i = 0; i < zconfleng; i++) {
+ if (zconftext[i] == '\t')
+ ts = (ts & ~7) + 8;
+ else
+ ts++;
+ }
+ last_ts = ts;
+ if (first_ts) {
+ if (ts < first_ts) {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ ts -= first_ts;
+ while (ts > 8) {
+ append_string(" ", 8);
+ ts -= 8;
+ }
+ append_string(" ", ts);
+ }
+ }
+ YY_BREAK
+case 30:
+/* rule 30 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+ current_file->lineno++;
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ YY_BREAK
+case 31:
+/* rule 31 can match eol */
+YY_RULE_SETUP
+{
+ current_file->lineno++;
+ append_string("\n", 1);
+ }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+{
+ while (zconfleng) {
+ if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t'))
+ break;
+ zconfleng--;
+ }
+ append_string(zconftext, zconfleng);
+ if (!first_ts)
+ first_ts = last_ts;
+ }
+ YY_BREAK
+case YY_STATE_EOF(HELP):
+{
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ YY_BREAK
+
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(COMMAND):
+{
+ if (current_file) {
+ zconf_endfile();
+ return T_EOL;
+ }
+ fclose(zconfin);
+ yyterminate();
+}
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+YY_FATAL_ERROR( "flex scanner jammed" );
+ YY_BREAK
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed zconfin at a new source and called
+ * zconflex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( zconfwrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * zconftext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of zconflex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ zconfrestart(zconfin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+
+ yy_current_state = yy_nxt[yy_current_state][1];
+ yy_is_jam = (yy_current_state <= 0);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp )
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up zconftext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ zconfrestart(zconfin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( zconfwrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve zconftext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void zconfrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ zconfensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ zconf_create_buffer(zconfin,YY_BUF_SIZE );
+ }
+
+ zconf_init_buffer(YY_CURRENT_BUFFER,input_file );
+ zconf_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * zconfpop_buffer_state();
+ * zconfpush_buffer_state(new_buffer);
+ */
+ zconfensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ zconf_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (zconfwrap()) processing, but the only time this flag
+ * is looked at is after zconfwrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void zconf_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ zconf_init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with zconf_create_buffer()
+ *
+ */
+ void zconf_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ zconffree((void *) b->yy_ch_buf );
+
+ zconffree((void *) b );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a zconfrestart() or at EOF.
+ */
+ static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ zconf_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then zconf_init_buffer was _probably_
+ * called from zconfrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void zconf_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ zconf_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ zconfensure_buffer_stack();
+
+ /* This block is copied from zconf_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from zconf_switch_to_buffer. */
+ zconf_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void zconfpop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ zconf_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ zconf_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void zconfensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ zconf_switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to zconflex() will
+ * scan from a @e copy of @a str.
+ * @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 * yystr )
+{
+
+ return zconf_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ 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 < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = zconf_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up zconftext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ zconftext[zconfleng] = (yy_hold_char); \
+ (yy_c_buf_p) = zconftext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ zconfleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int zconfget_lineno (void)
+{
+
+ return zconflineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *zconfget_in (void)
+{
+ return zconfin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *zconfget_out (void)
+{
+ return zconfout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int zconfget_leng (void)
+{
+ return zconfleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *zconfget_text (void)
+{
+ return zconftext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void zconfset_lineno (int line_number )
+{
+
+ zconflineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see zconf_switch_to_buffer
+ */
+void zconfset_in (FILE * in_str )
+{
+ zconfin = in_str ;
+}
+
+void zconfset_out (FILE * out_str )
+{
+ zconfout = out_str ;
+}
+
+int zconfget_debug (void)
+{
+ return zconf_flex_debug;
+}
+
+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)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ zconf_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ zconfpop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ 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;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *zconfalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *zconfrealloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void zconffree (void * ptr )
+{
+ free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+void zconf_starthelp(void)
+{
+ new_string();
+ last_ts = first_ts = 0;
+ BEGIN(HELP);
+}
+
+static void zconf_endhelp(void)
+{
+ zconflval.string = text;
+ BEGIN(INITIAL);
+}
+
+/*
+ * Try to open specified file with following names:
+ * ./name
+ * $(srctree)/name
+ * The latter is used when srctree is separate from objtree
+ * when compiling the kernel.
+ * Return NULL if file is not found.
+ */
+FILE *zconf_fopen(const char *name)
+{
+ char *env, fullname[PATH_MAX+1];
+ FILE *f;
+
+ f = fopen(name, "r");
+ if (!f && name != NULL && name[0] != '/') {
+ env = getenv(SRCTREE);
+ if (env) {
+ sprintf(fullname, "%s/%s", env, name);
+ f = fopen(fullname, "r");
+ }
+ }
+ return f;
+}
+
+void zconf_initscan(const char *name)
+{
+ zconfin = zconf_fopen(name);
+ if (!zconfin) {
+ printf("can't find file %s\n", name);
+ exit(1);
+ }
+
+ current_buf = xmalloc(sizeof(*current_buf));
+ memset(current_buf, 0, sizeof(*current_buf));
+
+ current_file = file_lookup(name);
+ current_file->lineno = 1;
+}
+
+void zconf_nextfile(const char *name)
+{
+ struct file *iter;
+ struct file *file = file_lookup(name);
+ struct buffer *buf = xmalloc(sizeof(*buf));
+ memset(buf, 0, sizeof(*buf));
+
+ current_buf->state = YY_CURRENT_BUFFER;
+ zconfin = zconf_fopen(file->name);
+ if (!zconfin) {
+ printf("%s:%d: can't open file \"%s\"\n",
+ zconf_curname(), zconf_lineno(), file->name);
+ exit(1);
+ }
+ zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
+ buf->parent = current_buf;
+ current_buf = buf;
+
+ for (iter = current_file->parent; iter; iter = iter->parent ) {
+ if (!strcmp(current_file->name,iter->name) ) {
+ printf("%s:%d: recursive inclusion detected. "
+ "Inclusion path:\n current file : '%s'\n",
+ zconf_curname(), zconf_lineno(),
+ zconf_curname());
+ iter = current_file->parent;
+ while (iter && \
+ strcmp(iter->name,current_file->name)) {
+ printf(" included from: '%s:%d'\n",
+ iter->name, iter->lineno-1);
+ iter = iter->parent;
+ }
+ if (iter)
+ printf(" included from: '%s:%d'\n",
+ iter->name, iter->lineno+1);
+ exit(1);
+ }
+ }
+ file->lineno = 1;
+ file->parent = current_file;
+ current_file = file;
+}
+
+static void zconf_endfile(void)
+{
+ struct buffer *parent;
+
+ current_file = current_file->parent;
+
+ parent = current_buf->parent;
+ if (parent) {
+ fclose(zconfin);
+ zconf_delete_buffer(YY_CURRENT_BUFFER);
+ zconf_switch_to_buffer(parent->state);
+ }
+ free(current_buf);
+ current_buf = parent;
+}
+
+int zconf_lineno(void)
+{
+ return current_pos.lineno;
+}
+
+const char *zconf_curname(void)
+{
+ return current_pos.file ? current_pos.file->name : "<none>";
+}
+
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
new file mode 100644
index 0000000..f636141
--- /dev/null
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -0,0 +1,2504 @@
+/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names. */
+#define yyparse zconfparse
+#define yylex zconflex
+#define yyerror zconferror
+#define yylval zconflval
+#define yychar zconfchar
+#define yydebug zconfdebug
+#define yynerrs zconfnerrs
+
+
+/* Copy the first part of user declarations. */
+
+
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "lkc.h"
+
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
+
+#define PRINTD 0x0001
+#define DEBUG_PARSE 0x0002
+
+int cdebug = PRINTD;
+
+extern int zconflex(void);
+static void zconfprint(const char *err, ...);
+static void zconf_error(const char *err, ...);
+static void zconferror(const char *err);
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
+
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
+
+static struct menu *current_menu, *current_entry;
+
+
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ T_MAINMENU = 258,
+ T_MENU = 259,
+ T_ENDMENU = 260,
+ T_SOURCE = 261,
+ T_CHOICE = 262,
+ T_ENDCHOICE = 263,
+ T_COMMENT = 264,
+ T_CONFIG = 265,
+ T_MENUCONFIG = 266,
+ T_HELP = 267,
+ T_HELPTEXT = 268,
+ T_IF = 269,
+ T_ENDIF = 270,
+ T_DEPENDS = 271,
+ T_OPTIONAL = 272,
+ T_PROMPT = 273,
+ T_TYPE = 274,
+ T_DEFAULT = 275,
+ T_SELECT = 276,
+ T_RANGE = 277,
+ T_VISIBLE = 278,
+ T_OPTION = 279,
+ T_ON = 280,
+ T_WORD = 281,
+ T_WORD_QUOTE = 282,
+ T_UNEQUAL = 283,
+ T_CLOSE_PAREN = 284,
+ T_OPEN_PAREN = 285,
+ T_EOL = 286,
+ T_OR = 287,
+ T_AND = 288,
+ T_EQUAL = 289,
+ T_NOT = 290
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+
+ char *string;
+ struct file *file;
+ struct symbol *symbol;
+ struct expr *expr;
+ struct menu *menu;
+ const struct kconf_id *id;
+
+
+
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Include zconf.hash.c here so it can see the token constants. */
+#include "zconf.hash.c"
+
+
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 11
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 290
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 36
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 50
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 118
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 191
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 290
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 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,
+ 35
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 6, 8, 11, 13, 14, 17, 20,
+ 23, 26, 31, 36, 40, 42, 44, 46, 48, 50,
+ 52, 54, 56, 58, 60, 62, 64, 66, 68, 72,
+ 75, 79, 82, 86, 89, 90, 93, 96, 99, 102,
+ 105, 108, 112, 117, 122, 127, 133, 137, 138, 142,
+ 143, 146, 150, 153, 155, 159, 160, 163, 166, 169,
+ 172, 175, 180, 184, 187, 192, 193, 196, 200, 202,
+ 206, 207, 210, 213, 216, 220, 224, 228, 230, 234,
+ 235, 238, 241, 244, 248, 252, 255, 258, 261, 262,
+ 265, 268, 271, 276, 277, 280, 283, 286, 287, 290,
+ 292, 294, 297, 300, 303, 305, 308, 309, 312, 314,
+ 318, 322, 326, 329, 333, 337, 339, 341, 342
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 37, 0, -1, 81, 38, -1, 38, -1, 63, 39,
+ -1, 39, -1, -1, 39, 41, -1, 39, 55, -1,
+ 39, 67, -1, 39, 80, -1, 39, 26, 1, 31,
+ -1, 39, 40, 1, 31, -1, 39, 1, 31, -1,
+ 16, -1, 18, -1, 19, -1, 21, -1, 17, -1,
+ 22, -1, 20, -1, 23, -1, 31, -1, 61, -1,
+ 71, -1, 44, -1, 46, -1, 69, -1, 26, 1,
+ 31, -1, 1, 31, -1, 10, 26, 31, -1, 43,
+ 47, -1, 11, 26, 31, -1, 45, 47, -1, -1,
+ 47, 48, -1, 47, 49, -1, 47, 75, -1, 47,
+ 73, -1, 47, 42, -1, 47, 31, -1, 19, 78,
+ 31, -1, 18, 79, 82, 31, -1, 20, 83, 82,
+ 31, -1, 21, 26, 82, 31, -1, 22, 84, 84,
+ 82, 31, -1, 24, 50, 31, -1, -1, 50, 26,
+ 51, -1, -1, 34, 79, -1, 7, 85, 31, -1,
+ 52, 56, -1, 80, -1, 53, 58, 54, -1, -1,
+ 56, 57, -1, 56, 75, -1, 56, 73, -1, 56,
+ 31, -1, 56, 42, -1, 18, 79, 82, 31, -1,
+ 19, 78, 31, -1, 17, 31, -1, 20, 26, 82,
+ 31, -1, -1, 58, 41, -1, 14, 83, 81, -1,
+ 80, -1, 59, 62, 60, -1, -1, 62, 41, -1,
+ 62, 67, -1, 62, 55, -1, 3, 79, 81, -1,
+ 4, 79, 31, -1, 64, 76, 74, -1, 80, -1,
+ 65, 68, 66, -1, -1, 68, 41, -1, 68, 67,
+ -1, 68, 55, -1, 6, 79, 31, -1, 9, 79,
+ 31, -1, 70, 74, -1, 12, 31, -1, 72, 13,
+ -1, -1, 74, 75, -1, 74, 31, -1, 74, 42,
+ -1, 16, 25, 83, 31, -1, -1, 76, 77, -1,
+ 76, 31, -1, 23, 82, -1, -1, 79, 82, -1,
+ 26, -1, 27, -1, 5, 31, -1, 8, 31, -1,
+ 15, 31, -1, 31, -1, 81, 31, -1, -1, 14,
+ 83, -1, 84, -1, 84, 34, 84, -1, 84, 28,
+ 84, -1, 30, 83, 29, -1, 35, 83, -1, 83,
+ 32, 83, -1, 83, 33, 83, -1, 26, -1, 27,
+ -1, -1, 26, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 104, 104, 104, 106, 106, 108, 110, 111, 112,
+ 113, 114, 115, 119, 123, 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, 359, 364, 372, 375,
+ 377, 378, 379, 382, 390, 397, 404, 410, 417, 419,
+ 420, 421, 424, 432, 434, 435, 438, 445, 447, 452,
+ 453, 456, 457, 458, 462, 463, 466, 467, 470, 471,
+ 472, 473, 474, 475, 476, 479, 480, 483, 484
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU",
+ "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
+ "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
+ "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
+ "T_VISIBLE", "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", "start", "stmt_list", "option_name",
+ "common_stmt", "option_error", "config_entry_start", "config_stmt",
+ "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
+ "config_option", "symbol_option", "symbol_option_list",
+ "symbol_option_arg", "choice", "choice_entry", "choice_end",
+ "choice_stmt", "choice_option_list", "choice_option", "choice_block",
+ "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu",
+ "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
+ "comment", "comment_stmt", "help_start", "help", "depends_list",
+ "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
+ "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 36, 37, 37, 38, 38, 39, 39, 39, 39,
+ 39, 39, 39, 39, 40, 40, 40, 40, 40, 40,
+ 40, 40, 41, 41, 41, 41, 41, 41, 42, 42,
+ 43, 44, 45, 46, 47, 47, 47, 47, 47, 47,
+ 47, 48, 48, 48, 48, 48, 49, 50, 50, 51,
+ 51, 52, 53, 54, 55, 56, 56, 56, 56, 56,
+ 56, 57, 57, 57, 57, 58, 58, 59, 60, 61,
+ 62, 62, 62, 62, 63, 64, 65, 66, 67, 68,
+ 68, 68, 68, 69, 70, 71, 72, 73, 74, 74,
+ 74, 74, 75, 76, 76, 76, 77, 78, 78, 79,
+ 79, 80, 80, 80, 81, 81, 82, 82, 83, 83,
+ 83, 83, 83, 83, 83, 84, 84, 85, 85
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 2, 1, 2, 1, 0, 2, 2, 2,
+ 2, 4, 4, 3, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 3, 2,
+ 3, 2, 3, 2, 0, 2, 2, 2, 2, 2,
+ 2, 3, 4, 4, 4, 5, 3, 0, 3, 0,
+ 2, 3, 2, 1, 3, 0, 2, 2, 2, 2,
+ 2, 4, 3, 2, 4, 0, 2, 3, 1, 3,
+ 0, 2, 2, 2, 3, 3, 3, 1, 3, 0,
+ 2, 2, 2, 3, 3, 2, 2, 2, 0, 2,
+ 2, 2, 4, 0, 2, 2, 2, 0, 2, 1,
+ 1, 2, 2, 2, 1, 2, 0, 2, 1, 3,
+ 3, 3, 2, 3, 3, 1, 1, 0, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 6, 0, 104, 0, 3, 0, 6, 6, 99, 100,
+ 0, 1, 0, 0, 0, 0, 117, 0, 0, 0,
+ 0, 0, 0, 14, 18, 15, 16, 20, 17, 19,
+ 21, 0, 22, 0, 7, 34, 25, 34, 26, 55,
+ 65, 8, 70, 23, 93, 79, 9, 27, 88, 24,
+ 10, 0, 105, 2, 74, 13, 0, 101, 0, 118,
+ 0, 102, 0, 0, 0, 115, 116, 0, 0, 0,
+ 108, 103, 0, 0, 0, 0, 0, 0, 0, 88,
+ 0, 0, 75, 83, 51, 84, 30, 32, 0, 112,
+ 0, 0, 67, 0, 0, 11, 12, 0, 0, 0,
+ 0, 97, 0, 0, 0, 47, 0, 40, 39, 35,
+ 36, 0, 38, 37, 0, 0, 97, 0, 59, 60,
+ 56, 58, 57, 66, 54, 53, 71, 73, 69, 72,
+ 68, 106, 95, 0, 94, 80, 82, 78, 81, 77,
+ 90, 91, 89, 111, 113, 114, 110, 109, 29, 86,
+ 0, 106, 0, 106, 106, 106, 0, 0, 0, 87,
+ 63, 106, 0, 106, 0, 96, 0, 0, 41, 98,
+ 0, 0, 106, 49, 46, 28, 0, 62, 0, 107,
+ 92, 42, 43, 44, 0, 0, 48, 61, 64, 45,
+ 50
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 3, 4, 5, 33, 34, 108, 35, 36, 37,
+ 38, 74, 109, 110, 157, 186, 39, 40, 124, 41,
+ 76, 120, 77, 42, 128, 43, 78, 6, 44, 45,
+ 137, 46, 80, 47, 48, 49, 111, 112, 81, 113,
+ 79, 134, 152, 153, 50, 7, 165, 69, 70, 60
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -90
+static const yytype_int16 yypact[] =
+{
+ 4, 42, -90, 96, -90, 111, -90, 15, -90, -90,
+ 75, -90, 82, 42, 104, 42, 110, 107, 42, 115,
+ 125, -4, 121, -90, -90, -90, -90, -90, -90, -90,
+ -90, 162, -90, 163, -90, -90, -90, -90, -90, -90,
+ -90, -90, -90, -90, -90, -90, -90, -90, -90, -90,
+ -90, 139, -90, -90, 138, -90, 142, -90, 143, -90,
+ 152, -90, 164, 167, 168, -90, -90, -4, -4, 77,
+ -18, -90, 177, 185, 33, 71, 195, 247, 236, -2,
+ 236, 171, -90, -90, -90, -90, -90, -90, 41, -90,
+ -4, -4, 138, 97, 97, -90, -90, 186, 187, 194,
+ 42, 42, -4, 196, 97, -90, 219, -90, -90, -90,
+ -90, 210, -90, -90, 204, 42, 42, 199, -90, -90,
+ -90, -90, -90, -90, -90, -90, -90, -90, -90, -90,
+ -90, 222, -90, 223, -90, -90, -90, -90, -90, -90,
+ -90, -90, -90, -90, 215, -90, -90, -90, -90, -90,
+ -4, 222, 228, 222, -5, 222, 97, 35, 229, -90,
+ -90, 222, 232, 222, -4, -90, 135, 233, -90, -90,
+ 234, 235, 222, 240, -90, -90, 237, -90, 239, -13,
+ -90, -90, -90, -90, 244, 42, -90, -90, -90, -90,
+ -90
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -90, -90, 269, 271, -90, 23, -70, -90, -90, -90,
+ -90, 243, -90, -90, -90, -90, -90, -90, -90, -48,
+ -90, -90, -90, -90, -90, -90, -90, -90, -90, -90,
+ -90, -20, -90, -90, -90, -90, -90, 206, 205, -68,
+ -90, -90, 169, -1, 27, -7, 118, -66, -89, -90
+};
+
+/* 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 -86
+static const yytype_int16 yytable[] =
+{
+ 10, 88, 89, 54, 146, 147, 119, 1, 122, 164,
+ 93, 141, 56, 142, 58, 156, 94, 62, 1, 90,
+ 91, 131, 65, 66, 144, 145, 67, 90, 91, 132,
+ 127, 68, 136, -31, 97, 2, 154, -31, -31, -31,
+ -31, -31, -31, -31, -31, 98, 52, -31, -31, 99,
+ -31, 100, 101, 102, 103, 104, -31, 105, 129, 106,
+ 138, 173, 92, 141, 107, 142, 174, 172, 8, 9,
+ 143, -33, 97, 90, 91, -33, -33, -33, -33, -33,
+ -33, -33, -33, 98, 166, -33, -33, 99, -33, 100,
+ 101, 102, 103, 104, -33, 105, 11, 106, 179, 151,
+ 123, 126, 107, 135, 125, 130, 2, 139, 2, 90,
+ 91, -5, 12, 55, 161, 13, 14, 15, 16, 17,
+ 18, 19, 20, 65, 66, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 57, 59, 31, 61, -4,
+ 12, 63, 32, 13, 14, 15, 16, 17, 18, 19,
+ 20, 64, 71, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 72, 73, 31, 180, 90, 91, 52,
+ 32, -85, 97, 82, 83, -85, -85, -85, -85, -85,
+ -85, -85, -85, 84, 190, -85, -85, 99, -85, -85,
+ -85, -85, -85, -85, -85, 85, 97, 106, 86, 87,
+ -52, -52, 140, -52, -52, -52, -52, 98, 95, -52,
+ -52, 99, 114, 115, 116, 117, 96, 148, 149, 150,
+ 158, 106, 155, 159, 97, 163, 118, -76, -76, -76,
+ -76, -76, -76, -76, -76, 160, 164, -76, -76, 99,
+ 13, 14, 15, 16, 17, 18, 19, 20, 91, 106,
+ 21, 22, 14, 15, 140, 17, 18, 19, 20, 168,
+ 175, 21, 22, 177, 181, 182, 183, 32, 187, 167,
+ 188, 169, 170, 171, 185, 189, 53, 51, 32, 176,
+ 75, 178, 121, 0, 133, 162, 0, 0, 0, 0,
+ 184
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 1, 67, 68, 10, 93, 94, 76, 3, 76, 14,
+ 28, 81, 13, 81, 15, 104, 34, 18, 3, 32,
+ 33, 23, 26, 27, 90, 91, 30, 32, 33, 31,
+ 78, 35, 80, 0, 1, 31, 102, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 31, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 78, 26,
+ 80, 26, 69, 133, 31, 133, 31, 156, 26, 27,
+ 29, 0, 1, 32, 33, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 150, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 0, 26, 164, 100,
+ 77, 78, 31, 80, 77, 78, 31, 80, 31, 32,
+ 33, 0, 1, 31, 115, 4, 5, 6, 7, 8,
+ 9, 10, 11, 26, 27, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 31, 26, 26, 31, 0,
+ 1, 26, 31, 4, 5, 6, 7, 8, 9, 10,
+ 11, 26, 31, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 1, 1, 26, 31, 32, 33, 31,
+ 31, 0, 1, 31, 31, 4, 5, 6, 7, 8,
+ 9, 10, 11, 31, 185, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 31, 1, 26, 31, 31,
+ 5, 6, 31, 8, 9, 10, 11, 12, 31, 14,
+ 15, 16, 17, 18, 19, 20, 31, 31, 31, 25,
+ 1, 26, 26, 13, 1, 26, 31, 4, 5, 6,
+ 7, 8, 9, 10, 11, 31, 14, 14, 15, 16,
+ 4, 5, 6, 7, 8, 9, 10, 11, 33, 26,
+ 14, 15, 5, 6, 31, 8, 9, 10, 11, 31,
+ 31, 14, 15, 31, 31, 31, 31, 31, 31, 151,
+ 31, 153, 154, 155, 34, 31, 7, 6, 31, 161,
+ 37, 163, 76, -1, 79, 116, -1, -1, -1, -1,
+ 172
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 31, 37, 38, 39, 63, 81, 26, 27,
+ 79, 0, 1, 4, 5, 6, 7, 8, 9, 10,
+ 11, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 26, 31, 40, 41, 43, 44, 45, 46, 52,
+ 53, 55, 59, 61, 64, 65, 67, 69, 70, 71,
+ 80, 39, 31, 38, 81, 31, 79, 31, 79, 26,
+ 85, 31, 79, 26, 26, 26, 27, 30, 35, 83,
+ 84, 31, 1, 1, 47, 47, 56, 58, 62, 76,
+ 68, 74, 31, 31, 31, 31, 31, 31, 83, 83,
+ 32, 33, 81, 28, 34, 31, 31, 1, 12, 16,
+ 18, 19, 20, 21, 22, 24, 26, 31, 42, 48,
+ 49, 72, 73, 75, 17, 18, 19, 20, 31, 42,
+ 57, 73, 75, 41, 54, 80, 41, 55, 60, 67,
+ 80, 23, 31, 74, 77, 41, 55, 66, 67, 80,
+ 31, 42, 75, 29, 83, 83, 84, 84, 31, 31,
+ 25, 79, 78, 79, 83, 26, 84, 50, 1, 13,
+ 31, 79, 78, 26, 14, 82, 83, 82, 31, 82,
+ 82, 82, 84, 26, 31, 31, 82, 31, 82, 83,
+ 31, 31, 31, 31, 82, 34, 51, 31, 31, 31,
+ 79
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
+
+#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# 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 == '"')
+ {
+ YYSIZE_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
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { 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;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* 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 = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+ case 53: /* "choice_entry" */
+
+ {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+ (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
+ if (current_menu == (yyvaluep->menu))
+ menu_end_menu();
+};
+
+ break;
+ case 59: /* "if_entry" */
+
+ {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+ (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
+ if (current_menu == (yyvaluep->menu))
+ menu_end_menu();
+};
+
+ break;
+ case 65: /* "menu_entry" */
+
+ {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+ (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
+ if (current_menu == (yyvaluep->menu))
+ menu_end_menu();
+};
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 10:
+
+ { zconf_error("unexpected end statement"); ;}
+ break;
+
+ case 11:
+
+ { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;}
+ break;
+
+ case 12:
+
+ {
+ zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
+;}
+ break;
+
+ case 13:
+
+ { zconf_error("invalid statement"); ;}
+ break;
+
+ case 28:
+
+ { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;}
+ break;
+
+ case 29:
+
+ { zconf_error("invalid option"); ;}
+ break;
+
+ case 30:
+
+ {
+ struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+;}
+ break;
+
+ case 31:
+
+ {
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 32:
+
+ {
+ struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+;}
+ break;
+
+ case 33:
+
+ {
+ if (current_entry->prompt)
+ current_entry->prompt->type = P_MENU;
+ else
+ zconfprint("warning: menuconfig statement without prompt");
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 41:
+
+ {
+ menu_set_type((yyvsp[(1) - (3)].id)->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ (yyvsp[(1) - (3)].id)->stype);
+;}
+ break;
+
+ case 42:
+
+ {
+ menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 43:
+
+ {
+ menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
+ if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN)
+ menu_set_type((yyvsp[(1) - (4)].id)->stype);
+ printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ (yyvsp[(1) - (4)].id)->stype);
+;}
+ break;
+
+ case 44:
+
+ {
+ menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+ printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 45:
+
+ {
+ menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
+ printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 48:
+
+ {
+ const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
+ if (id && id->flags & TF_OPTION)
+ menu_add_option(id->token, (yyvsp[(3) - (3)].string));
+ else
+ zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string));
+ free((yyvsp[(2) - (3)].string));
+;}
+ break;
+
+ case 49:
+
+ { (yyval.string) = NULL; ;}
+ break;
+
+ case 50:
+
+ { (yyval.string) = (yyvsp[(2) - (2)].string); ;}
+ break;
+
+ case 51:
+
+ {
+ struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
+ sym->flags |= SYMBOL_AUTO;
+ menu_add_entry(sym);
+ menu_add_expr(P_CHOICE, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 52:
+
+ {
+ (yyval.menu) = menu_add_menu();
+;}
+ break;
+
+ case 53:
+
+ {
+ if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
+ }
+;}
+ break;
+
+ case 61:
+
+ {
+ menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 62:
+
+ {
+ if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
+ menu_set_type((yyvsp[(1) - (3)].id)->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ (yyvsp[(1) - (3)].id)->stype);
+ } else
+ YYERROR;
+;}
+ break;
+
+ case 63:
+
+ {
+ current_entry->sym->flags |= SYMBOL_OPTIONAL;
+ printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 64:
+
+ {
+ if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
+ menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+ printd(DEBUG_PARSE, "%s:%d:default\n",
+ zconf_curname(), zconf_lineno());
+ } else
+ YYERROR;
+;}
+ break;
+
+ case 67:
+
+ {
+ printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
+ menu_add_entry(NULL);
+ menu_add_dep((yyvsp[(2) - (3)].expr));
+ (yyval.menu) = menu_add_menu();
+;}
+ break;
+
+ case 68:
+
+ {
+ if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
+ }
+;}
+ break;
+
+ case 74:
+
+ {
+ menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+;}
+ break;
+
+ case 75:
+
+ {
+ menu_add_entry(NULL);
+ menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+ printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 76:
+
+ {
+ (yyval.menu) = menu_add_menu();
+;}
+ break;
+
+ case 77:
+
+ {
+ if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
+ }
+;}
+ break;
+
+ case 83:
+
+ {
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+ zconf_nextfile((yyvsp[(2) - (3)].string));
+;}
+ break;
+
+ case 84:
+
+ {
+ menu_add_entry(NULL);
+ menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL);
+ printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 85:
+
+ {
+ menu_end_entry();
+;}
+ break;
+
+ case 86:
+
+ {
+ printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
+ zconf_starthelp();
+;}
+ break;
+
+ case 87:
+
+ {
+ current_entry->help = (yyvsp[(2) - (2)].string);
+;}
+ break;
+
+ case 92:
+
+ {
+ menu_add_dep((yyvsp[(3) - (4)].expr));
+ printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
+;}
+ break;
+
+ case 96:
+
+ {
+ menu_add_visibility((yyvsp[(2) - (2)].expr));
+;}
+ break;
+
+ case 98:
+
+ {
+ menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
+;}
+ break;
+
+ case 101:
+
+ { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
+ break;
+
+ case 102:
+
+ { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
+ break;
+
+ case 103:
+
+ { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
+ break;
+
+ case 106:
+
+ { (yyval.expr) = NULL; ;}
+ break;
+
+ case 107:
+
+ { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
+ break;
+
+ case 108:
+
+ { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;}
+ break;
+
+ case 109:
+
+ { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
+ break;
+
+ case 110:
+
+ { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
+ break;
+
+ case 111:
+
+ { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
+ break;
+
+ case 112:
+
+ { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;}
+ break;
+
+ case 113:
+
+ { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+ break;
+
+ case 114:
+
+ { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+ break;
+
+ case 115:
+
+ { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;}
+ break;
+
+ case 116:
+
+ { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;}
+ break;
+
+ case 117:
+
+ { (yyval.string) = NULL; ;}
+ break;
+
+
+
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+
+
+void conf_parse(const char *name)
+{
+ struct symbol *sym;
+ int i;
+
+ zconf_initscan(name);
+
+ sym_init();
+ _menu_init();
+ 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 (getenv("ZCONF_DEBUG"))
+ zconfdebug = 1;
+ 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));
+ }
+
+ rootmenu.prompt->text = _(rootmenu.prompt->text);
+ rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
+
+ menu_finalize(&rootmenu);
+ for_all_symbols(i, sym) {
+ if (sym_check_deps(sym))
+ zconfnerrs++;
+ }
+ if (zconfnerrs)
+ exit(1);
+ sym_set_change_count(1);
+}
+
+static const char *zconf_tokenname(int token)
+{
+ switch (token) {
+ case T_MENU: return "menu";
+ case T_ENDMENU: return "endmenu";
+ case T_CHOICE: return "choice";
+ case T_ENDCHOICE: return "endchoice";
+ case T_IF: return "if";
+ case T_ENDIF: return "endif";
+ case T_DEPENDS: return "depends";
+ case T_VISIBLE: return "visible";
+ }
+ return "<token>";
+}
+
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
+{
+ if (id->token != endtoken) {
+ zconf_error("unexpected '%s' within %s block",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ if (current_menu->file != current_file) {
+ zconf_error("'%s' in different file than '%s'",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ fprintf(stderr, "%s:%d: location of the '%s'\n",
+ current_menu->file->name, current_menu->lineno,
+ zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ return true;
+}
+
+static void zconfprint(const char *err, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconf_error(const char *err, ...)
+{
+ va_list ap;
+
+ zconfnerrs++;
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconferror(const char *err)
+{
+ fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+}
+
+static void print_quoted_string(FILE *out, const char *str)
+{
+ const char *p;
+ int len;
+
+ putc('"', out);
+ while ((p = strchr(str, '"'))) {
+ len = p - str;
+ if (len)
+ fprintf(out, "%.*s", len, str);
+ fputs("\\\"", out);
+ str = p + 1;
+ }
+ fputs(str, out);
+ putc('"', out);
+}
+
+static void print_symbol(FILE *out, struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ struct property *prop;
+
+ if (sym_is_choice(sym))
+ fprintf(out, "\nchoice\n");
+ else
+ fprintf(out, "\nconfig %s\n", sym->name);
+ switch (sym->type) {
+ case S_BOOLEAN:
+ fputs(" boolean\n", out);
+ break;
+ case S_TRISTATE:
+ fputs(" tristate\n", out);
+ break;
+ case S_STRING:
+ fputs(" string\n", out);
+ break;
+ case S_INT:
+ fputs(" integer\n", out);
+ break;
+ case S_HEX:
+ fputs(" hex\n", out);
+ break;
+ default:
+ fputs(" ???\n", out);
+ break;
+ }
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ switch (prop->type) {
+ case P_PROMPT:
+ fputs(" prompt ", out);
+ print_quoted_string(out, prop->text);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_DEFAULT:
+ fputs( " default ", out);
+ expr_fprint(prop->expr, out);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_CHOICE:
+ fputs(" #choice value\n", out);
+ break;
+ case P_SELECT:
+ fputs( " select ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
+ case P_RANGE:
+ fputs( " range ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
+ case P_MENU:
+ fputs( " menu ", out);
+ print_quoted_string(out, prop->text);
+ fputc('\n', out);
+ break;
+ default:
+ fprintf(out, " unknown prop %d!\n", prop->type);
+ break;
+ }
+ }
+ if (menu->help) {
+ int len = strlen(menu->help);
+ while (menu->help[--len] == '\n')
+ menu->help[len] = 0;
+ fprintf(out, " help\n%s\n", menu->help);
+ }
+}
+
+void zconfdump(FILE *out)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct menu *menu;
+
+ menu = rootmenu.list;
+ while (menu) {
+ if ((sym = menu->sym))
+ print_symbol(out, menu);
+ else if ((prop = menu->prompt)) {
+ switch (prop->type) {
+ case P_COMMENT:
+ fputs("\ncomment ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ case P_MENU:
+ fputs("\nmenu ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ default:
+ ;
+ }
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" depends ", out);
+ expr_fprint(prop->visible.expr, out);
+ fputc('\n', out);
+ }
+ }
+
+ if (menu->list)
+ menu = menu->list;
+ else if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->prompt && menu->prompt->type == P_MENU)
+ fputs("\nendmenu\n", out);
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+}
+
+#include "zconf.lex.c"
+#include "util.c"
+#include "confdata.c"
+#include "expr.c"
+#include "symbol.c"
+#include "menu.c"
+
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
new file mode 100644
index 0000000..864da07
--- /dev/null
+++ b/scripts/kconfig/zconf.y
@@ -0,0 +1,740 @@
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "lkc.h"
+
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
+
+#define PRINTD 0x0001
+#define DEBUG_PARSE 0x0002
+
+int cdebug = PRINTD;
+
+extern int zconflex(void);
+static void zconfprint(const char *err, ...);
+static void zconf_error(const char *err, ...);
+static void zconferror(const char *err);
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
+
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
+
+static struct menu *current_menu, *current_entry;
+
+%}
+%expect 30
+
+%union
+{
+ char *string;
+ struct file *file;
+ struct symbol *symbol;
+ struct expr *expr;
+ struct menu *menu;
+ const struct kconf_id *id;
+}
+
+%token <id>T_MAINMENU
+%token <id>T_MENU
+%token <id>T_ENDMENU
+%token <id>T_SOURCE
+%token <id>T_CHOICE
+%token <id>T_ENDCHOICE
+%token <id>T_COMMENT
+%token <id>T_CONFIG
+%token <id>T_MENUCONFIG
+%token <id>T_HELP
+%token <string> T_HELPTEXT
+%token <id>T_IF
+%token <id>T_ENDIF
+%token <id>T_DEPENDS
+%token <id>T_OPTIONAL
+%token <id>T_PROMPT
+%token <id>T_TYPE
+%token <id>T_DEFAULT
+%token <id>T_SELECT
+%token <id>T_RANGE
+%token <id>T_VISIBLE
+%token <id>T_OPTION
+%token <id>T_ON
+%token <string> T_WORD
+%token <string> T_WORD_QUOTE
+%token T_UNEQUAL
+%token T_CLOSE_PAREN
+%token T_OPEN_PAREN
+%token T_EOL
+
+%left T_OR
+%left T_AND
+%left T_EQUAL T_UNEQUAL
+%nonassoc T_NOT
+
+%type <string> prompt
+%type <symbol> symbol
+%type <expr> expr
+%type <expr> if_expr
+%type <id> end
+%type <id> option_name
+%type <menu> if_entry menu_entry choice_entry
+%type <string> symbol_option_arg word_opt
+
+%destructor {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+ $$->file->name, $$->lineno);
+ if (current_menu == $$)
+ menu_end_menu();
+} if_entry menu_entry choice_entry
+
+%{
+/* Include zconf.hash.c here so it can see the token constants. */
+#include "zconf.hash.c"
+%}
+
+%%
+input: nl start | start;
+
+start: mainmenu_stmt stmt_list | stmt_list;
+
+stmt_list:
+ /* empty */
+ | stmt_list common_stmt
+ | stmt_list choice_stmt
+ | stmt_list menu_stmt
+ | stmt_list end { zconf_error("unexpected end statement"); }
+ | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
+ | stmt_list option_name error T_EOL
+{
+ zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
+}
+ | stmt_list error T_EOL { zconf_error("invalid statement"); }
+;
+
+option_name:
+ T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
+;
+
+common_stmt:
+ T_EOL
+ | if_stmt
+ | comment_stmt
+ | config_stmt
+ | menuconfig_stmt
+ | source_stmt
+;
+
+option_error:
+ T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
+ | error T_EOL { zconf_error("invalid option"); }
+;
+
+
+/* config/menuconfig entry */
+
+config_entry_start: T_CONFIG T_WORD T_EOL
+{
+ struct symbol *sym = sym_lookup($2, 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+config_stmt: config_entry_start config_option_list
+{
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
+menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
+{
+ struct symbol *sym = sym_lookup($2, 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+menuconfig_stmt: menuconfig_entry_start config_option_list
+{
+ if (current_entry->prompt)
+ current_entry->prompt->type = P_MENU;
+ else
+ zconfprint("warning: menuconfig statement without prompt");
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
+config_option_list:
+ /* empty */
+ | config_option_list config_option
+ | config_option_list symbol_option
+ | config_option_list depends
+ | config_option_list help
+ | config_option_list option_error
+ | config_option_list T_EOL
+;
+
+config_option: T_TYPE prompt_stmt_opt T_EOL
+{
+ menu_set_type($1->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ $1->stype);
+};
+
+config_option: T_PROMPT prompt if_expr T_EOL
+{
+ menu_add_prompt(P_PROMPT, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_DEFAULT expr if_expr T_EOL
+{
+ menu_add_expr(P_DEFAULT, $2, $3);
+ if ($1->stype != S_UNKNOWN)
+ menu_set_type($1->stype);
+ printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ $1->stype);
+};
+
+config_option: T_SELECT T_WORD if_expr T_EOL
+{
+ menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
+ printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_RANGE symbol symbol if_expr T_EOL
+{
+ menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
+ 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
+{
+ const 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 word_opt T_EOL
+{
+ struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
+ sym->flags |= SYMBOL_AUTO;
+ menu_add_entry(sym);
+ menu_add_expr(P_CHOICE, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+};
+
+choice_entry: choice choice_option_list
+{
+ $$ = menu_add_menu();
+};
+
+choice_end: end
+{
+ if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+choice_stmt: choice_entry choice_block choice_end
+;
+
+choice_option_list:
+ /* empty */
+ | choice_option_list choice_option
+ | choice_option_list depends
+ | choice_option_list help
+ | choice_option_list T_EOL
+ | choice_option_list option_error
+;
+
+choice_option: T_PROMPT prompt if_expr T_EOL
+{
+ menu_add_prompt(P_PROMPT, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_TYPE prompt_stmt_opt T_EOL
+{
+ if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
+ menu_set_type($1->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ $1->stype);
+ } else
+ YYERROR;
+};
+
+choice_option: T_OPTIONAL T_EOL
+{
+ current_entry->sym->flags |= SYMBOL_OPTIONAL;
+ printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_DEFAULT T_WORD if_expr T_EOL
+{
+ if ($1->stype == S_UNKNOWN) {
+ menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
+ printd(DEBUG_PARSE, "%s:%d:default\n",
+ zconf_curname(), zconf_lineno());
+ } else
+ YYERROR;
+};
+
+choice_block:
+ /* empty */
+ | choice_block common_stmt
+;
+
+/* if entry */
+
+if_entry: T_IF expr nl
+{
+ printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
+ menu_add_entry(NULL);
+ menu_add_dep($2);
+ $$ = menu_add_menu();
+};
+
+if_end: end
+{
+ if (zconf_endtoken($1, T_IF, T_ENDIF)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+if_stmt: if_entry if_block if_end
+;
+
+if_block:
+ /* empty */
+ | if_block common_stmt
+ | if_block menu_stmt
+ | if_block choice_stmt
+;
+
+/* mainmenu entry */
+
+mainmenu_stmt: T_MAINMENU prompt nl
+{
+ menu_add_prompt(P_MENU, $2, NULL);
+};
+
+/* menu entry */
+
+menu: T_MENU prompt T_EOL
+{
+ menu_add_entry(NULL);
+ menu_add_prompt(P_MENU, $2, NULL);
+ printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
+};
+
+menu_entry: menu visibility_list depends_list
+{
+ $$ = menu_add_menu();
+};
+
+menu_end: end
+{
+ if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+menu_stmt: menu_entry menu_block menu_end
+;
+
+menu_block:
+ /* empty */
+ | menu_block common_stmt
+ | menu_block menu_stmt
+ | menu_block choice_stmt
+;
+
+source_stmt: T_SOURCE prompt T_EOL
+{
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
+ zconf_nextfile($2);
+};
+
+/* comment entry */
+
+comment: T_COMMENT prompt T_EOL
+{
+ menu_add_entry(NULL);
+ menu_add_prompt(P_COMMENT, $2, NULL);
+ printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
+};
+
+comment_stmt: comment depends_list
+{
+ menu_end_entry();
+};
+
+/* help option */
+
+help_start: T_HELP T_EOL
+{
+ printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
+ zconf_starthelp();
+};
+
+help: help_start T_HELPTEXT
+{
+ current_entry->help = $2;
+};
+
+/* depends option */
+
+depends_list:
+ /* empty */
+ | depends_list depends
+ | depends_list T_EOL
+ | depends_list option_error
+;
+
+depends: T_DEPENDS T_ON expr T_EOL
+{
+ menu_add_dep($3);
+ printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
+};
+
+/* visibility option */
+
+visibility_list:
+ /* empty */
+ | visibility_list visible
+ | visibility_list T_EOL
+;
+
+visible: T_VISIBLE if_expr
+{
+ menu_add_visibility($2);
+};
+
+/* prompt statement */
+
+prompt_stmt_opt:
+ /* empty */
+ | prompt if_expr
+{
+ menu_add_prompt(P_PROMPT, $1, $2);
+};
+
+prompt: T_WORD
+ | T_WORD_QUOTE
+;
+
+end: T_ENDMENU T_EOL { $$ = $1; }
+ | T_ENDCHOICE T_EOL { $$ = $1; }
+ | T_ENDIF T_EOL { $$ = $1; }
+;
+
+nl:
+ T_EOL
+ | nl T_EOL
+;
+
+if_expr: /* empty */ { $$ = NULL; }
+ | T_IF expr { $$ = $2; }
+;
+
+expr: symbol { $$ = expr_alloc_symbol($1); }
+ | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
+ | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
+ | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
+ | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
+ | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
+ | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
+;
+
+symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
+ | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
+;
+
+word_opt: /* empty */ { $$ = NULL; }
+ | T_WORD
+
+%%
+
+void conf_parse(const char *name)
+{
+ struct symbol *sym;
+ int i;
+
+ zconf_initscan(name);
+
+ sym_init();
+ _menu_init();
+ 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 (getenv("ZCONF_DEBUG"))
+ zconfdebug = 1;
+ 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));
+ }
+
+ rootmenu.prompt->text = _(rootmenu.prompt->text);
+ rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
+
+ menu_finalize(&rootmenu);
+ for_all_symbols(i, sym) {
+ if (sym_check_deps(sym))
+ zconfnerrs++;
+ }
+ if (zconfnerrs)
+ exit(1);
+ sym_set_change_count(1);
+}
+
+static const char *zconf_tokenname(int token)
+{
+ switch (token) {
+ case T_MENU: return "menu";
+ case T_ENDMENU: return "endmenu";
+ case T_CHOICE: return "choice";
+ case T_ENDCHOICE: return "endchoice";
+ case T_IF: return "if";
+ case T_ENDIF: return "endif";
+ case T_DEPENDS: return "depends";
+ case T_VISIBLE: return "visible";
+ }
+ return "<token>";
+}
+
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
+{
+ if (id->token != endtoken) {
+ zconf_error("unexpected '%s' within %s block",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ if (current_menu->file != current_file) {
+ zconf_error("'%s' in different file than '%s'",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ fprintf(stderr, "%s:%d: location of the '%s'\n",
+ current_menu->file->name, current_menu->lineno,
+ zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ return true;
+}
+
+static void zconfprint(const char *err, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconf_error(const char *err, ...)
+{
+ va_list ap;
+
+ zconfnerrs++;
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconferror(const char *err)
+{
+ fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+}
+
+static void print_quoted_string(FILE *out, const char *str)
+{
+ const char *p;
+ int len;
+
+ putc('"', out);
+ while ((p = strchr(str, '"'))) {
+ len = p - str;
+ if (len)
+ fprintf(out, "%.*s", len, str);
+ fputs("\\\"", out);
+ str = p + 1;
+ }
+ fputs(str, out);
+ putc('"', out);
+}
+
+static void print_symbol(FILE *out, struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ struct property *prop;
+
+ if (sym_is_choice(sym))
+ fprintf(out, "\nchoice\n");
+ else
+ fprintf(out, "\nconfig %s\n", sym->name);
+ switch (sym->type) {
+ case S_BOOLEAN:
+ fputs(" boolean\n", out);
+ break;
+ case S_TRISTATE:
+ fputs(" tristate\n", out);
+ break;
+ case S_STRING:
+ fputs(" string\n", out);
+ break;
+ case S_INT:
+ fputs(" integer\n", out);
+ break;
+ case S_HEX:
+ fputs(" hex\n", out);
+ break;
+ default:
+ fputs(" ???\n", out);
+ break;
+ }
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ switch (prop->type) {
+ case P_PROMPT:
+ fputs(" prompt ", out);
+ print_quoted_string(out, prop->text);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_DEFAULT:
+ fputs( " default ", out);
+ expr_fprint(prop->expr, out);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_CHOICE:
+ fputs(" #choice value\n", out);
+ break;
+ case P_SELECT:
+ fputs( " select ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
+ case P_RANGE:
+ fputs( " range ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
+ case P_MENU:
+ fputs( " menu ", out);
+ print_quoted_string(out, prop->text);
+ fputc('\n', out);
+ break;
+ default:
+ fprintf(out, " unknown prop %d!\n", prop->type);
+ break;
+ }
+ }
+ if (menu->help) {
+ int len = strlen(menu->help);
+ while (menu->help[--len] == '\n')
+ menu->help[len] = 0;
+ fprintf(out, " help\n%s\n", menu->help);
+ }
+}
+
+void zconfdump(FILE *out)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct menu *menu;
+
+ menu = rootmenu.list;
+ while (menu) {
+ if ((sym = menu->sym))
+ print_symbol(out, menu);
+ else if ((prop = menu->prompt)) {
+ switch (prop->type) {
+ case P_COMMENT:
+ fputs("\ncomment ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ case P_MENU:
+ fputs("\nmenu ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ default:
+ ;
+ }
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" depends ", out);
+ expr_fprint(prop->visible.expr, out);
+ fputc('\n', out);
+ }
+ }
+
+ if (menu->list)
+ menu = menu->list;
+ else if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->prompt && menu->prompt->type == P_MENU)
+ fputs("\nendmenu\n", out);
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+}
+
+#include "zconf.lex.c"
+#include "util.c"
+#include "confdata.c"
+#include "expr.c"
+#include "symbol.c"
+#include "menu.c"
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
new file mode 100644
index 0000000..b3d907e
--- /dev/null
+++ b/scripts/link-vmlinux.sh
@@ -0,0 +1,226 @@
+#!/bin/sh
+#
+# link vmlinux
+#
+# vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_INIT) and
+# $(KBUILD_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 $(KBUILD_VMLINUX_INIT) must be first.
+#
+# vmlinux
+# ^
+# |
+# +-< $(KBUILD_VMLINUX_INIT)
+# | +--< init/version.o + more
+# |
+# +--< $(KBUILD_VMLINUX_MAIN)
+# | +--< drivers/built-in.o mm/built-in.o + more
+# |
+# +-< ${kallsymso} (see description in KALLSYMS section)
+#
+# vmlinux version (uname -v) cannot be updated during normal
+# descending-into-subdirs phase since we do not yet know if we need to
+# update vmlinux.
+# Therefore this step is delayed until just before final link of vmlinux.
+#
+# System.map is generated to document addresses of all kernel symbols
+
+# Error out on error
+set -e
+
+# Nice output in kbuild format
+# Will be supressed by "make -s"
+info()
+{
+ if [ "${quiet}" != "silent_" ]; then
+ printf " %-7s %s\n" ${1} ${2}
+ fi
+}
+
+# Link of vmlinux.o used for section mismatch analysis
+# ${1} output file
+modpost_link()
+{
+ ${LD} ${LDFLAGS} -r -o ${1} ${KBUILD_VMLINUX_INIT} \
+ --start-group ${KBUILD_VMLINUX_MAIN} --end-group
+}
+
+# Link of vmlinux
+# ${1} - optional extra .o files
+# ${2} - output file
+vmlinux_link()
+{
+ local lds="${objtree}/${KBUILD_LDS}"
+
+ if [ "${SRCARCH}" != "um" ]; then
+ ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
+ -T ${lds} ${KBUILD_VMLINUX_INIT} \
+ --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1}
+ else
+ ${CC} ${CFLAGS_vmlinux} -o ${2} \
+ -Wl,-T,${lds} ${KBUILD_VMLINUX_INIT} \
+ -Wl,--start-group \
+ ${KBUILD_VMLINUX_MAIN} \
+ -Wl,--end-group \
+ -lutil ${1}
+ rm -f linux
+ fi
+}
+
+
+# Create ${2} .o file with all symbols from the ${1} object file
+kallsyms()
+{
+ info KSYM ${2}
+ local kallsymopt;
+
+ if [ -n "${CONFIG_SYMBOL_PREFIX}" ]; then
+ kallsymopt="${kallsymopt} \
+ --symbol-prefix=${CONFIG_SYMBOL_PREFIX}"
+ fi
+
+ if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
+ kallsymopt="${kallsymopt} --all-symbols"
+ fi
+
+ local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
+ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
+
+ ${NM} -n ${1} | \
+ scripts/kallsyms ${kallsymopt} | \
+ ${CC} ${aflags} -c -o ${2} -x assembler-with-cpp -
+}
+
+# Create map file with all symbols from ${1}
+# See mksymap for additional details
+mksysmap()
+{
+ ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
+}
+
+sortextable()
+{
+ ${objtree}/scripts/sortextable ${1}
+}
+
+# Delete output files in case of error
+trap cleanup SIGHUP SIGINT SIGQUIT SIGTERM ERR
+cleanup()
+{
+ rm -f .old_version
+ rm -f .tmp_System.map
+ rm -f .tmp_kallsyms*
+ rm -f .tmp_version
+ rm -f .tmp_vmlinux*
+ rm -f System.map
+ rm -f vmlinux
+ rm -f vmlinux.o
+}
+
+#
+#
+# Use "make V=1" to debug this script
+case "${KBUILD_VERBOSE}" in
+*1*)
+ set -x
+ ;;
+esac
+
+if [ "$1" = "clean" ]; then
+ cleanup
+ exit 0
+fi
+
+# We need access to CONFIG_ symbols
+. ./.config
+
+#link vmlinux.o
+info LD vmlinux.o
+modpost_link vmlinux.o
+
+# modpost vmlinux.o to check for section mismatches
+${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
+
+# Update version
+info GEN .version
+if [ ! -r .version ]; then
+ rm -f .version;
+ echo 1 >.version;
+else
+ mv .version .old_version;
+ expr 0$(cat .old_version) + 1 >.version;
+fi;
+
+# final build of init/
+${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init
+
+kallsymso=""
+kallsyms_vmlinux=""
+if [ -n "${CONFIG_KALLSYMS}" ]; then
+
+ # kallsyms support
+ # Generate section listing all symbols and add it into vmlinux
+ # It's a three step process:
+ # 1) Link .tmp_vmlinux1 so it has all symbols and sections,
+ # but __kallsyms is empty.
+ # Running kallsyms on that gives us .tmp_kallsyms1.o with
+ # the right size
+ # 2) Link .tmp_vmlinux2 so it now has a __kallsyms section of
+ # the right size, but due to the added section, some
+ # addresses have shifted.
+ # From here, we generate a correct .tmp_kallsyms2.o
+ # 2a) We may use an extra pass as this has been necessary to
+ # woraround some alignment related bugs.
+ # KALLSYMS_EXTRA_PASS=1 is used to trigger this.
+ # 3) The correct ${kallsymso} is linked into the final vmlinux.
+ #
+ # a) Verify that the System.map from vmlinux matches the map from
+ # ${kallsymso}.
+
+ kallsymso=.tmp_kallsyms2.o
+ kallsyms_vmlinux=.tmp_vmlinux2
+
+ # step 1
+ vmlinux_link "" .tmp_vmlinux1
+ kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o
+
+ # step 2
+ vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2
+ kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o
+
+ # step 2a
+ if [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
+ kallsymso=.tmp_kallsyms3.o
+ kallsyms_vmlinux=.tmp_vmlinux3
+
+ vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3
+
+ kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o
+ fi
+fi
+
+info LD vmlinux
+vmlinux_link "${kallsymso}" vmlinux
+
+if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
+ info SORTEX vmlinux
+ sortextable vmlinux
+fi
+
+info SYSMAP System.map
+mksysmap vmlinux System.map
+
+# step a (see comment above)
+if [ -n "${CONFIG_KALLSYMS}" ]; then
+ mksysmap ${kallsyms_vmlinux} .tmp_System.map
+
+ if ! cmp -s System.map .tmp_System.map; then
+ echo >&2 Inconsistent kallsyms data
+ echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
+ cleanup
+ exit 1
+ fi
+fi
+
+# We made a new kernel - delete old version file
+rm -f .old_version
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
new file mode 100755
index 0000000..f221ddf
--- /dev/null
+++ b/scripts/mkcompile_h
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+TARGET=$1
+ARCH=$2
+SMP=$3
+PREEMPT=$4
+CC=$5
+
+vecho() { [ "${quiet}" = "silent_" ] || echo "$@" ; }
+
+# If compile.h exists already and we don't own autoconf.h
+# (i.e. we're not the same user who did make *config), don't
+# modify compile.h
+# So "sudo make install" won't change the "compiled by <user>"
+# do "compiled by root"
+
+if [ -r $TARGET -a ! -O include/generated/autoconf.h ]; then
+ vecho " SKIPPED $TARGET"
+ exit 0
+fi
+
+# Do not expand names
+set -f
+
+# Fix the language to get consistent output
+LC_ALL=C
+export LC_ALL
+
+if [ -z "$KBUILD_BUILD_VERSION" ]; then
+ if [ -r .version ]; then
+ VERSION=`cat .version`
+ else
+ VERSION=0
+ echo 0 > .version
+ fi
+else
+ VERSION=$KBUILD_BUILD_VERSION
+fi
+
+if [ -z "$KBUILD_BUILD_TIMESTAMP" ]; then
+ TIMESTAMP=`date`
+else
+ TIMESTAMP=$KBUILD_BUILD_TIMESTAMP
+fi
+if test -z "$KBUILD_BUILD_USER"; then
+ LINUX_COMPILE_BY=$(whoami | sed 's/\\/\\\\/')
+else
+ LINUX_COMPILE_BY=$KBUILD_BUILD_USER
+fi
+if test -z "$KBUILD_BUILD_HOST"; then
+ LINUX_COMPILE_HOST=`hostname`
+else
+ LINUX_COMPILE_HOST=$KBUILD_BUILD_HOST
+fi
+
+UTS_VERSION="#$VERSION"
+CONFIG_FLAGS=""
+if [ -n "$SMP" ] ; then CONFIG_FLAGS="SMP"; fi
+if [ -n "$PREEMPT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT"; fi
+UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"
+
+# Truncate to maximum length
+
+UTS_LEN=64
+UTS_TRUNCATE="cut -b -$UTS_LEN"
+
+# Generate a temporary compile.h
+
+( echo /\* This file is auto generated, version $VERSION \*/
+ if [ -n "$CONFIG_FLAGS" ] ; then echo "/* $CONFIG_FLAGS */"; fi
+
+ echo \#define UTS_MACHINE \"$ARCH\"
+
+ echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\"
+
+ echo \#define LINUX_COMPILE_BY \"`echo $LINUX_COMPILE_BY | $UTS_TRUNCATE`\"
+ echo \#define LINUX_COMPILE_HOST \"`echo $LINUX_COMPILE_HOST | $UTS_TRUNCATE`\"
+
+ echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\"
+) > .tmpcompile
+
+# Only replace the real compile.h if the new one is different,
+# in order to preserve the timestamp and avoid unnecessary
+# recompilations.
+# We don't consider the file changed if only the date/time changed.
+# A kernel config change will increase the generation number, thus
+# causing compile.h to be updated (including date/time) due to the
+# changed comment in the
+# first line.
+
+if [ -r $TARGET ] && \
+ grep -v 'UTS_VERSION' $TARGET > .tmpver.1 && \
+ grep -v 'UTS_VERSION' .tmpcompile > .tmpver.2 && \
+ cmp -s .tmpver.1 .tmpver.2; then
+ rm -f .tmpcompile
+else
+ vecho " UPD $TARGET"
+ mv -f .tmpcompile $TARGET
+fi
+rm -f .tmpver.1 .tmpver.2
diff --git a/scripts/mksysmap b/scripts/mksysmap
new file mode 100644
index 0000000..c1b6191
--- /dev/null
+++ b/scripts/mksysmap
@@ -0,0 +1,45 @@
+#!/bin/sh -x
+# Based on the vmlinux file create the System.map file
+# System.map is used by module-init tools and some debugging
+# tools to retrieve the actual addresses of symbols in the kernel.
+#
+# Usage
+# mksysmap vmlinux System.map
+
+
+#####
+# Generate System.map (actual filename passed as second argument)
+
+# $NM produces the following output:
+# f0081e80 T alloc_vfsmnt
+
+# The second row specify the type of the symbol:
+# A = Absolute
+# B = Uninitialised data (.bss)
+# C = Common symbol
+# D = Initialised data
+# G = Initialised data for small objects
+# I = Indirect reference to another symbol
+# N = Debugging symbol
+# R = Read only
+# S = Uninitialised data for small objects
+# T = Text code symbol
+# U = Undefined symbol
+# V = Weak symbol
+# W = Weak symbol
+# Corresponding small letters are local symbols
+
+# For System.map filter away:
+# a - local absolute symbols
+# U - undefined global symbols
+# N - debugging symbols
+# w - local weak symbols
+
+# readprofile starts reading symbols when _stext is found, and
+# continue until it finds a symbol which is not either of 'T', 't',
+# 'W' or 'w'. __crc_ are 'A' and placed in the middle
+# so we just ignore them to let readprofile continue to work.
+# (At least sparc64 has __crc_ in the middle).
+
+$NM -n $1 | grep -v '\( [aNUw] \)\|\(__crc_\)\|\( \$[adt]\)' > $2
+
diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore
new file mode 100644
index 0000000..33bae0d
--- /dev/null
+++ b/scripts/mod/.gitignore
@@ -0,0 +1,5 @@
+elfconfig.h
+mk_elfconfig
+modpost
+devicetable-offsets.h
+
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
new file mode 100644
index 0000000..9415b56
--- /dev/null
+++ b/scripts/mod/Makefile
@@ -0,0 +1,51 @@
+hostprogs-y := modpost mk_elfconfig
+always := $(hostprogs-y) empty.o
+
+modpost-objs := modpost.o file2alias.o sumversion.o
+
+devicetable-offsets-file := devicetable-offsets.h
+
+define sed-y
+ "/^->/{s:->#\(.*\):/* \1 */:; \
+ s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
+ s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+ s:->::; p;}"
+endef
+
+quiet_cmd_offsets = GEN $@
+define cmd_offsets
+ (set -e; \
+ echo "#ifndef __DEVICEVTABLE_OFFSETS_H__"; \
+ echo "#define __DEVICEVTABLE_OFFSETS_H__"; \
+ echo "/*"; \
+ echo " * DO NOT MODIFY."; \
+ echo " *"; \
+ echo " * This file was generated by Kbuild"; \
+ echo " *"; \
+ echo " */"; \
+ echo ""; \
+ sed -ne $(sed-y) $<; \
+ echo ""; \
+ echo "#endif" ) > $@
+endef
+
+# We use internal kbuild rules to avoid the "is up to date" message from make
+scripts/mod/devicetable-offsets.s: scripts/mod/devicetable-offsets.c FORCE
+ $(Q)mkdir -p $(dir $@)
+ $(call if_changed_dep,cc_s_c)
+
+$(obj)/$(devicetable-offsets-file): scripts/mod/devicetable-offsets.s
+ $(call cmd,offsets)
+
+# dependencies on generated files need to be listed explicitly
+
+$(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o: $(obj)/elfconfig.h
+$(obj)/file2alias.o: $(obj)/$(devicetable-offsets-file)
+
+quiet_cmd_elfconfig = MKELF $@
+ cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@
+
+$(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE
+ $(call if_changed,elfconfig)
+
+targets += elfconfig.h
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
new file mode 100644
index 0000000..b45260b
--- /dev/null
+++ b/scripts/mod/devicetable-offsets.c
@@ -0,0 +1,178 @@
+#include <linux/kbuild.h>
+#include <linux/mod_devicetable.h>
+
+#define DEVID(devid) DEFINE(SIZE_##devid, sizeof(struct devid))
+#define DEVID_FIELD(devid, field) \
+ DEFINE(OFF_##devid##_##field, offsetof(struct devid, field))
+
+int main(void)
+{
+ DEVID(usb_device_id);
+ DEVID_FIELD(usb_device_id, match_flags);
+ DEVID_FIELD(usb_device_id, idVendor);
+ DEVID_FIELD(usb_device_id, idProduct);
+ DEVID_FIELD(usb_device_id, bcdDevice_lo);
+ DEVID_FIELD(usb_device_id, bcdDevice_hi);
+ DEVID_FIELD(usb_device_id, bDeviceClass);
+ DEVID_FIELD(usb_device_id, bDeviceSubClass);
+ DEVID_FIELD(usb_device_id, bDeviceProtocol);
+ DEVID_FIELD(usb_device_id, bInterfaceClass);
+ DEVID_FIELD(usb_device_id, bInterfaceSubClass);
+ DEVID_FIELD(usb_device_id, bInterfaceProtocol);
+ DEVID_FIELD(usb_device_id, bInterfaceNumber);
+
+ DEVID(hid_device_id);
+ DEVID_FIELD(hid_device_id, bus);
+ DEVID_FIELD(hid_device_id, group);
+ DEVID_FIELD(hid_device_id, vendor);
+ DEVID_FIELD(hid_device_id, product);
+
+ DEVID(ieee1394_device_id);
+ DEVID_FIELD(ieee1394_device_id, match_flags);
+ DEVID_FIELD(ieee1394_device_id, vendor_id);
+ DEVID_FIELD(ieee1394_device_id, model_id);
+ DEVID_FIELD(ieee1394_device_id, specifier_id);
+ DEVID_FIELD(ieee1394_device_id, version);
+
+ DEVID(pci_device_id);
+ DEVID_FIELD(pci_device_id, vendor);
+ DEVID_FIELD(pci_device_id, device);
+ DEVID_FIELD(pci_device_id, subvendor);
+ DEVID_FIELD(pci_device_id, subdevice);
+ DEVID_FIELD(pci_device_id, class);
+ DEVID_FIELD(pci_device_id, class_mask);
+
+ DEVID(ccw_device_id);
+ DEVID_FIELD(ccw_device_id, match_flags);
+ DEVID_FIELD(ccw_device_id, cu_type);
+ DEVID_FIELD(ccw_device_id, cu_model);
+ DEVID_FIELD(ccw_device_id, dev_type);
+ DEVID_FIELD(ccw_device_id, dev_model);
+
+ DEVID(ap_device_id);
+ DEVID_FIELD(ap_device_id, dev_type);
+
+ DEVID(css_device_id);
+ DEVID_FIELD(css_device_id, type);
+
+ DEVID(serio_device_id);
+ DEVID_FIELD(serio_device_id, type);
+ DEVID_FIELD(serio_device_id, proto);
+ DEVID_FIELD(serio_device_id, id);
+ DEVID_FIELD(serio_device_id, extra);
+
+ DEVID(acpi_device_id);
+ DEVID_FIELD(acpi_device_id, id);
+
+ DEVID(pnp_device_id);
+ DEVID_FIELD(pnp_device_id, id);
+
+ DEVID(pnp_card_device_id);
+ DEVID_FIELD(pnp_card_device_id, devs);
+
+ DEVID(pcmcia_device_id);
+ DEVID_FIELD(pcmcia_device_id, match_flags);
+ DEVID_FIELD(pcmcia_device_id, manf_id);
+ DEVID_FIELD(pcmcia_device_id, card_id);
+ DEVID_FIELD(pcmcia_device_id, func_id);
+ DEVID_FIELD(pcmcia_device_id, function);
+ DEVID_FIELD(pcmcia_device_id, device_no);
+ DEVID_FIELD(pcmcia_device_id, prod_id_hash);
+
+ DEVID(of_device_id);
+ DEVID_FIELD(of_device_id, name);
+ DEVID_FIELD(of_device_id, type);
+ DEVID_FIELD(of_device_id, compatible);
+
+ DEVID(vio_device_id);
+ DEVID_FIELD(vio_device_id, type);
+ DEVID_FIELD(vio_device_id, compat);
+
+ DEVID(input_device_id);
+ DEVID_FIELD(input_device_id, flags);
+ DEVID_FIELD(input_device_id, bustype);
+ DEVID_FIELD(input_device_id, vendor);
+ DEVID_FIELD(input_device_id, product);
+ DEVID_FIELD(input_device_id, version);
+ DEVID_FIELD(input_device_id, evbit);
+ DEVID_FIELD(input_device_id, keybit);
+ DEVID_FIELD(input_device_id, relbit);
+ DEVID_FIELD(input_device_id, absbit);
+ DEVID_FIELD(input_device_id, mscbit);
+ DEVID_FIELD(input_device_id, ledbit);
+ DEVID_FIELD(input_device_id, sndbit);
+ DEVID_FIELD(input_device_id, ffbit);
+ DEVID_FIELD(input_device_id, swbit);
+
+ DEVID(eisa_device_id);
+ DEVID_FIELD(eisa_device_id, sig);
+
+ DEVID(parisc_device_id);
+ DEVID_FIELD(parisc_device_id, hw_type);
+ DEVID_FIELD(parisc_device_id, hversion);
+ DEVID_FIELD(parisc_device_id, hversion_rev);
+ DEVID_FIELD(parisc_device_id, sversion);
+
+ DEVID(sdio_device_id);
+ DEVID_FIELD(sdio_device_id, class);
+ DEVID_FIELD(sdio_device_id, vendor);
+ DEVID_FIELD(sdio_device_id, device);
+
+ DEVID(ssb_device_id);
+ DEVID_FIELD(ssb_device_id, vendor);
+ DEVID_FIELD(ssb_device_id, coreid);
+ DEVID_FIELD(ssb_device_id, revision);
+
+ DEVID(bcma_device_id);
+ DEVID_FIELD(bcma_device_id, manuf);
+ DEVID_FIELD(bcma_device_id, id);
+ DEVID_FIELD(bcma_device_id, rev);
+ DEVID_FIELD(bcma_device_id, class);
+
+ DEVID(virtio_device_id);
+ DEVID_FIELD(virtio_device_id, device);
+ DEVID_FIELD(virtio_device_id, vendor);
+
+ DEVID(hv_vmbus_device_id);
+ DEVID_FIELD(hv_vmbus_device_id, guid);
+
+ DEVID(i2c_device_id);
+ DEVID_FIELD(i2c_device_id, name);
+
+ DEVID(spi_device_id);
+ DEVID_FIELD(spi_device_id, name);
+
+ DEVID(dmi_system_id);
+ DEVID_FIELD(dmi_system_id, matches);
+
+ DEVID(platform_device_id);
+ DEVID_FIELD(platform_device_id, name);
+
+ DEVID(mdio_device_id);
+ DEVID_FIELD(mdio_device_id, phy_id);
+ DEVID_FIELD(mdio_device_id, phy_id_mask);
+
+ DEVID(zorro_device_id);
+ DEVID_FIELD(zorro_device_id, id);
+
+ DEVID(isapnp_device_id);
+ DEVID_FIELD(isapnp_device_id, vendor);
+ DEVID_FIELD(isapnp_device_id, function);
+
+ DEVID(ipack_device_id);
+ DEVID_FIELD(ipack_device_id, format);
+ DEVID_FIELD(ipack_device_id, vendor);
+ DEVID_FIELD(ipack_device_id, device);
+
+ DEVID(amba_id);
+ DEVID_FIELD(amba_id, id);
+ DEVID_FIELD(amba_id, mask);
+
+ DEVID(x86_cpu_id);
+ DEVID_FIELD(x86_cpu_id, feature);
+ DEVID_FIELD(x86_cpu_id, family);
+ DEVID_FIELD(x86_cpu_id, model);
+ DEVID_FIELD(x86_cpu_id, vendor);
+
+ return 0;
+}
diff --git a/scripts/mod/empty.c b/scripts/mod/empty.c
new file mode 100644
index 0000000..49839cc
--- /dev/null
+++ b/scripts/mod/empty.c
@@ -0,0 +1 @@
+/* empty file to figure out endianness / word size */
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
new file mode 100644
index 0000000..771ac17
--- /dev/null
+++ b/scripts/mod/file2alias.c
@@ -0,0 +1,1236 @@
+/* Simple code to turn various tables in an ELF file into alias definitions.
+ * This deals with kernel datastructures where they should be
+ * dealt with: in the kernel source.
+ *
+ * Copyright 2002-2003 Rusty Russell, IBM Corporation
+ * 2003 Kai Germaschewski
+ *
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "modpost.h"
+#include "devicetable-offsets.h"
+
+/* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
+ * use either stdint.h or inttypes.h for the rest. */
+#if KERNEL_ELFCLASS == ELFCLASS32
+typedef Elf32_Addr kernel_ulong_t;
+#define BITS_PER_LONG 32
+#else
+typedef Elf64_Addr kernel_ulong_t;
+#define BITS_PER_LONG 64
+#endif
+#ifdef __sun__
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+
+#include <ctype.h>
+#include <stdbool.h>
+
+typedef uint32_t __u32;
+typedef uint16_t __u16;
+typedef unsigned char __u8;
+
+/* Big exception to the "don't include kernel headers into userspace, which
+ * even potentially has different endianness and word sizes, since
+ * we handle those differences explicitly below */
+#include "../../include/linux/mod_devicetable.h"
+
+/* This array collects all instances that use the generic do_table */
+struct devtable {
+ const char *device_id; /* name of table, __mod_<name>_device_table. */
+ unsigned long id_size;
+ void *function;
+};
+
+#define ___cat(a,b) a ## b
+#define __cat(a,b) ___cat(a,b)
+
+/* we need some special handling for this host tool running eventually on
+ * Darwin. The Mach-O section handling is a bit different than ELF section
+ * handling. The differnces in detail are:
+ * a) we have segments which have sections
+ * b) we need a API call to get the respective section symbols */
+#if defined(__MACH__)
+#include <mach-o/getsect.h>
+
+#define INIT_SECTION(name) do { \
+ unsigned long name ## _len; \
+ char *__cat(pstart_,name) = getsectdata("__TEXT", \
+ #name, &__cat(name,_len)); \
+ char *__cat(pstop_,name) = __cat(pstart_,name) + \
+ __cat(name, _len); \
+ __cat(__start_,name) = (void *)__cat(pstart_,name); \
+ __cat(__stop_,name) = (void *)__cat(pstop_,name); \
+ } while (0)
+#define SECTION(name) __attribute__((section("__TEXT, " #name)))
+
+struct devtable **__start___devtable, **__stop___devtable;
+#else
+#define INIT_SECTION(name) /* no-op for ELF */
+#define SECTION(name) __attribute__((section(#name)))
+
+/* We construct a table of pointers in an ELF section (pointers generally
+ * go unpadded by gcc). ld creates boundary syms for us. */
+extern struct devtable *__start___devtable[], *__stop___devtable[];
+#endif /* __MACH__ */
+
+#if __GNUC__ == 3 && __GNUC_MINOR__ < 3
+# define __used __attribute__((__unused__))
+#else
+# define __used __attribute__((__used__))
+#endif
+
+/* Define a variable f that holds the value of field f of struct devid
+ * based at address m.
+ */
+#define DEF_FIELD(m, devid, f) \
+ typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f))
+/* Define a variable f that holds the address of field f of struct devid
+ * based at address m. Due to the way typeof works, for a field of type
+ * T[N] the variable has type T(*)[N], _not_ T*.
+ */
+#define DEF_FIELD_ADDR(m, devid, f) \
+ typeof(((struct devid *)0)->f) *f = ((m) + OFF_##devid##_##f)
+
+/* Add a table entry. We test function type matches while we're here. */
+#define ADD_TO_DEVTABLE(device_id, type, function) \
+ static struct devtable __cat(devtable,__LINE__) = { \
+ device_id + 0*sizeof((function)((const char *)NULL, \
+ (void *)NULL, \
+ (char *)NULL)), \
+ SIZE_##type, (function) }; \
+ static struct devtable *SECTION(__devtable) __used \
+ __cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__)
+
+#define ADD(str, sep, cond, field) \
+do { \
+ strcat(str, sep); \
+ if (cond) \
+ sprintf(str + strlen(str), \
+ sizeof(field) == 1 ? "%02X" : \
+ sizeof(field) == 2 ? "%04X" : \
+ sizeof(field) == 4 ? "%08X" : "", \
+ field); \
+ else \
+ sprintf(str + strlen(str), "*"); \
+} while(0)
+
+/* Always end in a wildcard, for future extension */
+static inline void add_wildcard(char *str)
+{
+ int len = strlen(str);
+
+ if (str[len - 1] != '*')
+ strcat(str + len, "*");
+}
+
+/**
+ * Check that sizeof(device_id type) are consistent with size of section
+ * in .o file. If in-consistent then userspace and kernel does not agree
+ * on actual size which is a bug.
+ * Also verify that the final entry in the table is all zeros.
+ * Ignore both checks if build host differ from target host and size differs.
+ **/
+static void device_id_check(const char *modname, const char *device_id,
+ unsigned long size, unsigned long id_size,
+ void *symval)
+{
+ int i;
+
+ if (size % id_size || size < id_size) {
+ fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
+ "of the size of section __mod_%s_device_table=%lu.\n"
+ "Fix definition of struct %s_device_id "
+ "in mod_devicetable.h\n",
+ modname, device_id, id_size, device_id, size, device_id);
+ }
+ /* Verify last one is a terminator */
+ for (i = 0; i < id_size; i++ ) {
+ if (*(uint8_t*)(symval+size-id_size+i)) {
+ fprintf(stderr,"%s: struct %s_device_id is %lu bytes. "
+ "The last of %lu is:\n",
+ modname, device_id, id_size, size / id_size);
+ for (i = 0; i < id_size; i++ )
+ fprintf(stderr,"0x%02x ",
+ *(uint8_t*)(symval+size-id_size+i) );
+ fprintf(stderr,"\n");
+ fatal("%s: struct %s_device_id is not terminated "
+ "with a NULL entry!\n", modname, device_id);
+ }
+ }
+}
+
+/* USB is special because the bcdDevice can be matched against a numeric range */
+/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */
+static void do_usb_entry(void *symval,
+ unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
+ unsigned char range_lo, unsigned char range_hi,
+ unsigned char max, struct module *mod)
+{
+ char alias[500];
+ DEF_FIELD(symval, usb_device_id, match_flags);
+ DEF_FIELD(symval, usb_device_id, idVendor);
+ DEF_FIELD(symval, usb_device_id, idProduct);
+ DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
+ DEF_FIELD(symval, usb_device_id, bDeviceClass);
+ DEF_FIELD(symval, usb_device_id, bDeviceSubClass);
+ DEF_FIELD(symval, usb_device_id, bDeviceProtocol);
+ DEF_FIELD(symval, usb_device_id, bInterfaceClass);
+ DEF_FIELD(symval, usb_device_id, bInterfaceSubClass);
+ DEF_FIELD(symval, usb_device_id, bInterfaceProtocol);
+ DEF_FIELD(symval, usb_device_id, bInterfaceNumber);
+
+ strcpy(alias, "usb:");
+ ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR,
+ idVendor);
+ ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
+ idProduct);
+
+ strcat(alias, "d");
+ if (bcdDevice_initial_digits)
+ sprintf(alias + strlen(alias), "%0*X",
+ bcdDevice_initial_digits, bcdDevice_initial);
+ if (range_lo == range_hi)
+ sprintf(alias + strlen(alias), "%X", range_lo);
+ else if (range_lo > 0 || range_hi < max) {
+ if (range_lo > 0x9 || range_hi < 0xA)
+ sprintf(alias + strlen(alias),
+ "[%X-%X]",
+ range_lo,
+ range_hi);
+ else {
+ sprintf(alias + strlen(alias),
+ range_lo < 0x9 ? "[%X-9" : "[%X",
+ range_lo);
+ sprintf(alias + strlen(alias),
+ range_hi > 0xA ? "a-%X]" : "%X]",
+ range_lo);
+ }
+ }
+ if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
+ strcat(alias, "*");
+
+ ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
+ bDeviceClass);
+ ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
+ bDeviceSubClass);
+ ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+ bDeviceProtocol);
+ ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
+ bInterfaceClass);
+ ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+ bInterfaceSubClass);
+ ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+ bInterfaceProtocol);
+ ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER,
+ bInterfaceNumber);
+
+ add_wildcard(alias);
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"%s\");\n", alias);
+}
+
+/* Handles increment/decrement of BCD formatted integers */
+/* Returns the previous value, so it works like i++ or i-- */
+static unsigned int incbcd(unsigned int *bcd,
+ int inc,
+ unsigned char max,
+ size_t chars)
+{
+ unsigned int init = *bcd, i, j;
+ unsigned long long c, dec = 0;
+
+ /* If bcd is not in BCD format, just increment */
+ if (max > 0x9) {
+ *bcd += inc;
+ return init;
+ }
+
+ /* Convert BCD to Decimal */
+ for (i=0 ; i < chars ; i++) {
+ c = (*bcd >> (i << 2)) & 0xf;
+ c = c > 9 ? 9 : c; /* force to bcd just in case */
+ for (j=0 ; j < i ; j++)
+ c = c * 10;
+ dec += c;
+ }
+
+ /* Do our increment/decrement */
+ dec += inc;
+ *bcd = 0;
+
+ /* Convert back to BCD */
+ for (i=0 ; i < chars ; i++) {
+ for (c=1,j=0 ; j < i ; j++)
+ c = c * 10;
+ c = (dec / c) % 10;
+ *bcd += c << (i << 2);
+ }
+ return init;
+}
+
+static void do_usb_entry_multi(void *symval, struct module *mod)
+{
+ unsigned int devlo, devhi;
+ unsigned char chi, clo, max;
+ int ndigits;
+
+ DEF_FIELD(symval, usb_device_id, match_flags);
+ DEF_FIELD(symval, usb_device_id, idVendor);
+ DEF_FIELD(symval, usb_device_id, idProduct);
+ DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
+ DEF_FIELD(symval, usb_device_id, bcdDevice_hi);
+ DEF_FIELD(symval, usb_device_id, bDeviceClass);
+ DEF_FIELD(symval, usb_device_id, bInterfaceClass);
+
+ devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
+ bcdDevice_lo : 0x0U;
+ devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
+ bcdDevice_hi : ~0x0U;
+
+ /* Figure out if this entry is in bcd or hex format */
+ max = 0x9; /* Default to decimal format */
+ for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) {
+ clo = (devlo >> (ndigits << 2)) & 0xf;
+ chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf;
+ if (clo > max || chi > max) {
+ max = 0xf;
+ break;
+ }
+ }
+
+ /*
+ * Some modules (visor) have empty slots as placeholder for
+ * run-time specification that results in catch-all alias
+ */
+ if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass))
+ return;
+
+ /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
+ for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
+ clo = devlo & 0xf;
+ chi = devhi & 0xf;
+ if (chi > max) /* If we are in bcd mode, truncate if necessary */
+ chi = max;
+ devlo >>= 4;
+ devhi >>= 4;
+
+ if (devlo == devhi || !ndigits) {
+ do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod);
+ break;
+ }
+
+ if (clo > 0x0)
+ do_usb_entry(symval,
+ incbcd(&devlo, 1, max,
+ sizeof(bcdDevice_lo) * 2),
+ ndigits, clo, max, max, mod);
+
+ if (chi < max)
+ do_usb_entry(symval,
+ incbcd(&devhi, -1, max,
+ sizeof(bcdDevice_lo) * 2),
+ ndigits, 0x0, chi, max, mod);
+ }
+}
+
+static void do_usb_table(void *symval, unsigned long size,
+ struct module *mod)
+{
+ unsigned int i;
+ const unsigned long id_size = SIZE_usb_device_id;
+
+ device_id_check(mod->name, "usb", size, id_size, symval);
+
+ /* Leave last one: it's the terminator. */
+ size -= id_size;
+
+ for (i = 0; i < size; i += id_size)
+ do_usb_entry_multi(symval + i, mod);
+}
+
+/* Looks like: hid:bNvNpN */
+static int do_hid_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, hid_device_id, bus);
+ DEF_FIELD(symval, hid_device_id, group);
+ DEF_FIELD(symval, hid_device_id, vendor);
+ DEF_FIELD(symval, hid_device_id, product);
+
+ sprintf(alias, "hid:");
+ ADD(alias, "b", bus != HID_BUS_ANY, bus);
+ ADD(alias, "g", group != HID_GROUP_ANY, group);
+ ADD(alias, "v", vendor != HID_ANY_ID, vendor);
+ ADD(alias, "p", product != HID_ANY_ID, product);
+
+ return 1;
+}
+ADD_TO_DEVTABLE("hid", hid_device_id, do_hid_entry);
+
+/* Looks like: ieee1394:venNmoNspNverN */
+static int do_ieee1394_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, ieee1394_device_id, match_flags);
+ DEF_FIELD(symval, ieee1394_device_id, vendor_id);
+ DEF_FIELD(symval, ieee1394_device_id, model_id);
+ DEF_FIELD(symval, ieee1394_device_id, specifier_id);
+ DEF_FIELD(symval, ieee1394_device_id, version);
+
+ strcpy(alias, "ieee1394:");
+ ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID,
+ vendor_id);
+ ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID,
+ model_id);
+ ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID,
+ specifier_id);
+ ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION,
+ version);
+
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("ieee1394", ieee1394_device_id, do_ieee1394_entry);
+
+/* Looks like: pci:vNdNsvNsdNbcNscNiN. */
+static int do_pci_entry(const char *filename,
+ void *symval, char *alias)
+{
+ /* Class field can be divided into these three. */
+ unsigned char baseclass, subclass, interface,
+ baseclass_mask, subclass_mask, interface_mask;
+
+ DEF_FIELD(symval, pci_device_id, vendor);
+ DEF_FIELD(symval, pci_device_id, device);
+ DEF_FIELD(symval, pci_device_id, subvendor);
+ DEF_FIELD(symval, pci_device_id, subdevice);
+ DEF_FIELD(symval, pci_device_id, class);
+ DEF_FIELD(symval, pci_device_id, class_mask);
+
+ strcpy(alias, "pci:");
+ ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
+ ADD(alias, "d", device != PCI_ANY_ID, device);
+ ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor);
+ ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice);
+
+ baseclass = (class) >> 16;
+ baseclass_mask = (class_mask) >> 16;
+ subclass = (class) >> 8;
+ subclass_mask = (class_mask) >> 8;
+ interface = class;
+ interface_mask = class_mask;
+
+ if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
+ || (subclass_mask != 0 && subclass_mask != 0xFF)
+ || (interface_mask != 0 && interface_mask != 0xFF)) {
+ warn("Can't handle masks in %s:%04X\n",
+ filename, class_mask);
+ return 0;
+ }
+
+ ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
+ ADD(alias, "sc", subclass_mask == 0xFF, subclass);
+ ADD(alias, "i", interface_mask == 0xFF, interface);
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("pci", pci_device_id, do_pci_entry);
+
+/* looks like: "ccw:tNmNdtNdmN" */
+static int do_ccw_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, ccw_device_id, match_flags);
+ DEF_FIELD(symval, ccw_device_id, cu_type);
+ DEF_FIELD(symval, ccw_device_id, cu_model);
+ DEF_FIELD(symval, ccw_device_id, dev_type);
+ DEF_FIELD(symval, ccw_device_id, dev_model);
+
+ strcpy(alias, "ccw:");
+ ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
+ cu_type);
+ ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
+ cu_model);
+ ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
+ dev_type);
+ ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
+ dev_model);
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("ccw", ccw_device_id, do_ccw_entry);
+
+/* looks like: "ap:tN" */
+static int do_ap_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, ap_device_id, dev_type);
+
+ sprintf(alias, "ap:t%02X*", dev_type);
+ return 1;
+}
+ADD_TO_DEVTABLE("ap", ap_device_id, do_ap_entry);
+
+/* looks like: "css:tN" */
+static int do_css_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, css_device_id, type);
+
+ sprintf(alias, "css:t%01X", type);
+ return 1;
+}
+ADD_TO_DEVTABLE("css", css_device_id, do_css_entry);
+
+/* Looks like: "serio:tyNprNidNexN" */
+static int do_serio_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, serio_device_id, type);
+ DEF_FIELD(symval, serio_device_id, proto);
+ DEF_FIELD(symval, serio_device_id, id);
+ DEF_FIELD(symval, serio_device_id, extra);
+
+ strcpy(alias, "serio:");
+ ADD(alias, "ty", type != SERIO_ANY, type);
+ ADD(alias, "pr", proto != SERIO_ANY, proto);
+ ADD(alias, "id", id != SERIO_ANY, id);
+ ADD(alias, "ex", extra != SERIO_ANY, extra);
+
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("serio", serio_device_id, do_serio_entry);
+
+/* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */
+static int do_acpi_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD_ADDR(symval, acpi_device_id, id);
+ sprintf(alias, "acpi*:%s:*", *id);
+ return 1;
+}
+ADD_TO_DEVTABLE("acpi", acpi_device_id, do_acpi_entry);
+
+/* looks like: "pnp:dD" */
+static void do_pnp_device_entry(void *symval, unsigned long size,
+ struct module *mod)
+{
+ const unsigned long id_size = SIZE_pnp_device_id;
+ const unsigned int count = (size / id_size)-1;
+ unsigned int i;
+
+ device_id_check(mod->name, "pnp", size, id_size, symval);
+
+ for (i = 0; i < count; i++) {
+ DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id);
+ char acpi_id[sizeof(*id)];
+ int j;
+
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"pnp:d%s*\");\n", *id);
+
+ /* fix broken pnp bus lowercasing */
+ for (j = 0; j < sizeof(acpi_id); j++)
+ acpi_id[j] = toupper((*id)[j]);
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
+ }
+}
+
+/* looks like: "pnp:dD" for every device of the card */
+static void do_pnp_card_entries(void *symval, unsigned long size,
+ struct module *mod)
+{
+ const unsigned long id_size = SIZE_pnp_card_device_id;
+ const unsigned int count = (size / id_size)-1;
+ unsigned int i;
+
+ device_id_check(mod->name, "pnp", size, id_size, symval);
+
+ for (i = 0; i < count; i++) {
+ unsigned int j;
+ DEF_FIELD_ADDR(symval + i*id_size, pnp_card_device_id, devs);
+
+ for (j = 0; j < PNP_MAX_DEVICES; j++) {
+ const char *id = (char *)(*devs)[j].id;
+ int i2, j2;
+ int dup = 0;
+
+ if (!id[0])
+ break;
+
+ /* find duplicate, already added value */
+ for (i2 = 0; i2 < i && !dup; i2++) {
+ DEF_FIELD_ADDR(symval + i2*id_size, pnp_card_device_id, devs);
+
+ for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
+ const char *id2 = (char *)(*devs)[j2].id;
+
+ if (!id2[0])
+ break;
+
+ if (!strcmp(id, id2)) {
+ dup = 1;
+ break;
+ }
+ }
+ }
+
+ /* add an individual alias for every device entry */
+ if (!dup) {
+ char acpi_id[PNP_ID_LEN];
+ int k;
+
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+
+ /* fix broken pnp bus lowercasing */
+ for (k = 0; k < sizeof(acpi_id); k++)
+ acpi_id[k] = toupper(id[k]);
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
+ }
+ }
+ }
+}
+
+/* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
+static int do_pcmcia_entry(const char *filename,
+ void *symval, char *alias)
+{
+ unsigned int i;
+ DEF_FIELD(symval, pcmcia_device_id, match_flags);
+ DEF_FIELD(symval, pcmcia_device_id, manf_id);
+ DEF_FIELD(symval, pcmcia_device_id, card_id);
+ DEF_FIELD(symval, pcmcia_device_id, func_id);
+ DEF_FIELD(symval, pcmcia_device_id, function);
+ DEF_FIELD(symval, pcmcia_device_id, device_no);
+ DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash);
+
+ for (i=0; i<4; i++) {
+ (*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]);
+ }
+
+ strcpy(alias, "pcmcia:");
+ ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
+ manf_id);
+ ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
+ card_id);
+ ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
+ func_id);
+ ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
+ function);
+ ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
+ device_no);
+ ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]);
+ ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]);
+ ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]);
+ ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]);
+
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("pcmcia", pcmcia_device_id, do_pcmcia_entry);
+
+static int do_of_entry (const char *filename, void *symval, char *alias)
+{
+ int len;
+ char *tmp;
+ DEF_FIELD_ADDR(symval, of_device_id, name);
+ DEF_FIELD_ADDR(symval, of_device_id, type);
+ DEF_FIELD_ADDR(symval, of_device_id, compatible);
+
+ len = sprintf (alias, "of:N%sT%s",
+ (*name)[0] ? *name : "*",
+ (*type)[0] ? *type : "*");
+
+ if (compatible[0])
+ sprintf (&alias[len], "%sC%s",
+ (*type)[0] ? "*" : "",
+ *compatible);
+
+ /* Replace all whitespace with underscores */
+ for (tmp = alias; tmp && *tmp; tmp++)
+ if (isspace (*tmp))
+ *tmp = '_';
+
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("of", of_device_id, do_of_entry);
+
+static int do_vio_entry(const char *filename, void *symval,
+ char *alias)
+{
+ char *tmp;
+ DEF_FIELD_ADDR(symval, vio_device_id, type);
+ DEF_FIELD_ADDR(symval, vio_device_id, compat);
+
+ sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*",
+ (*compat)[0] ? *compat : "*");
+
+ /* Replace all whitespace with underscores */
+ for (tmp = alias; tmp && *tmp; tmp++)
+ if (isspace (*tmp))
+ *tmp = '_';
+
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("vio", vio_device_id, do_vio_entry);
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static void do_input(char *alias,
+ kernel_ulong_t *arr, unsigned int min, unsigned int max)
+{
+ unsigned int i;
+
+ for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++)
+ arr[i] = TO_NATIVE(arr[i]);
+ for (i = min; i < max; i++)
+ if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
+ sprintf(alias + strlen(alias), "%X,*", i);
+}
+
+/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
+static int do_input_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD(symval, input_device_id, flags);
+ DEF_FIELD(symval, input_device_id, bustype);
+ DEF_FIELD(symval, input_device_id, vendor);
+ DEF_FIELD(symval, input_device_id, product);
+ DEF_FIELD(symval, input_device_id, version);
+ DEF_FIELD_ADDR(symval, input_device_id, evbit);
+ DEF_FIELD_ADDR(symval, input_device_id, keybit);
+ DEF_FIELD_ADDR(symval, input_device_id, relbit);
+ DEF_FIELD_ADDR(symval, input_device_id, absbit);
+ DEF_FIELD_ADDR(symval, input_device_id, mscbit);
+ DEF_FIELD_ADDR(symval, input_device_id, ledbit);
+ DEF_FIELD_ADDR(symval, input_device_id, sndbit);
+ DEF_FIELD_ADDR(symval, input_device_id, ffbit);
+ DEF_FIELD_ADDR(symval, input_device_id, swbit);
+
+ sprintf(alias, "input:");
+
+ ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype);
+ ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor);
+ ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product);
+ ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version);
+
+ sprintf(alias + strlen(alias), "-e*");
+ if (flags & INPUT_DEVICE_ID_MATCH_EVBIT)
+ do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX);
+ sprintf(alias + strlen(alias), "k*");
+ if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
+ do_input(alias, *keybit,
+ INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
+ INPUT_DEVICE_ID_KEY_MAX);
+ sprintf(alias + strlen(alias), "r*");
+ if (flags & INPUT_DEVICE_ID_MATCH_RELBIT)
+ do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX);
+ sprintf(alias + strlen(alias), "a*");
+ if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
+ do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
+ sprintf(alias + strlen(alias), "m*");
+ if (flags & INPUT_DEVICE_ID_MATCH_MSCIT)
+ do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
+ sprintf(alias + strlen(alias), "l*");
+ if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
+ do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
+ sprintf(alias + strlen(alias), "s*");
+ if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
+ do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
+ sprintf(alias + strlen(alias), "f*");
+ if (flags & INPUT_DEVICE_ID_MATCH_FFBIT)
+ do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
+ sprintf(alias + strlen(alias), "w*");
+ if (flags & INPUT_DEVICE_ID_MATCH_SWBIT)
+ do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
+ return 1;
+}
+ADD_TO_DEVTABLE("input", input_device_id, do_input_entry);
+
+static int do_eisa_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD_ADDR(symval, eisa_device_id, sig);
+ if (sig[0])
+ sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig);
+ else
+ strcat(alias, "*");
+ return 1;
+}
+ADD_TO_DEVTABLE("eisa", eisa_device_id, do_eisa_entry);
+
+/* Looks like: parisc:tNhvNrevNsvN */
+static int do_parisc_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD(symval, parisc_device_id, hw_type);
+ DEF_FIELD(symval, parisc_device_id, hversion);
+ DEF_FIELD(symval, parisc_device_id, hversion_rev);
+ DEF_FIELD(symval, parisc_device_id, sversion);
+
+ strcpy(alias, "parisc:");
+ ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type);
+ ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion);
+ ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev);
+ ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion);
+
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("parisc", parisc_device_id, do_parisc_entry);
+
+/* Looks like: sdio:cNvNdN. */
+static int do_sdio_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, sdio_device_id, class);
+ DEF_FIELD(symval, sdio_device_id, vendor);
+ DEF_FIELD(symval, sdio_device_id, device);
+
+ strcpy(alias, "sdio:");
+ ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class);
+ ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor);
+ ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device);
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("sdio", sdio_device_id, do_sdio_entry);
+
+/* Looks like: ssb:vNidNrevN. */
+static int do_ssb_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, ssb_device_id, vendor);
+ DEF_FIELD(symval, ssb_device_id, coreid);
+ DEF_FIELD(symval, ssb_device_id, revision);
+
+ strcpy(alias, "ssb:");
+ ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor);
+ ADD(alias, "id", coreid != SSB_ANY_ID, coreid);
+ ADD(alias, "rev", revision != SSB_ANY_REV, revision);
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("ssb", ssb_device_id, do_ssb_entry);
+
+/* Looks like: bcma:mNidNrevNclN. */
+static int do_bcma_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, bcma_device_id, manuf);
+ DEF_FIELD(symval, bcma_device_id, id);
+ DEF_FIELD(symval, bcma_device_id, rev);
+ DEF_FIELD(symval, bcma_device_id, class);
+
+ strcpy(alias, "bcma:");
+ ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf);
+ ADD(alias, "id", id != BCMA_ANY_ID, id);
+ ADD(alias, "rev", rev != BCMA_ANY_REV, rev);
+ ADD(alias, "cl", class != BCMA_ANY_CLASS, class);
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("bcma", bcma_device_id, do_bcma_entry);
+
+/* Looks like: virtio:dNvN */
+static int do_virtio_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD(symval, virtio_device_id, device);
+ DEF_FIELD(symval, virtio_device_id, vendor);
+
+ strcpy(alias, "virtio:");
+ ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device);
+ ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor);
+
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("virtio", virtio_device_id, do_virtio_entry);
+
+/*
+ * Looks like: vmbus:guid
+ * Each byte of the guid will be represented by two hex characters
+ * in the name.
+ */
+
+static int do_vmbus_entry(const char *filename, void *symval,
+ char *alias)
+{
+ int i;
+ DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid);
+ char guid_name[(sizeof(*guid) + 1) * 2];
+
+ for (i = 0; i < (sizeof(*guid) * 2); i += 2)
+ sprintf(&guid_name[i], "%02x", TO_NATIVE((*guid)[i/2]));
+
+ strcpy(alias, "vmbus:");
+ strcat(alias, guid_name);
+
+ return 1;
+}
+ADD_TO_DEVTABLE("vmbus", hv_vmbus_device_id, do_vmbus_entry);
+
+/* Looks like: i2c:S */
+static int do_i2c_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD_ADDR(symval, i2c_device_id, name);
+ sprintf(alias, I2C_MODULE_PREFIX "%s", *name);
+
+ return 1;
+}
+ADD_TO_DEVTABLE("i2c", i2c_device_id, do_i2c_entry);
+
+/* Looks like: spi:S */
+static int do_spi_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD_ADDR(symval, spi_device_id, name);
+ sprintf(alias, SPI_MODULE_PREFIX "%s", *name);
+
+ return 1;
+}
+ADD_TO_DEVTABLE("spi", spi_device_id, do_spi_entry);
+
+static const struct dmifield {
+ const char *prefix;
+ int field;
+} dmi_fields[] = {
+ { "bvn", DMI_BIOS_VENDOR },
+ { "bvr", DMI_BIOS_VERSION },
+ { "bd", DMI_BIOS_DATE },
+ { "svn", DMI_SYS_VENDOR },
+ { "pn", DMI_PRODUCT_NAME },
+ { "pvr", DMI_PRODUCT_VERSION },
+ { "rvn", DMI_BOARD_VENDOR },
+ { "rn", DMI_BOARD_NAME },
+ { "rvr", DMI_BOARD_VERSION },
+ { "cvn", DMI_CHASSIS_VENDOR },
+ { "ct", DMI_CHASSIS_TYPE },
+ { "cvr", DMI_CHASSIS_VERSION },
+ { NULL, DMI_NONE }
+};
+
+static void dmi_ascii_filter(char *d, const char *s)
+{
+ /* Filter out characters we don't want to see in the modalias string */
+ for (; *s; s++)
+ if (*s > ' ' && *s < 127 && *s != ':')
+ *(d++) = *s;
+
+ *d = 0;
+}
+
+
+static int do_dmi_entry(const char *filename, void *symval,
+ char *alias)
+{
+ int i, j;
+ DEF_FIELD_ADDR(symval, dmi_system_id, matches);
+ sprintf(alias, "dmi*");
+
+ for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
+ for (j = 0; j < 4; j++) {
+ if ((*matches)[j].slot &&
+ (*matches)[j].slot == dmi_fields[i].field) {
+ sprintf(alias + strlen(alias), ":%s*",
+ dmi_fields[i].prefix);
+ dmi_ascii_filter(alias + strlen(alias),
+ (*matches)[j].substr);
+ strcat(alias, "*");
+ }
+ }
+ }
+
+ strcat(alias, ":");
+ return 1;
+}
+ADD_TO_DEVTABLE("dmi", dmi_system_id, do_dmi_entry);
+
+static int do_platform_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD_ADDR(symval, platform_device_id, name);
+ sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name);
+ return 1;
+}
+ADD_TO_DEVTABLE("platform", platform_device_id, do_platform_entry);
+
+static int do_mdio_entry(const char *filename,
+ void *symval, char *alias)
+{
+ int i;
+ DEF_FIELD(symval, mdio_device_id, phy_id);
+ DEF_FIELD(symval, mdio_device_id, phy_id_mask);
+
+ alias += sprintf(alias, MDIO_MODULE_PREFIX);
+
+ for (i = 0; i < 32; i++) {
+ if (!((phy_id_mask >> (31-i)) & 1))
+ *(alias++) = '?';
+ else if ((phy_id >> (31-i)) & 1)
+ *(alias++) = '1';
+ else
+ *(alias++) = '0';
+ }
+
+ /* Terminate the string */
+ *alias = 0;
+
+ return 1;
+}
+ADD_TO_DEVTABLE("mdio", mdio_device_id, do_mdio_entry);
+
+/* Looks like: zorro:iN. */
+static int do_zorro_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD(symval, zorro_device_id, id);
+ strcpy(alias, "zorro:");
+ ADD(alias, "i", id != ZORRO_WILDCARD, id);
+ return 1;
+}
+ADD_TO_DEVTABLE("zorro", zorro_device_id, do_zorro_entry);
+
+/* looks like: "pnp:dD" */
+static int do_isapnp_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, isapnp_device_id, vendor);
+ DEF_FIELD(symval, isapnp_device_id, function);
+ sprintf(alias, "pnp:d%c%c%c%x%x%x%x*",
+ 'A' + ((vendor >> 2) & 0x3f) - 1,
+ 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+ 'A' + ((vendor >> 8) & 0x1f) - 1,
+ (function >> 4) & 0x0f, function & 0x0f,
+ (function >> 12) & 0x0f, (function >> 8) & 0x0f);
+ return 1;
+}
+ADD_TO_DEVTABLE("isapnp", isapnp_device_id, do_isapnp_entry);
+
+/* Looks like: "ipack:fNvNdN". */
+static int do_ipack_entry(const char *filename,
+ void *symval, char *alias)
+{
+ DEF_FIELD(symval, ipack_device_id, format);
+ DEF_FIELD(symval, ipack_device_id, vendor);
+ DEF_FIELD(symval, ipack_device_id, device);
+ strcpy(alias, "ipack:");
+ ADD(alias, "f", format != IPACK_ANY_FORMAT, format);
+ ADD(alias, "v", vendor != IPACK_ANY_ID, vendor);
+ ADD(alias, "d", device != IPACK_ANY_ID, device);
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("ipack", ipack_device_id, do_ipack_entry);
+
+/*
+ * Append a match expression for a single masked hex digit.
+ * outp points to a pointer to the character at which to append.
+ * *outp is updated on return to point just after the appended text,
+ * to facilitate further appending.
+ */
+static void append_nibble_mask(char **outp,
+ unsigned int nibble, unsigned int mask)
+{
+ char *p = *outp;
+ unsigned int i;
+
+ switch (mask) {
+ case 0:
+ *p++ = '?';
+ break;
+
+ case 0xf:
+ p += sprintf(p, "%X", nibble);
+ break;
+
+ default:
+ /*
+ * Dumbly emit a match pattern for all possible matching
+ * digits. This could be improved in some cases using ranges,
+ * but it has the advantage of being trivially correct, and is
+ * often optimal.
+ */
+ *p++ = '[';
+ for (i = 0; i < 0x10; i++)
+ if ((i & mask) == nibble)
+ p += sprintf(p, "%X", i);
+ *p++ = ']';
+ }
+
+ /* Ensure that the string remains NUL-terminated: */
+ *p = '\0';
+
+ /* Advance the caller's end-of-string pointer: */
+ *outp = p;
+}
+
+/*
+ * looks like: "amba:dN"
+ *
+ * N is exactly 8 digits, where each is an upper-case hex digit, or
+ * a ? or [] pattern matching exactly one digit.
+ */
+static int do_amba_entry(const char *filename,
+ void *symval, char *alias)
+{
+ unsigned int digit;
+ char *p = alias;
+ DEF_FIELD(symval, amba_id, id);
+ DEF_FIELD(symval, amba_id, mask);
+
+ if ((id & mask) != id)
+ fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: "
+ "id=0x%08X, mask=0x%08X. Please fix this driver.\n",
+ filename, id, mask);
+
+ p += sprintf(alias, "amba:d");
+ for (digit = 0; digit < 8; digit++)
+ append_nibble_mask(&p,
+ (id >> (4 * (7 - digit))) & 0xf,
+ (mask >> (4 * (7 - digit))) & 0xf);
+
+ return 1;
+}
+ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry);
+
+/* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,*
+ * All fields are numbers. It would be nicer to use strings for vendor
+ * and feature, but getting those out of the build system here is too
+ * complicated.
+ */
+
+static int do_x86cpu_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD(symval, x86_cpu_id, feature);
+ DEF_FIELD(symval, x86_cpu_id, family);
+ DEF_FIELD(symval, x86_cpu_id, model);
+ DEF_FIELD(symval, x86_cpu_id, vendor);
+
+ strcpy(alias, "x86cpu:");
+ ADD(alias, "vendor:", vendor != X86_VENDOR_ANY, vendor);
+ ADD(alias, ":family:", family != X86_FAMILY_ANY, family);
+ ADD(alias, ":model:", model != X86_MODEL_ANY, model);
+ strcat(alias, ":feature:*");
+ if (feature != X86_FEATURE_ANY)
+ sprintf(alias + strlen(alias), "%04X*", feature);
+ return 1;
+}
+ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
+
+/* Does namelen bytes of name exactly match the symbol? */
+static bool sym_is(const char *name, unsigned namelen, const char *symbol)
+{
+ if (namelen != strlen(symbol))
+ return false;
+
+ return memcmp(name, symbol, namelen) == 0;
+}
+
+static void do_table(void *symval, unsigned long size,
+ unsigned long id_size,
+ const char *device_id,
+ void *function,
+ struct module *mod)
+{
+ unsigned int i;
+ char alias[500];
+ int (*do_entry)(const char *, void *entry, char *alias) = function;
+
+ device_id_check(mod->name, device_id, size, id_size, symval);
+ /* Leave last one: it's the terminator. */
+ size -= id_size;
+
+ for (i = 0; i < size; i += id_size) {
+ if (do_entry(mod->name, symval+i, alias)) {
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"%s\");\n", alias);
+ }
+ }
+}
+
+/* Create MODULE_ALIAS() statements.
+ * At this time, we cannot write the actual output C source yet,
+ * so we write into the mod->dev_table_buf buffer. */
+void handle_moddevtable(struct module *mod, struct elf_info *info,
+ Elf_Sym *sym, const char *symname)
+{
+ void *symval;
+ char *zeros = NULL;
+ const char *name;
+ unsigned int namelen;
+
+ /* We're looking for a section relative symbol */
+ if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
+ return;
+
+ /* We're looking for an object */
+ if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
+ return;
+
+ /* All our symbols are of form <prefix>__mod_XXX_device_table. */
+ name = strstr(symname, "__mod_");
+ if (!name)
+ return;
+ name += strlen("__mod_");
+ namelen = strlen(name);
+ if (namelen < strlen("_device_table"))
+ return;
+ if (strcmp(name + namelen - strlen("_device_table"), "_device_table"))
+ return;
+ namelen -= strlen("_device_table");
+
+ /* Handle all-NULL symbols allocated into .bss */
+ if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
+ zeros = calloc(1, sym->st_size);
+ symval = zeros;
+ } else {
+ symval = (void *)info->hdr
+ + info->sechdrs[get_secindex(info, sym)].sh_offset
+ + sym->st_value;
+ }
+
+ /* First handle the "special" cases */
+ if (sym_is(name, namelen, "usb"))
+ do_usb_table(symval, sym->st_size, mod);
+ else if (sym_is(name, namelen, "pnp"))
+ do_pnp_device_entry(symval, sym->st_size, mod);
+ else if (sym_is(name, namelen, "pnp_card"))
+ do_pnp_card_entries(symval, sym->st_size, mod);
+ else {
+ struct devtable **p;
+ INIT_SECTION(__devtable);
+
+ for (p = __start___devtable; p < __stop___devtable; p++) {
+ if (sym_is(name, namelen, (*p)->device_id)) {
+ do_table(symval, sym->st_size, (*p)->id_size,
+ (*p)->device_id, (*p)->function, mod);
+ break;
+ }
+ }
+ }
+ free(zeros);
+}
+
+/* Now add out buffered information to the generated C source */
+void add_moddevtable(struct buffer *buf, struct module *mod)
+{
+ buf_printf(buf, "\n");
+ buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
+ free(mod->dev_table_buf.p);
+}
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c
new file mode 100644
index 0000000..639bca7
--- /dev/null
+++ b/scripts/mod/mk_elfconfig.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <elf.h>
+
+int
+main(int argc, char **argv)
+{
+ unsigned char ei[EI_NIDENT];
+ union { short s; char c[2]; } endian_test;
+
+ if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) {
+ fprintf(stderr, "Error: input truncated\n");
+ return 1;
+ }
+ if (memcmp(ei, ELFMAG, SELFMAG) != 0) {
+ fprintf(stderr, "Error: not ELF\n");
+ return 1;
+ }
+ switch (ei[EI_CLASS]) {
+ case ELFCLASS32:
+ printf("#define KERNEL_ELFCLASS ELFCLASS32\n");
+ break;
+ case ELFCLASS64:
+ printf("#define KERNEL_ELFCLASS ELFCLASS64\n");
+ break;
+ default:
+ exit(1);
+ }
+ switch (ei[EI_DATA]) {
+ case ELFDATA2LSB:
+ printf("#define KERNEL_ELFDATA ELFDATA2LSB\n");
+ break;
+ case ELFDATA2MSB:
+ printf("#define KERNEL_ELFDATA ELFDATA2MSB\n");
+ break;
+ default:
+ exit(1);
+ }
+
+ if (sizeof(unsigned long) == 4) {
+ printf("#define HOST_ELFCLASS ELFCLASS32\n");
+ } else if (sizeof(unsigned long) == 8) {
+ printf("#define HOST_ELFCLASS ELFCLASS64\n");
+ }
+
+ endian_test.s = 0x0102;
+ if (memcmp(endian_test.c, "\x01\x02", 2) == 0)
+ printf("#define HOST_ELFDATA ELFDATA2MSB\n");
+ else if (memcmp(endian_test.c, "\x02\x01", 2) == 0)
+ printf("#define HOST_ELFDATA ELFDATA2LSB\n");
+ else
+ exit(1);
+
+ return 0;
+}
+
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
new file mode 100644
index 0000000..78b30c1
--- /dev/null
+++ b/scripts/mod/modpost.c
@@ -0,0 +1,2222 @@
+/* Postprocess module symbol versions
+ *
+ * Copyright 2003 Kai Germaschewski
+ * Copyright 2002-2004 Rusty Russell, IBM Corporation
+ * Copyright 2006-2008 Sam Ravnborg
+ * Based in part on module-init-tools/depmod.c,file2alias
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * Usage: modpost vmlinux module1.o module2.o ...
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "modpost.h"
+#include "../../include/generated/autoconf.h"
+#include "../../include/linux/license.h"
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_SYMBOL_PREFIX
+#define MODULE_SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX
+#else
+#define MODULE_SYMBOL_PREFIX ""
+#endif
+
+
+/* Are we using CONFIG_MODVERSIONS? */
+int modversions = 0;
+/* Warn about undefined symbols? (do so if we have vmlinux) */
+int have_vmlinux = 0;
+/* Is CONFIG_MODULE_SRCVERSION_ALL set? */
+static int all_versions = 0;
+/* If we are modposting external module set to 1 */
+static int external_module = 0;
+/* Warn about section mismatch in vmlinux if set to 1 */
+static int vmlinux_section_warnings = 1;
+/* Only warn about unresolved symbols */
+static int warn_unresolved = 0;
+/* How a symbol is exported */
+static int sec_mismatch_count = 0;
+static int sec_mismatch_verbose = 1;
+
+enum export {
+ export_plain, export_unused, export_gpl,
+ export_unused_gpl, export_gpl_future, export_unknown
+};
+
+#define PRINTF __attribute__ ((format (printf, 1, 2)))
+
+PRINTF void fatal(const char *fmt, ...)
+{
+ va_list arglist;
+
+ fprintf(stderr, "FATAL: ");
+
+ va_start(arglist, fmt);
+ vfprintf(stderr, fmt, arglist);
+ va_end(arglist);
+
+ exit(1);
+}
+
+PRINTF void warn(const char *fmt, ...)
+{
+ va_list arglist;
+
+ fprintf(stderr, "WARNING: ");
+
+ va_start(arglist, fmt);
+ vfprintf(stderr, fmt, arglist);
+ va_end(arglist);
+}
+
+PRINTF void merror(const char *fmt, ...)
+{
+ va_list arglist;
+
+ fprintf(stderr, "ERROR: ");
+
+ va_start(arglist, fmt);
+ vfprintf(stderr, fmt, arglist);
+ va_end(arglist);
+}
+
+static int is_vmlinux(const char *modname)
+{
+ const char *myname;
+
+ myname = strrchr(modname, '/');
+ if (myname)
+ myname++;
+ else
+ myname = modname;
+
+ return (strcmp(myname, "vmlinux") == 0) ||
+ (strcmp(myname, "vmlinux.o") == 0);
+}
+
+void *do_nofail(void *ptr, const char *expr)
+{
+ if (!ptr)
+ fatal("modpost: Memory allocation failure: %s.\n", expr);
+
+ return ptr;
+}
+
+/* A list of all modules we processed */
+static struct module *modules;
+
+static struct module *find_module(char *modname)
+{
+ struct module *mod;
+
+ for (mod = modules; mod; mod = mod->next)
+ if (strcmp(mod->name, modname) == 0)
+ break;
+ return mod;
+}
+
+static struct module *new_module(char *modname)
+{
+ struct module *mod;
+ char *p, *s;
+
+ mod = NOFAIL(malloc(sizeof(*mod)));
+ memset(mod, 0, sizeof(*mod));
+ p = NOFAIL(strdup(modname));
+
+ /* strip trailing .o */
+ s = strrchr(p, '.');
+ if (s != NULL)
+ if (strcmp(s, ".o") == 0) {
+ *s = '\0';
+ mod->is_dot_o = 1;
+ }
+
+ /* add to list */
+ mod->name = p;
+ mod->gpl_compatible = -1;
+ mod->next = modules;
+ modules = mod;
+
+ return mod;
+}
+
+/* A hash of all exported symbols,
+ * struct symbol is also used for lists of unresolved symbols */
+
+#define SYMBOL_HASH_SIZE 1024
+
+struct symbol {
+ struct symbol *next;
+ struct module *module;
+ unsigned int crc;
+ int crc_valid;
+ unsigned int weak:1;
+ unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */
+ 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];
+};
+
+static struct symbol *symbolhash[SYMBOL_HASH_SIZE];
+
+/* This is based on the hash agorithm from gdbm, via tdb */
+static inline unsigned int tdb_hash(const char *name)
+{
+ unsigned value; /* Used to compute the hash value. */
+ unsigned i; /* Used to cycle through random values. */
+
+ /* Set the initial value from the key size. */
+ for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++)
+ value = (value + (((unsigned char *)name)[i] << (i*5 % 24)));
+
+ return (1103515243 * value + 12345);
+}
+
+/**
+ * Allocate a new symbols for use in the hash of exported symbols or
+ * the list of unresolved symbols per module
+ **/
+static struct symbol *alloc_symbol(const char *name, unsigned int weak,
+ struct symbol *next)
+{
+ struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1));
+
+ memset(s, 0, sizeof(*s));
+ strcpy(s->name, name);
+ s->weak = weak;
+ s->next = next;
+ return s;
+}
+
+/* For the hash of exported symbols */
+static struct symbol *new_symbol(const char *name, struct module *module,
+ enum export export)
+{
+ unsigned int hash;
+ struct symbol *new;
+
+ hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
+ new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
+ new->module = module;
+ new->export = export;
+ return new;
+}
+
+static struct symbol *find_symbol(const char *name)
+{
+ struct symbol *s;
+
+ /* For our purposes, .foo matches foo. PPC64 needs this. */
+ if (name[0] == '.')
+ name++;
+
+ for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) {
+ if (strcmp(s->name, name) == 0)
+ return s;
+ }
+ return NULL;
+}
+
+static struct {
+ const char *str;
+ enum export export;
+} export_list[] = {
+ { .str = "EXPORT_SYMBOL", .export = export_plain },
+ { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused },
+ { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl },
+ { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl },
+ { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future },
+ { .str = "(unknown)", .export = export_unknown },
+};
+
+
+static const char *export_str(enum export ex)
+{
+ return export_list[ex].str;
+}
+
+static enum export export_no(const char *s)
+{
+ int i;
+
+ if (!s)
+ return export_unknown;
+ for (i = 0; export_list[i].export != export_unknown; i++) {
+ if (strcmp(export_list[i].str, s) == 0)
+ return export_list[i].export;
+ }
+ return export_unknown;
+}
+
+static const char *sec_name(struct elf_info *elf, int secindex);
+
+#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
+
+static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
+{
+ const char *secname = sec_name(elf, sec);
+
+ if (strstarts(secname, "___ksymtab+"))
+ return export_plain;
+ else if (strstarts(secname, "___ksymtab_unused+"))
+ return export_unused;
+ else if (strstarts(secname, "___ksymtab_gpl+"))
+ return export_gpl;
+ else if (strstarts(secname, "___ksymtab_unused_gpl+"))
+ return export_unused_gpl;
+ else if (strstarts(secname, "___ksymtab_gpl_future+"))
+ return export_gpl_future;
+ else
+ return export_unknown;
+}
+
+static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
+{
+ if (sec == elf->export_sec)
+ return export_plain;
+ else if (sec == elf->export_unused_sec)
+ return export_unused;
+ else if (sec == elf->export_gpl_sec)
+ return export_gpl;
+ else if (sec == elf->export_unused_gpl_sec)
+ return export_unused_gpl;
+ else if (sec == elf->export_gpl_future_sec)
+ return export_gpl_future;
+ else
+ return export_unknown;
+}
+
+/**
+ * Add an exported symbol - it may have already been added without a
+ * CRC, in this case just update the CRC
+ **/
+static struct symbol *sym_add_exported(const char *name, struct module *mod,
+ enum export export)
+{
+ struct symbol *s = find_symbol(name);
+
+ if (!s) {
+ s = new_symbol(name, mod, export);
+ } else {
+ if (!s->preloaded) {
+ warn("%s: '%s' exported twice. Previous export "
+ "was in %s%s\n", mod->name, name,
+ s->module->name,
+ is_vmlinux(s->module->name) ?"":".ko");
+ } else {
+ /* In case Modules.symvers was out of date */
+ s->module = mod;
+ }
+ }
+ s->preloaded = 0;
+ s->vmlinux = is_vmlinux(mod->name);
+ s->kernel = 0;
+ s->export = export;
+ return s;
+}
+
+static void sym_update_crc(const char *name, struct module *mod,
+ unsigned int crc, enum export export)
+{
+ struct symbol *s = find_symbol(name);
+
+ if (!s)
+ s = new_symbol(name, mod, export);
+ s->crc = crc;
+ s->crc_valid = 1;
+}
+
+void *grab_file(const char *filename, unsigned long *size)
+{
+ struct stat st;
+ void *map = MAP_FAILED;
+ int fd;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+ if (fstat(fd, &st))
+ goto failed;
+
+ *size = st.st_size;
+ map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+
+failed:
+ close(fd);
+ if (map == MAP_FAILED)
+ return NULL;
+ return map;
+}
+
+/**
+ * Return a copy of the next line in a mmap'ed file.
+ * spaces in the beginning of the line is trimmed away.
+ * Return a pointer to a static buffer.
+ **/
+char *get_next_line(unsigned long *pos, void *file, unsigned long size)
+{
+ static char line[4096];
+ int skip = 1;
+ size_t len = 0;
+ signed char *p = (signed char *)file + *pos;
+ char *s = line;
+
+ for (; *pos < size ; (*pos)++) {
+ if (skip && isspace(*p)) {
+ p++;
+ continue;
+ }
+ skip = 0;
+ if (*p != '\n' && (*pos < size)) {
+ len++;
+ *s++ = *p++;
+ if (len > 4095)
+ break; /* Too long, stop */
+ } else {
+ /* End of string */
+ *s = '\0';
+ return line;
+ }
+ }
+ /* End of buffer */
+ return NULL;
+}
+
+void release_file(void *file, unsigned long size)
+{
+ munmap(file, size);
+}
+
+static int parse_elf(struct elf_info *info, const char *filename)
+{
+ unsigned int i;
+ Elf_Ehdr *hdr;
+ Elf_Shdr *sechdrs;
+ Elf_Sym *sym;
+ const char *secstrings;
+ unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U;
+
+ hdr = grab_file(filename, &info->size);
+ if (!hdr) {
+ perror(filename);
+ exit(1);
+ }
+ info->hdr = hdr;
+ if (info->size < sizeof(*hdr)) {
+ /* file too small, assume this is an empty .o file */
+ return 0;
+ }
+ /* Is this a valid ELF file? */
+ if ((hdr->e_ident[EI_MAG0] != ELFMAG0) ||
+ (hdr->e_ident[EI_MAG1] != ELFMAG1) ||
+ (hdr->e_ident[EI_MAG2] != ELFMAG2) ||
+ (hdr->e_ident[EI_MAG3] != ELFMAG3)) {
+ /* Not an ELF file - silently ignore it */
+ return 0;
+ }
+ /* Fix endianness in ELF header */
+ hdr->e_type = TO_NATIVE(hdr->e_type);
+ hdr->e_machine = TO_NATIVE(hdr->e_machine);
+ hdr->e_version = TO_NATIVE(hdr->e_version);
+ hdr->e_entry = TO_NATIVE(hdr->e_entry);
+ hdr->e_phoff = TO_NATIVE(hdr->e_phoff);
+ hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
+ hdr->e_flags = TO_NATIVE(hdr->e_flags);
+ hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize);
+ hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize);
+ hdr->e_phnum = TO_NATIVE(hdr->e_phnum);
+ hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize);
+ hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
+ hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
+ sechdrs = (void *)hdr + hdr->e_shoff;
+ info->sechdrs = sechdrs;
+
+ /* Check if file offset is correct */
+ if (hdr->e_shoff > info->size) {
+ fatal("section header offset=%lu in file '%s' is bigger than "
+ "filesize=%lu\n", (unsigned long)hdr->e_shoff,
+ filename, info->size);
+ return 0;
+ }
+
+ if (hdr->e_shnum == SHN_UNDEF) {
+ /*
+ * There are more than 64k sections,
+ * read count from .sh_size.
+ */
+ info->num_sections = TO_NATIVE(sechdrs[0].sh_size);
+ }
+ else {
+ info->num_sections = hdr->e_shnum;
+ }
+ if (hdr->e_shstrndx == SHN_XINDEX) {
+ info->secindex_strings = TO_NATIVE(sechdrs[0].sh_link);
+ }
+ else {
+ info->secindex_strings = hdr->e_shstrndx;
+ }
+
+ /* Fix endianness in section headers */
+ for (i = 0; i < info->num_sections; i++) {
+ sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
+ sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
+ sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags);
+ sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr);
+ sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
+ sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
+ sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
+ sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info);
+ sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign);
+ sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize);
+ }
+ /* Find symbol table. */
+ secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset;
+ for (i = 1; i < info->num_sections; i++) {
+ const char *secname;
+ int nobits = sechdrs[i].sh_type == SHT_NOBITS;
+
+ if (!nobits && sechdrs[i].sh_offset > info->size) {
+ fatal("%s is truncated. sechdrs[i].sh_offset=%lu > "
+ "sizeof(*hrd)=%zu\n", filename,
+ (unsigned long)sechdrs[i].sh_offset,
+ sizeof(*hdr));
+ return 0;
+ }
+ secname = secstrings + sechdrs[i].sh_name;
+ if (strcmp(secname, ".modinfo") == 0) {
+ if (nobits)
+ fatal("%s has NOBITS .modinfo\n", filename);
+ info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
+ info->modinfo_len = sechdrs[i].sh_size;
+ } else if (strcmp(secname, "__ksymtab") == 0)
+ info->export_sec = i;
+ else if (strcmp(secname, "__ksymtab_unused") == 0)
+ info->export_unused_sec = i;
+ else if (strcmp(secname, "__ksymtab_gpl") == 0)
+ info->export_gpl_sec = i;
+ else if (strcmp(secname, "__ksymtab_unused_gpl") == 0)
+ info->export_unused_gpl_sec = i;
+ else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
+ info->export_gpl_future_sec = i;
+
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ unsigned int sh_link_idx;
+ symtab_idx = i;
+ info->symtab_start = (void *)hdr +
+ sechdrs[i].sh_offset;
+ info->symtab_stop = (void *)hdr +
+ sechdrs[i].sh_offset + sechdrs[i].sh_size;
+ sh_link_idx = sechdrs[i].sh_link;
+ info->strtab = (void *)hdr +
+ sechdrs[sh_link_idx].sh_offset;
+ }
+
+ /* 32bit section no. table? ("more than 64k sections") */
+ if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) {
+ symtab_shndx_idx = i;
+ info->symtab_shndx_start = (void *)hdr +
+ sechdrs[i].sh_offset;
+ info->symtab_shndx_stop = (void *)hdr +
+ sechdrs[i].sh_offset + sechdrs[i].sh_size;
+ }
+ }
+ if (!info->symtab_start)
+ fatal("%s has no symtab?\n", filename);
+
+ /* Fix endianness in symbols */
+ for (sym = info->symtab_start; sym < info->symtab_stop; sym++) {
+ sym->st_shndx = TO_NATIVE(sym->st_shndx);
+ sym->st_name = TO_NATIVE(sym->st_name);
+ sym->st_value = TO_NATIVE(sym->st_value);
+ sym->st_size = TO_NATIVE(sym->st_size);
+ }
+
+ if (symtab_shndx_idx != ~0U) {
+ Elf32_Word *p;
+ if (symtab_idx != sechdrs[symtab_shndx_idx].sh_link)
+ fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n",
+ filename, sechdrs[symtab_shndx_idx].sh_link,
+ symtab_idx);
+ /* Fix endianness */
+ for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop;
+ p++)
+ *p = TO_NATIVE(*p);
+ }
+
+ return 1;
+}
+
+static void parse_elf_finish(struct elf_info *info)
+{
+ release_file(info->hdr, info->size);
+}
+
+static int ignore_undef_symbol(struct elf_info *info, const char *symname)
+{
+ /* ignore __this_module, it will be resolved shortly */
+ if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0)
+ return 1;
+ /* ignore global offset table */
+ if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0)
+ return 1;
+ if (info->hdr->e_machine == EM_PPC)
+ /* Special register function linked on all modules during final link of .ko */
+ if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 ||
+ strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 ||
+ strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 ||
+ strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0)
+ return 1;
+ if (info->hdr->e_machine == EM_PPC64)
+ /* Special register function linked on all modules during final link of .ko */
+ if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 ||
+ strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0)
+ return 1;
+ /* Do not ignore this symbol */
+ return 0;
+}
+
+#define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_"
+#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
+
+static void handle_modversions(struct module *mod, struct elf_info *info,
+ Elf_Sym *sym, const char *symname)
+{
+ unsigned int crc;
+ enum export export;
+
+ if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
+ strncmp(symname, "__ksymtab", 9) == 0)
+ export = export_from_secname(info, get_secindex(info, sym));
+ else
+ export = export_from_sec(info, get_secindex(info, sym));
+
+ switch (sym->st_shndx) {
+ case SHN_COMMON:
+ warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
+ break;
+ case SHN_ABS:
+ /* CRC'd symbol */
+ if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
+ crc = (unsigned int) sym->st_value;
+ sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
+ export);
+ }
+ break;
+ case SHN_UNDEF:
+ /* undefined symbol */
+ if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
+ ELF_ST_BIND(sym->st_info) != STB_WEAK)
+ break;
+ if (ignore_undef_symbol(info, symname))
+ break;
+/* cope with newer glibc (2.3.4 or higher) STT_ definition in elf.h */
+#if defined(STT_REGISTER) || defined(STT_SPARC_REGISTER)
+/* add compatibility with older glibc */
+#ifndef STT_SPARC_REGISTER
+#define STT_SPARC_REGISTER STT_REGISTER
+#endif
+ if (info->hdr->e_machine == EM_SPARC ||
+ info->hdr->e_machine == EM_SPARCV9) {
+ /* Ignore register directives. */
+ if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
+ break;
+ if (symname[0] == '.') {
+ char *munged = strdup(symname);
+ munged[0] = '_';
+ munged[1] = toupper(munged[1]);
+ symname = munged;
+ }
+ }
+#endif
+
+ if (memcmp(symname, MODULE_SYMBOL_PREFIX,
+ strlen(MODULE_SYMBOL_PREFIX)) == 0) {
+ mod->unres =
+ alloc_symbol(symname +
+ strlen(MODULE_SYMBOL_PREFIX),
+ ELF_ST_BIND(sym->st_info) == STB_WEAK,
+ mod->unres);
+ }
+ break;
+ default:
+ /* All exported symbols */
+ if (strncmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
+ sym_add_exported(symname + strlen(KSYMTAB_PFX), mod,
+ export);
+ }
+ if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
+ mod->has_init = 1;
+ if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0)
+ mod->has_cleanup = 1;
+ break;
+ }
+}
+
+/**
+ * Parse tag=value strings from .modinfo section
+ **/
+static char *next_string(char *string, unsigned long *secsize)
+{
+ /* Skip non-zero chars */
+ while (string[0]) {
+ string++;
+ if ((*secsize)-- <= 1)
+ return NULL;
+ }
+
+ /* Skip any zero padding. */
+ while (!string[0]) {
+ string++;
+ if ((*secsize)-- <= 1)
+ return NULL;
+ }
+ return string;
+}
+
+static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len,
+ const char *tag, char *info)
+{
+ char *p;
+ unsigned int taglen = strlen(tag);
+ unsigned long size = modinfo_len;
+
+ if (info) {
+ size -= info - (char *)modinfo;
+ modinfo = next_string(info, &size);
+ }
+
+ for (p = modinfo; p; p = next_string(p, &size)) {
+ if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
+ return p + taglen + 1;
+ }
+ return NULL;
+}
+
+static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
+ const char *tag)
+
+{
+ return get_next_modinfo(modinfo, modinfo_len, tag, NULL);
+}
+
+/**
+ * Test if string s ends in string sub
+ * return 0 if match
+ **/
+static int strrcmp(const char *s, const char *sub)
+{
+ int slen, sublen;
+
+ if (!s || !sub)
+ return 1;
+
+ slen = strlen(s);
+ sublen = strlen(sub);
+
+ if ((slen == 0) || (sublen == 0))
+ return 1;
+
+ if (sublen > slen)
+ return 1;
+
+ return memcmp(s + slen - sublen, sub, sublen);
+}
+
+static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
+{
+ if (sym)
+ return elf->strtab + sym->st_name;
+ else
+ return "(unknown)";
+}
+
+static const char *sec_name(struct elf_info *elf, int secindex)
+{
+ Elf_Shdr *sechdrs = elf->sechdrs;
+ return (void *)elf->hdr +
+ elf->sechdrs[elf->secindex_strings].sh_offset +
+ sechdrs[secindex].sh_name;
+}
+
+static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
+{
+ return (void *)elf->hdr +
+ elf->sechdrs[elf->secindex_strings].sh_offset +
+ sechdr->sh_name;
+}
+
+/* if sym is empty or point to a string
+ * like ".[0-9]+" then return 1.
+ * This is the optional prefix added by ld to some sections
+ */
+static int number_prefix(const char *sym)
+{
+ if (*sym++ == '\0')
+ return 1;
+ if (*sym != '.')
+ return 0;
+ do {
+ char c = *sym++;
+ if (c < '0' || c > '9')
+ return 0;
+ } while (*sym);
+ return 1;
+}
+
+/* The pattern is an array of simple patterns.
+ * "foo" will match an exact string equal to "foo"
+ * "*foo" will match a string that ends with "foo"
+ * "foo*" will match a string that begins with "foo"
+ * "foo$" will match a string equal to "foo" or "foo.1"
+ * where the '1' can be any number including several digits.
+ * The $ syntax is for sections where ld append a dot number
+ * to make section name unique.
+ */
+static int match(const char *sym, const char * const pat[])
+{
+ const char *p;
+ while (*pat) {
+ p = *pat++;
+ const char *endp = p + strlen(p) - 1;
+
+ /* "*foo" */
+ if (*p == '*') {
+ if (strrcmp(sym, p + 1) == 0)
+ return 1;
+ }
+ /* "foo*" */
+ else if (*endp == '*') {
+ if (strncmp(sym, p, strlen(p) - 1) == 0)
+ return 1;
+ }
+ /* "foo$" */
+ else if (*endp == '$') {
+ if (strncmp(sym, p, strlen(p) - 1) == 0) {
+ if (number_prefix(sym + strlen(p) - 1))
+ return 1;
+ }
+ }
+ /* no wildcards */
+ else {
+ if (strcmp(p, sym) == 0)
+ return 1;
+ }
+ }
+ /* no match */
+ return 0;
+}
+
+/* sections that we do not want to do full section mismatch check on */
+static const char *section_white_list[] =
+{
+ ".comment*",
+ ".debug*",
+ ".zdebug*", /* Compressed debug sections. */
+ ".GCC-command-line", /* mn10300 */
+ ".GCC.command.line", /* record-gcc-switches, non mn10300 */
+ ".mdebug*", /* alpha, score, mips etc. */
+ ".pdr", /* alpha, score, mips etc. */
+ ".stab*",
+ ".note*",
+ ".got*",
+ ".toc*",
+ ".xt.prop", /* xtensa */
+ ".xt.lit", /* xtensa */
+ ".arcextmap*", /* arc */
+ ".gnu.linkonce.arcext*", /* arc : modules */
+ NULL
+};
+
+/*
+ * This is used to find sections missing the SHF_ALLOC flag.
+ * The cause of this is often a section specified in assembler
+ * without "ax" / "aw".
+ */
+static void check_section(const char *modname, struct elf_info *elf,
+ Elf_Shdr *sechdr)
+{
+ const char *sec = sech_name(elf, sechdr);
+
+ if (sechdr->sh_type == SHT_PROGBITS &&
+ !(sechdr->sh_flags & SHF_ALLOC) &&
+ !match(sec, section_white_list)) {
+ warn("%s (%s): unexpected non-allocatable section.\n"
+ "Did you forget to use \"ax\"/\"aw\" in a .S file?\n"
+ "Note that for example <linux/init.h> contains\n"
+ "section definitions for use in .S files.\n\n",
+ modname, sec);
+ }
+}
+
+
+
+#define ALL_INIT_DATA_SECTIONS \
+ ".init.setup$", ".init.rodata$", \
+ ".cpuinit.rodata$", ".meminit.rodata$", \
+ ".init.data$", ".cpuinit.data$", ".meminit.data$"
+#define ALL_EXIT_DATA_SECTIONS \
+ ".exit.data$", ".cpuexit.data$", ".memexit.data$"
+
+#define ALL_INIT_TEXT_SECTIONS \
+ ".init.text$", ".cpuinit.text$", ".meminit.text$"
+#define ALL_EXIT_TEXT_SECTIONS \
+ ".exit.text$", ".cpuexit.text$", ".memexit.text$"
+
+#define ALL_PCI_INIT_SECTIONS \
+ ".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \
+ ".pci_fixup_enable$", ".pci_fixup_resume$", \
+ ".pci_fixup_resume_early$", ".pci_fixup_suspend$"
+
+#define ALL_XXXINIT_SECTIONS CPU_INIT_SECTIONS, MEM_INIT_SECTIONS
+#define ALL_XXXEXIT_SECTIONS CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS
+
+#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS
+#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
+
+#define DATA_SECTIONS ".data$", ".data.rel$"
+#define TEXT_SECTIONS ".text$"
+
+#define INIT_SECTIONS ".init.*"
+#define CPU_INIT_SECTIONS ".cpuinit.*"
+#define MEM_INIT_SECTIONS ".meminit.*"
+
+#define EXIT_SECTIONS ".exit.*"
+#define CPU_EXIT_SECTIONS ".cpuexit.*"
+#define MEM_EXIT_SECTIONS ".memexit.*"
+
+/* init data sections */
+static const char *init_data_sections[] = { ALL_INIT_DATA_SECTIONS, NULL };
+
+/* all init sections */
+static const char *init_sections[] = { ALL_INIT_SECTIONS, NULL };
+
+/* All init and exit sections (code + data) */
+static const char *init_exit_sections[] =
+ {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };
+
+/* data section */
+static const char *data_sections[] = { DATA_SECTIONS, NULL };
+
+
+/* symbols in .data that may refer to init/exit sections */
+#define DEFAULT_SYMBOL_WHITE_LIST \
+ "*driver", \
+ "*_template", /* scsi uses *_template a lot */ \
+ "*_timer", /* arm uses ops structures named _timer a lot */ \
+ "*_sht", /* scsi also used *_sht to some extent */ \
+ "*_ops", \
+ "*_probe", \
+ "*_probe_one", \
+ "*_console"
+
+static const char *head_sections[] = { ".head.text*", NULL };
+static const char *linker_symbols[] =
+ { "__init_begin", "_sinittext", "_einittext", NULL };
+
+enum mismatch {
+ TEXT_TO_ANY_INIT,
+ DATA_TO_ANY_INIT,
+ TEXT_TO_ANY_EXIT,
+ DATA_TO_ANY_EXIT,
+ XXXINIT_TO_SOME_INIT,
+ XXXEXIT_TO_SOME_EXIT,
+ ANY_INIT_TO_ANY_EXIT,
+ ANY_EXIT_TO_ANY_INIT,
+ EXPORT_TO_INIT_EXIT,
+};
+
+struct sectioncheck {
+ const char *fromsec[20];
+ const char *tosec[20];
+ enum mismatch mismatch;
+ const char *symbol_white_list[20];
+};
+
+const struct sectioncheck sectioncheck[] = {
+/* Do not reference init/exit code/data from
+ * normal code and data
+ */
+{
+ .fromsec = { TEXT_SECTIONS, NULL },
+ .tosec = { ALL_INIT_SECTIONS, NULL },
+ .mismatch = TEXT_TO_ANY_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+{
+ .fromsec = { DATA_SECTIONS, NULL },
+ .tosec = { ALL_XXXINIT_SECTIONS, NULL },
+ .mismatch = DATA_TO_ANY_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+{
+ .fromsec = { DATA_SECTIONS, NULL },
+ .tosec = { INIT_SECTIONS, NULL },
+ .mismatch = DATA_TO_ANY_INIT,
+ .symbol_white_list = {
+ "*_template", "*_timer", "*_sht", "*_ops",
+ "*_probe", "*_probe_one", "*_console", NULL
+ },
+},
+{
+ .fromsec = { TEXT_SECTIONS, NULL },
+ .tosec = { ALL_EXIT_SECTIONS, NULL },
+ .mismatch = TEXT_TO_ANY_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+{
+ .fromsec = { DATA_SECTIONS, NULL },
+ .tosec = { ALL_EXIT_SECTIONS, NULL },
+ .mismatch = DATA_TO_ANY_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+/* Do not reference init code/data from cpuinit/meminit code/data */
+{
+ .fromsec = { ALL_XXXINIT_SECTIONS, NULL },
+ .tosec = { INIT_SECTIONS, NULL },
+ .mismatch = XXXINIT_TO_SOME_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+/* Do not reference cpuinit code/data from meminit code/data */
+{
+ .fromsec = { MEM_INIT_SECTIONS, NULL },
+ .tosec = { CPU_INIT_SECTIONS, NULL },
+ .mismatch = XXXINIT_TO_SOME_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+/* Do not reference meminit code/data from cpuinit code/data */
+{
+ .fromsec = { CPU_INIT_SECTIONS, NULL },
+ .tosec = { MEM_INIT_SECTIONS, NULL },
+ .mismatch = XXXINIT_TO_SOME_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+/* Do not reference exit code/data from cpuexit/memexit code/data */
+{
+ .fromsec = { ALL_XXXEXIT_SECTIONS, NULL },
+ .tosec = { EXIT_SECTIONS, NULL },
+ .mismatch = XXXEXIT_TO_SOME_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+/* Do not reference cpuexit code/data from memexit code/data */
+{
+ .fromsec = { MEM_EXIT_SECTIONS, NULL },
+ .tosec = { CPU_EXIT_SECTIONS, NULL },
+ .mismatch = XXXEXIT_TO_SOME_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+/* Do not reference memexit code/data from cpuexit code/data */
+{
+ .fromsec = { CPU_EXIT_SECTIONS, NULL },
+ .tosec = { MEM_EXIT_SECTIONS, NULL },
+ .mismatch = XXXEXIT_TO_SOME_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+/* Do not use exit code/data from init code */
+{
+ .fromsec = { ALL_INIT_SECTIONS, NULL },
+ .tosec = { ALL_EXIT_SECTIONS, NULL },
+ .mismatch = ANY_INIT_TO_ANY_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+/* Do not use init code/data from exit code */
+{
+ .fromsec = { ALL_EXIT_SECTIONS, NULL },
+ .tosec = { ALL_INIT_SECTIONS, NULL },
+ .mismatch = ANY_EXIT_TO_ANY_INIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+{
+ .fromsec = { ALL_PCI_INIT_SECTIONS, NULL },
+ .tosec = { INIT_SECTIONS, NULL },
+ .mismatch = ANY_INIT_TO_ANY_EXIT,
+ .symbol_white_list = { NULL },
+},
+/* Do not export init/exit functions or data */
+{
+ .fromsec = { "__ksymtab*", NULL },
+ .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
+ .mismatch = EXPORT_TO_INIT_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+}
+};
+
+static const struct sectioncheck *section_mismatch(
+ const char *fromsec, const char *tosec)
+{
+ int i;
+ int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
+ const struct sectioncheck *check = §ioncheck[0];
+
+ for (i = 0; i < elems; i++) {
+ if (match(fromsec, check->fromsec) &&
+ match(tosec, check->tosec))
+ return check;
+ check++;
+ }
+ return NULL;
+}
+
+/**
+ * Whitelist to allow certain references to pass with no warning.
+ *
+ * Pattern 1:
+ * If a module parameter is declared __initdata and permissions=0
+ * then this is legal despite the warning generated.
+ * We cannot see value of permissions here, so just ignore
+ * this pattern.
+ * The pattern is identified by:
+ * tosec = .init.data
+ * fromsec = .data*
+ * atsym =__param*
+ *
+ * Pattern 1a:
+ * module_param_call() ops can refer to __init set function if permissions=0
+ * The pattern is identified by:
+ * tosec = .init.text
+ * fromsec = .data*
+ * atsym = __param_ops_*
+ *
+ * Pattern 2:
+ * Many drivers utilise a *driver container with references to
+ * add, remove, probe functions etc.
+ * These functions may often be marked __cpuinit and we do not want to
+ * warn here.
+ * the pattern is identified by:
+ * tosec = init or exit section
+ * fromsec = data section
+ * atsym = *driver, *_template, *_sht, *_ops, *_probe,
+ * *probe_one, *_console, *_timer
+ *
+ * Pattern 3:
+ * Whitelist all references from .head.text to any init section
+ *
+ * Pattern 4:
+ * Some symbols belong to init section but still it is ok to reference
+ * these from non-init sections as these symbols don't have any memory
+ * allocated for them and symbol address and value are same. So even
+ * if init section is freed, its ok to reference those symbols.
+ * For ex. symbols marking the init section boundaries.
+ * This pattern is identified by
+ * refsymname = __init_begin, _sinittext, _einittext
+ *
+ **/
+static int secref_whitelist(const struct sectioncheck *mismatch,
+ const char *fromsec, const char *fromsym,
+ const char *tosec, const char *tosym)
+{
+ /* Check for pattern 1 */
+ if (match(tosec, init_data_sections) &&
+ match(fromsec, data_sections) &&
+ (strncmp(fromsym, "__param", strlen("__param")) == 0))
+ return 0;
+
+ /* Check for pattern 1a */
+ if (strcmp(tosec, ".init.text") == 0 &&
+ match(fromsec, data_sections) &&
+ (strncmp(fromsym, "__param_ops_", strlen("__param_ops_")) == 0))
+ return 0;
+
+ /* Check for pattern 2 */
+ if (match(tosec, init_exit_sections) &&
+ match(fromsec, data_sections) &&
+ match(fromsym, mismatch->symbol_white_list))
+ return 0;
+
+ /* Check for pattern 3 */
+ if (match(fromsec, head_sections) &&
+ match(tosec, init_sections))
+ return 0;
+
+ /* Check for pattern 4 */
+ if (match(tosym, linker_symbols))
+ return 0;
+
+ return 1;
+}
+
+/**
+ * Find symbol based on relocation record info.
+ * In some cases the symbol supplied is a valid symbol so
+ * return refsym. If st_name != 0 we assume this is a valid symbol.
+ * In other cases the symbol needs to be looked up in the symbol table
+ * based on section and address.
+ * **/
+static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
+ Elf_Sym *relsym)
+{
+ Elf_Sym *sym;
+ Elf_Sym *near = NULL;
+ Elf64_Sword distance = 20;
+ Elf64_Sword d;
+ unsigned int relsym_secindex;
+
+ if (relsym->st_name != 0)
+ return relsym;
+
+ relsym_secindex = get_secindex(elf, relsym);
+ for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
+ if (get_secindex(elf, sym) != relsym_secindex)
+ continue;
+ if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
+ continue;
+ if (sym->st_value == addr)
+ return sym;
+ /* Find a symbol nearby - addr are maybe negative */
+ d = sym->st_value - addr;
+ if (d < 0)
+ d = addr - sym->st_value;
+ if (d < distance) {
+ distance = d;
+ near = sym;
+ }
+ }
+ /* We need a close match */
+ if (distance < 20)
+ return near;
+ else
+ return NULL;
+}
+
+static inline int is_arm_mapping_symbol(const char *str)
+{
+ return str[0] == '$' && strchr("atd", str[1])
+ && (str[2] == '\0' || str[2] == '.');
+}
+
+/*
+ * If there's no name there, ignore it; likewise, ignore it if it's
+ * one of the magic symbols emitted used by current ARM tools.
+ *
+ * Otherwise if find_symbols_between() returns those symbols, they'll
+ * fail the whitelist tests and cause lots of false alarms ... fixable
+ * only by merging __exit and __init sections into __text, bloating
+ * the kernel (which is especially evil on embedded platforms).
+ */
+static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
+{
+ const char *name = elf->strtab + sym->st_name;
+
+ if (!name || !strlen(name))
+ return 0;
+ return !is_arm_mapping_symbol(name);
+}
+
+/*
+ * Find symbols before or equal addr and after addr - in the section sec.
+ * If we find two symbols with equal offset prefer one with a valid name.
+ * The ELF format may have a better way to detect what type of symbol
+ * it is, but this works for now.
+ **/
+static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
+ const char *sec)
+{
+ Elf_Sym *sym;
+ Elf_Sym *near = NULL;
+ Elf_Addr distance = ~0;
+
+ for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
+ const char *symsec;
+
+ if (is_shndx_special(sym->st_shndx))
+ continue;
+ symsec = sec_name(elf, get_secindex(elf, sym));
+ if (strcmp(symsec, sec) != 0)
+ continue;
+ if (!is_valid_name(elf, sym))
+ continue;
+ if (sym->st_value <= addr) {
+ if ((addr - sym->st_value) < distance) {
+ distance = addr - sym->st_value;
+ near = sym;
+ } else if ((addr - sym->st_value) == distance) {
+ near = sym;
+ }
+ }
+ }
+ return near;
+}
+
+/*
+ * Convert a section name to the function/data attribute
+ * .init.text => __init
+ * .cpuinit.data => __cpudata
+ * .memexitconst => __memconst
+ * etc.
+ *
+ * The memory of returned value has been allocated on a heap. The user of this
+ * method should free it after usage.
+*/
+static char *sec2annotation(const char *s)
+{
+ if (match(s, init_exit_sections)) {
+ char *p = malloc(20);
+ char *r = p;
+
+ *p++ = '_';
+ *p++ = '_';
+ if (*s == '.')
+ s++;
+ while (*s && *s != '.')
+ *p++ = *s++;
+ *p = '\0';
+ if (*s == '.')
+ s++;
+ if (strstr(s, "rodata") != NULL)
+ strcat(p, "const ");
+ else if (strstr(s, "data") != NULL)
+ strcat(p, "data ");
+ else
+ strcat(p, " ");
+ return r;
+ } else {
+ return strdup("");
+ }
+}
+
+static int is_function(Elf_Sym *sym)
+{
+ if (sym)
+ return ELF_ST_TYPE(sym->st_info) == STT_FUNC;
+ else
+ return -1;
+}
+
+static void print_section_list(const char * const list[20])
+{
+ const char *const *s = list;
+
+ while (*s) {
+ fprintf(stderr, "%s", *s);
+ s++;
+ if (*s)
+ fprintf(stderr, ", ");
+ }
+ fprintf(stderr, "\n");
+}
+
+/*
+ * Print a warning about a section mismatch.
+ * Try to find symbols near it so user can find it.
+ * Check whitelist before warning - it may be a false positive.
+ */
+static void report_sec_mismatch(const char *modname,
+ const struct sectioncheck *mismatch,
+ const char *fromsec,
+ unsigned long long fromaddr,
+ const char *fromsym,
+ int from_is_func,
+ const char *tosec, const char *tosym,
+ int to_is_func)
+{
+ const char *from, *from_p;
+ const char *to, *to_p;
+ char *prl_from;
+ char *prl_to;
+
+ switch (from_is_func) {
+ case 0: from = "variable"; from_p = ""; break;
+ case 1: from = "function"; from_p = "()"; break;
+ default: from = "(unknown reference)"; from_p = ""; break;
+ }
+ switch (to_is_func) {
+ case 0: to = "variable"; to_p = ""; break;
+ case 1: to = "function"; to_p = "()"; break;
+ default: to = "(unknown reference)"; to_p = ""; break;
+ }
+
+ sec_mismatch_count++;
+ if (!sec_mismatch_verbose)
+ return;
+
+ warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s "
+ "to the %s %s:%s%s\n",
+ modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec,
+ tosym, to_p);
+
+ switch (mismatch->mismatch) {
+ case TEXT_TO_ANY_INIT:
+ prl_from = sec2annotation(fromsec);
+ prl_to = sec2annotation(tosec);
+ fprintf(stderr,
+ "The function %s%s() references\n"
+ "the %s %s%s%s.\n"
+ "This is often because %s lacks a %s\n"
+ "annotation or the annotation of %s is wrong.\n",
+ prl_from, fromsym,
+ to, prl_to, tosym, to_p,
+ fromsym, prl_to, tosym);
+ free(prl_from);
+ free(prl_to);
+ break;
+ case DATA_TO_ANY_INIT: {
+ prl_to = sec2annotation(tosec);
+ fprintf(stderr,
+ "The variable %s references\n"
+ "the %s %s%s%s\n"
+ "If the reference is valid then annotate the\n"
+ "variable with __init* or __refdata (see linux/init.h) "
+ "or name the variable:\n",
+ fromsym, to, prl_to, tosym, to_p);
+ print_section_list(mismatch->symbol_white_list);
+ free(prl_to);
+ break;
+ }
+ case TEXT_TO_ANY_EXIT:
+ prl_to = sec2annotation(tosec);
+ fprintf(stderr,
+ "The function %s() references a %s in an exit section.\n"
+ "Often the %s %s%s has valid usage outside the exit section\n"
+ "and the fix is to remove the %sannotation of %s.\n",
+ fromsym, to, to, tosym, to_p, prl_to, tosym);
+ free(prl_to);
+ break;
+ case DATA_TO_ANY_EXIT: {
+ prl_to = sec2annotation(tosec);
+ fprintf(stderr,
+ "The variable %s references\n"
+ "the %s %s%s%s\n"
+ "If the reference is valid then annotate the\n"
+ "variable with __exit* (see linux/init.h) or "
+ "name the variable:\n",
+ fromsym, to, prl_to, tosym, to_p);
+ print_section_list(mismatch->symbol_white_list);
+ free(prl_to);
+ break;
+ }
+ case XXXINIT_TO_SOME_INIT:
+ case XXXEXIT_TO_SOME_EXIT:
+ prl_from = sec2annotation(fromsec);
+ prl_to = sec2annotation(tosec);
+ fprintf(stderr,
+ "The %s %s%s%s references\n"
+ "a %s %s%s%s.\n"
+ "If %s is only used by %s then\n"
+ "annotate %s with a matching annotation.\n",
+ from, prl_from, fromsym, from_p,
+ to, prl_to, tosym, to_p,
+ tosym, fromsym, tosym);
+ free(prl_from);
+ free(prl_to);
+ break;
+ case ANY_INIT_TO_ANY_EXIT:
+ prl_from = sec2annotation(fromsec);
+ prl_to = sec2annotation(tosec);
+ fprintf(stderr,
+ "The %s %s%s%s references\n"
+ "a %s %s%s%s.\n"
+ "This is often seen when error handling "
+ "in the init function\n"
+ "uses functionality in the exit path.\n"
+ "The fix is often to remove the %sannotation of\n"
+ "%s%s so it may be used outside an exit section.\n",
+ from, prl_from, fromsym, from_p,
+ to, prl_to, tosym, to_p,
+ prl_to, tosym, to_p);
+ free(prl_from);
+ free(prl_to);
+ break;
+ case ANY_EXIT_TO_ANY_INIT:
+ prl_from = sec2annotation(fromsec);
+ prl_to = sec2annotation(tosec);
+ fprintf(stderr,
+ "The %s %s%s%s references\n"
+ "a %s %s%s%s.\n"
+ "This is often seen when error handling "
+ "in the exit function\n"
+ "uses functionality in the init path.\n"
+ "The fix is often to remove the %sannotation of\n"
+ "%s%s so it may be used outside an init section.\n",
+ from, prl_from, fromsym, from_p,
+ to, prl_to, tosym, to_p,
+ prl_to, tosym, to_p);
+ free(prl_from);
+ free(prl_to);
+ break;
+ case EXPORT_TO_INIT_EXIT:
+ prl_to = sec2annotation(tosec);
+ fprintf(stderr,
+ "The symbol %s is exported and annotated %s\n"
+ "Fix this by removing the %sannotation of %s "
+ "or drop the export.\n",
+ tosym, prl_to, prl_to, tosym);
+ free(prl_to);
+ break;
+ }
+ fprintf(stderr, "\n");
+}
+
+static void check_section_mismatch(const char *modname, struct elf_info *elf,
+ Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
+{
+ const char *tosec;
+ const struct sectioncheck *mismatch;
+
+ tosec = sec_name(elf, get_secindex(elf, sym));
+ mismatch = section_mismatch(fromsec, tosec);
+ if (mismatch) {
+ Elf_Sym *to;
+ Elf_Sym *from;
+ const char *tosym;
+ const char *fromsym;
+
+ from = find_elf_symbol2(elf, r->r_offset, fromsec);
+ fromsym = sym_name(elf, from);
+ to = find_elf_symbol(elf, r->r_addend, sym);
+ tosym = sym_name(elf, to);
+
+ /* check whitelist - we may ignore it */
+ if (secref_whitelist(mismatch,
+ fromsec, fromsym, tosec, tosym)) {
+ report_sec_mismatch(modname, mismatch,
+ fromsec, r->r_offset, fromsym,
+ is_function(from), tosec, tosym,
+ is_function(to));
+ }
+ }
+}
+
+static unsigned int *reloc_location(struct elf_info *elf,
+ Elf_Shdr *sechdr, Elf_Rela *r)
+{
+ Elf_Shdr *sechdrs = elf->sechdrs;
+ int section = sechdr->sh_info;
+
+ return (void *)elf->hdr + sechdrs[section].sh_offset +
+ r->r_offset;
+}
+
+static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
+{
+ unsigned int r_typ = ELF_R_TYPE(r->r_info);
+ unsigned int *location = reloc_location(elf, sechdr, r);
+
+ switch (r_typ) {
+ case R_386_32:
+ r->r_addend = TO_NATIVE(*location);
+ break;
+ case R_386_PC32:
+ r->r_addend = TO_NATIVE(*location) + 4;
+ /* For CONFIG_RELOCATABLE=y */
+ if (elf->hdr->e_type == ET_EXEC)
+ r->r_addend += r->r_offset;
+ break;
+ }
+ return 0;
+}
+
+#ifndef R_ARM_CALL
+#define R_ARM_CALL 28
+#endif
+#ifndef R_ARM_JUMP24
+#define R_ARM_JUMP24 29
+#endif
+
+static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
+{
+ unsigned int r_typ = ELF_R_TYPE(r->r_info);
+
+ switch (r_typ) {
+ case R_ARM_ABS32:
+ /* From ARM ABI: (S + A) | T */
+ r->r_addend = (int)(long)
+ (elf->symtab_start + ELF_R_SYM(r->r_info));
+ break;
+ case R_ARM_PC24:
+ case R_ARM_CALL:
+ case R_ARM_JUMP24:
+ /* From ARM ABI: ((S + A) | T) - P */
+ r->r_addend = (int)(long)(elf->hdr +
+ sechdr->sh_offset +
+ (r->r_offset - sechdr->sh_addr));
+ break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
+{
+ unsigned int r_typ = ELF_R_TYPE(r->r_info);
+ unsigned int *location = reloc_location(elf, sechdr, r);
+ unsigned int inst;
+
+ if (r_typ == R_MIPS_HI16)
+ return 1; /* skip this */
+ inst = TO_NATIVE(*location);
+ switch (r_typ) {
+ case R_MIPS_LO16:
+ r->r_addend = inst & 0xffff;
+ break;
+ case R_MIPS_26:
+ r->r_addend = (inst & 0x03ffffff) << 2;
+ break;
+ case R_MIPS_32:
+ r->r_addend = inst;
+ break;
+ }
+ return 0;
+}
+
+static void section_rela(const char *modname, struct elf_info *elf,
+ Elf_Shdr *sechdr)
+{
+ Elf_Sym *sym;
+ Elf_Rela *rela;
+ Elf_Rela r;
+ unsigned int r_sym;
+ const char *fromsec;
+
+ Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset;
+ Elf_Rela *stop = (void *)start + sechdr->sh_size;
+
+ fromsec = sech_name(elf, sechdr);
+ fromsec += strlen(".rela");
+ /* if from section (name) is know good then skip it */
+ if (match(fromsec, section_white_list))
+ return;
+
+ for (rela = start; rela < stop; rela++) {
+ r.r_offset = TO_NATIVE(rela->r_offset);
+#if KERNEL_ELFCLASS == ELFCLASS64
+ if (elf->hdr->e_machine == EM_MIPS) {
+ unsigned int r_typ;
+ r_sym = ELF64_MIPS_R_SYM(rela->r_info);
+ r_sym = TO_NATIVE(r_sym);
+ r_typ = ELF64_MIPS_R_TYPE(rela->r_info);
+ r.r_info = ELF64_R_INFO(r_sym, r_typ);
+ } else {
+ r.r_info = TO_NATIVE(rela->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+ }
+#else
+ r.r_info = TO_NATIVE(rela->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+#endif
+ r.r_addend = TO_NATIVE(rela->r_addend);
+ sym = elf->symtab_start + r_sym;
+ /* Skip special sections */
+ if (is_shndx_special(sym->st_shndx))
+ continue;
+ check_section_mismatch(modname, elf, &r, sym, fromsec);
+ }
+}
+
+static void section_rel(const char *modname, struct elf_info *elf,
+ Elf_Shdr *sechdr)
+{
+ Elf_Sym *sym;
+ Elf_Rel *rel;
+ Elf_Rela r;
+ unsigned int r_sym;
+ const char *fromsec;
+
+ Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset;
+ Elf_Rel *stop = (void *)start + sechdr->sh_size;
+
+ fromsec = sech_name(elf, sechdr);
+ fromsec += strlen(".rel");
+ /* if from section (name) is know good then skip it */
+ if (match(fromsec, section_white_list))
+ return;
+
+ for (rel = start; rel < stop; rel++) {
+ r.r_offset = TO_NATIVE(rel->r_offset);
+#if KERNEL_ELFCLASS == ELFCLASS64
+ if (elf->hdr->e_machine == EM_MIPS) {
+ unsigned int r_typ;
+ r_sym = ELF64_MIPS_R_SYM(rel->r_info);
+ r_sym = TO_NATIVE(r_sym);
+ r_typ = ELF64_MIPS_R_TYPE(rel->r_info);
+ r.r_info = ELF64_R_INFO(r_sym, r_typ);
+ } else {
+ r.r_info = TO_NATIVE(rel->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+ }
+#else
+ r.r_info = TO_NATIVE(rel->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+#endif
+ r.r_addend = 0;
+ switch (elf->hdr->e_machine) {
+ case EM_386:
+ if (addend_386_rel(elf, sechdr, &r))
+ continue;
+ break;
+ case EM_ARM:
+ if (addend_arm_rel(elf, sechdr, &r))
+ continue;
+ break;
+ case EM_MIPS:
+ if (addend_mips_rel(elf, sechdr, &r))
+ continue;
+ break;
+ }
+ sym = elf->symtab_start + r_sym;
+ /* Skip special sections */
+ if (is_shndx_special(sym->st_shndx))
+ continue;
+ check_section_mismatch(modname, elf, &r, sym, fromsec);
+ }
+}
+
+/**
+ * A module includes a number of sections that are discarded
+ * either when loaded or when used as built-in.
+ * For loaded modules all functions marked __init and all data
+ * marked __initdata will be discarded when the module has been initialized.
+ * Likewise for modules used built-in the sections marked __exit
+ * are discarded because __exit marked function are supposed to be called
+ * only when a module is unloaded which never happens for built-in modules.
+ * The check_sec_ref() function traverses all relocation records
+ * to find all references to a section that reference a section that will
+ * be discarded and warns about it.
+ **/
+static void check_sec_ref(struct module *mod, const char *modname,
+ struct elf_info *elf)
+{
+ int i;
+ Elf_Shdr *sechdrs = elf->sechdrs;
+
+ /* Walk through all sections */
+ for (i = 0; i < elf->num_sections; i++) {
+ check_section(modname, elf, &elf->sechdrs[i]);
+ /* We want to process only relocation sections and not .init */
+ if (sechdrs[i].sh_type == SHT_RELA)
+ section_rela(modname, elf, &elf->sechdrs[i]);
+ else if (sechdrs[i].sh_type == SHT_REL)
+ section_rel(modname, elf, &elf->sechdrs[i]);
+ }
+}
+
+static void read_symbols(char *modname)
+{
+ const char *symname;
+ char *version;
+ char *license;
+ struct module *mod;
+ struct elf_info info = { };
+ Elf_Sym *sym;
+
+ if (!parse_elf(&info, modname))
+ return;
+
+ mod = new_module(modname);
+
+ /* When there's no vmlinux, don't print warnings about
+ * unresolved symbols (since there'll be too many ;) */
+ if (is_vmlinux(modname)) {
+ have_vmlinux = 1;
+ mod->skip = 1;
+ }
+
+ license = get_modinfo(info.modinfo, info.modinfo_len, "license");
+ if (info.modinfo && !license && !is_vmlinux(modname))
+ warn("modpost: missing MODULE_LICENSE() in %s\n"
+ "see include/linux/module.h for "
+ "more information\n", modname);
+ while (license) {
+ if (license_is_gpl_compatible(license))
+ mod->gpl_compatible = 1;
+ else {
+ mod->gpl_compatible = 0;
+ break;
+ }
+ license = get_next_modinfo(info.modinfo, info.modinfo_len,
+ "license", license);
+ }
+
+ for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
+ symname = info.strtab + sym->st_name;
+
+ handle_modversions(mod, &info, sym, symname);
+ handle_moddevtable(mod, &info, sym, symname);
+ }
+ if (!is_vmlinux(modname) ||
+ (is_vmlinux(modname) && vmlinux_section_warnings))
+ check_sec_ref(mod, modname, &info);
+
+ version = get_modinfo(info.modinfo, info.modinfo_len, "version");
+ if (version)
+ maybe_frob_rcs_version(modname, version, info.modinfo,
+ version - (char *)info.hdr);
+ if (version || (all_versions && !is_vmlinux(modname)))
+ get_src_version(modname, mod->srcversion,
+ sizeof(mod->srcversion)-1);
+
+ parse_elf_finish(&info);
+
+ /* Our trick to get versioning for module struct etc. - it's
+ * never passed as an argument to an exported function, so
+ * the automatic versioning doesn't pick it up, but it's really
+ * important anyhow */
+ if (modversions)
+ mod->unres = alloc_symbol("module_layout", 0, mod->unres);
+}
+
+#define SZ 500
+
+/* We first write the generated file into memory using the
+ * following helper, then compare to the file on disk and
+ * only update the later if anything changed */
+
+void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf,
+ const char *fmt, ...)
+{
+ char tmp[SZ];
+ int len;
+ va_list ap;
+
+ va_start(ap, fmt);
+ len = vsnprintf(tmp, SZ, fmt, ap);
+ buf_write(buf, tmp, len);
+ va_end(ap);
+}
+
+void buf_write(struct buffer *buf, const char *s, int len)
+{
+ if (buf->size - buf->pos < len) {
+ buf->size += len + SZ;
+ buf->p = realloc(buf->p, buf->size);
+ }
+ strncpy(buf->p + buf->pos, s, len);
+ buf->pos += len;
+}
+
+static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
+{
+ const char *e = is_vmlinux(m) ?"":".ko";
+
+ switch (exp) {
+ case export_gpl:
+ fatal("modpost: GPL-incompatible module %s%s "
+ "uses GPL-only symbol '%s'\n", m, e, s);
+ break;
+ case export_unused_gpl:
+ fatal("modpost: GPL-incompatible module %s%s "
+ "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s);
+ break;
+ case export_gpl_future:
+ warn("modpost: GPL-incompatible module %s%s "
+ "uses future GPL-only symbol '%s'\n", m, e, s);
+ break;
+ case export_plain:
+ case export_unused:
+ case export_unknown:
+ /* ignore */
+ break;
+ }
+}
+
+static void check_for_unused(enum export exp, const char *m, const char *s)
+{
+ const char *e = is_vmlinux(m) ?"":".ko";
+
+ switch (exp) {
+ case export_unused:
+ case export_unused_gpl:
+ warn("modpost: module %s%s "
+ "uses symbol '%s' marked UNUSED\n", m, e, s);
+ break;
+ default:
+ /* ignore */
+ break;
+ }
+}
+
+static void check_exports(struct module *mod)
+{
+ struct symbol *s, *exp;
+
+ for (s = mod->unres; s; s = s->next) {
+ const char *basename;
+ exp = find_symbol(s->name);
+ if (!exp || exp->module == mod)
+ continue;
+ basename = strrchr(mod->name, '/');
+ if (basename)
+ basename++;
+ else
+ basename = mod->name;
+ if (!mod->gpl_compatible)
+ check_for_gpl_usage(exp->export, basename, exp->name);
+ check_for_unused(exp->export, basename, exp->name);
+ }
+}
+
+/**
+ * Header for the generated file
+ **/
+static void add_header(struct buffer *b, struct module *mod)
+{
+ buf_printf(b, "#include <linux/module.h>\n");
+ buf_printf(b, "#include <linux/vermagic.h>\n");
+ buf_printf(b, "#include <linux/compiler.h>\n");
+ buf_printf(b, "\n");
+ buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
+ buf_printf(b, "\n");
+ buf_printf(b, "struct module __this_module\n");
+ buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
+ buf_printf(b, "\t.name = KBUILD_MODNAME,\n");
+ if (mod->has_init)
+ buf_printf(b, "\t.init = init_module,\n");
+ if (mod->has_cleanup)
+ buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
+ "\t.exit = cleanup_module,\n"
+ "#endif\n");
+ buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n");
+ buf_printf(b, "};\n");
+}
+
+static void add_intree_flag(struct buffer *b, int is_intree)
+{
+ if (is_intree)
+ buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n");
+}
+
+static void add_staging_flag(struct buffer *b, const char *name)
+{
+ static const char *staging_dir = "drivers/staging";
+
+ if (strncmp(staging_dir, name, strlen(staging_dir)) == 0)
+ buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n");
+}
+
+/**
+ * Record CRCs for unresolved symbols
+ **/
+static int add_versions(struct buffer *b, struct module *mod)
+{
+ struct symbol *s, *exp;
+ int err = 0;
+
+ for (s = mod->unres; s; s = s->next) {
+ exp = find_symbol(s->name);
+ if (!exp || exp->module == mod) {
+ if (have_vmlinux && !s->weak) {
+ if (warn_unresolved) {
+ warn("\"%s\" [%s.ko] undefined!\n",
+ s->name, mod->name);
+ } else {
+ merror("\"%s\" [%s.ko] undefined!\n",
+ s->name, mod->name);
+ err = 1;
+ }
+ }
+ continue;
+ }
+ s->module = exp->module;
+ s->crc_valid = exp->crc_valid;
+ s->crc = exp->crc;
+ }
+
+ if (!modversions)
+ return err;
+
+ buf_printf(b, "\n");
+ buf_printf(b, "static const struct modversion_info ____versions[]\n");
+ buf_printf(b, "__used\n");
+ buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n");
+
+ for (s = mod->unres; s; s = s->next) {
+ if (!s->module)
+ continue;
+ if (!s->crc_valid) {
+ warn("\"%s\" [%s.ko] has no CRC!\n",
+ s->name, mod->name);
+ continue;
+ }
+ buf_printf(b, "\t{ %#8x, \"%s\" },\n", s->crc, s->name);
+ }
+
+ buf_printf(b, "};\n");
+
+ return err;
+}
+
+static void add_depends(struct buffer *b, struct module *mod,
+ struct module *modules)
+{
+ struct symbol *s;
+ struct module *m;
+ int first = 1;
+
+ for (m = modules; m; m = m->next)
+ m->seen = is_vmlinux(m->name);
+
+ buf_printf(b, "\n");
+ buf_printf(b, "static const char __module_depends[]\n");
+ buf_printf(b, "__used\n");
+ buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n");
+ buf_printf(b, "\"depends=");
+ for (s = mod->unres; s; s = s->next) {
+ const char *p;
+ if (!s->module)
+ continue;
+
+ if (s->module->seen)
+ continue;
+
+ s->module->seen = 1;
+ p = strrchr(s->module->name, '/');
+ if (p)
+ p++;
+ else
+ p = s->module->name;
+ buf_printf(b, "%s%s", first ? "" : ",", p);
+ first = 0;
+ }
+ buf_printf(b, "\";\n");
+}
+
+static void add_srcversion(struct buffer *b, struct module *mod)
+{
+ if (mod->srcversion[0]) {
+ buf_printf(b, "\n");
+ buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n",
+ mod->srcversion);
+ }
+}
+
+static void write_if_changed(struct buffer *b, const char *fname)
+{
+ char *tmp;
+ FILE *file;
+ struct stat st;
+
+ file = fopen(fname, "r");
+ if (!file)
+ goto write;
+
+ if (fstat(fileno(file), &st) < 0)
+ goto close_write;
+
+ if (st.st_size != b->pos)
+ goto close_write;
+
+ tmp = NOFAIL(malloc(b->pos));
+ if (fread(tmp, 1, b->pos, file) != b->pos)
+ goto free_write;
+
+ if (memcmp(tmp, b->p, b->pos) != 0)
+ goto free_write;
+
+ free(tmp);
+ fclose(file);
+ return;
+
+ free_write:
+ free(tmp);
+ close_write:
+ fclose(file);
+ write:
+ file = fopen(fname, "w");
+ if (!file) {
+ perror(fname);
+ exit(1);
+ }
+ if (fwrite(b->p, 1, b->pos, file) != b->pos) {
+ perror(fname);
+ exit(1);
+ }
+ fclose(file);
+}
+
+/* parse Module.symvers file. line format:
+ * 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something]
+ **/
+static void read_dump(const char *fname, unsigned int kernel)
+{
+ unsigned long size, pos = 0;
+ void *file = grab_file(fname, &size);
+ char *line;
+
+ if (!file)
+ /* No symbol versions, silently ignore */
+ return;
+
+ while ((line = get_next_line(&pos, file, size))) {
+ char *symname, *modname, *d, *export, *end;
+ unsigned int crc;
+ struct module *mod;
+ struct symbol *s;
+
+ if (!(symname = strchr(line, '\t')))
+ goto fail;
+ *symname++ = '\0';
+ if (!(modname = strchr(symname, '\t')))
+ goto fail;
+ *modname++ = '\0';
+ if ((export = strchr(modname, '\t')) != NULL)
+ *export++ = '\0';
+ if (export && ((end = strchr(export, '\t')) != NULL))
+ *end = '\0';
+ crc = strtoul(line, &d, 16);
+ if (*symname == '\0' || *modname == '\0' || *d != '\0')
+ goto fail;
+ mod = find_module(modname);
+ if (!mod) {
+ if (is_vmlinux(modname))
+ have_vmlinux = 1;
+ mod = new_module(modname);
+ mod->skip = 1;
+ }
+ s = sym_add_exported(symname, mod, export_no(export));
+ s->kernel = kernel;
+ s->preloaded = 1;
+ sym_update_crc(symname, mod, crc, export_no(export));
+ }
+ return;
+fail:
+ fatal("parse error in symbol dump file\n");
+}
+
+/* For normal builds always dump all symbols.
+ * For external modules only dump symbols
+ * that are not read from kernel Module.symvers.
+ **/
+static int dump_sym(struct symbol *sym)
+{
+ if (!external_module)
+ return 1;
+ if (sym->vmlinux || sym->kernel)
+ return 0;
+ return 1;
+}
+
+static void write_dump(const char *fname)
+{
+ struct buffer buf = { };
+ struct symbol *symbol;
+ int n;
+
+ for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
+ symbol = symbolhash[n];
+ while (symbol) {
+ if (dump_sym(symbol))
+ buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n",
+ symbol->crc, symbol->name,
+ symbol->module->name,
+ export_str(symbol->export));
+ symbol = symbol->next;
+ }
+ }
+ write_if_changed(&buf, fname);
+}
+
+struct ext_sym_list {
+ struct ext_sym_list *next;
+ const char *file;
+};
+
+int main(int argc, char **argv)
+{
+ struct module *mod;
+ struct buffer buf = { };
+ char *kernel_read = NULL, *module_read = NULL;
+ char *dump_write = NULL;
+ int opt;
+ int err;
+ struct ext_sym_list *extsym_iter;
+ struct ext_sym_list *extsym_start = NULL;
+
+ while ((opt = getopt(argc, argv, "i:I:e:msSo:awM:K:")) != -1) {
+ switch (opt) {
+ case 'i':
+ kernel_read = optarg;
+ break;
+ case 'I':
+ module_read = optarg;
+ external_module = 1;
+ break;
+ case 'e':
+ external_module = 1;
+ extsym_iter =
+ NOFAIL(malloc(sizeof(*extsym_iter)));
+ extsym_iter->next = extsym_start;
+ extsym_iter->file = optarg;
+ extsym_start = extsym_iter;
+ break;
+ case 'm':
+ modversions = 1;
+ break;
+ case 'o':
+ dump_write = optarg;
+ break;
+ case 'a':
+ all_versions = 1;
+ break;
+ case 's':
+ vmlinux_section_warnings = 0;
+ break;
+ case 'S':
+ sec_mismatch_verbose = 0;
+ break;
+ case 'w':
+ warn_unresolved = 1;
+ break;
+ default:
+ exit(1);
+ }
+ }
+
+ if (kernel_read)
+ read_dump(kernel_read, 1);
+ if (module_read)
+ read_dump(module_read, 0);
+ while (extsym_start) {
+ read_dump(extsym_start->file, 0);
+ extsym_iter = extsym_start->next;
+ free(extsym_start);
+ extsym_start = extsym_iter;
+ }
+
+ while (optind < argc)
+ read_symbols(argv[optind++]);
+
+ for (mod = modules; mod; mod = mod->next) {
+ if (mod->skip)
+ continue;
+ check_exports(mod);
+ }
+
+ err = 0;
+
+ for (mod = modules; mod; mod = mod->next) {
+ char fname[strlen(mod->name) + 10];
+
+ if (mod->skip)
+ continue;
+
+ buf.pos = 0;
+
+ add_header(&buf, mod);
+ add_intree_flag(&buf, !external_module);
+ add_staging_flag(&buf, mod->name);
+ err |= add_versions(&buf, mod);
+ add_depends(&buf, mod, modules);
+ add_moddevtable(&buf, mod);
+ add_srcversion(&buf, mod);
+
+ sprintf(fname, "%s.mod.c", mod->name);
+ write_if_changed(&buf, fname);
+ }
+
+ if (dump_write)
+ write_dump(dump_write);
+ if (sec_mismatch_count && !sec_mismatch_verbose)
+ warn("modpost: Found %d section mismatch(es).\n"
+ "To see full details build your kernel with:\n"
+ "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
+ sec_mismatch_count);
+
+ return err;
+}
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
new file mode 100644
index 0000000..51207e4
--- /dev/null
+++ b/scripts/mod/modpost.h
@@ -0,0 +1,187 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <elf.h>
+
+#include "elfconfig.h"
+
+#if KERNEL_ELFCLASS == ELFCLASS32
+
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Addr Elf32_Addr
+#define Elf_Sword Elf64_Sword
+#define Elf_Section Elf32_Half
+#define ELF_ST_BIND ELF32_ST_BIND
+#define ELF_ST_TYPE ELF32_ST_TYPE
+
+#define Elf_Rel Elf32_Rel
+#define Elf_Rela Elf32_Rela
+#define ELF_R_SYM ELF32_R_SYM
+#define ELF_R_TYPE ELF32_R_TYPE
+#else
+
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Addr Elf64_Addr
+#define Elf_Sword Elf64_Sxword
+#define Elf_Section Elf64_Half
+#define ELF_ST_BIND ELF64_ST_BIND
+#define ELF_ST_TYPE ELF64_ST_TYPE
+
+#define Elf_Rel Elf64_Rel
+#define Elf_Rela Elf64_Rela
+#define ELF_R_SYM ELF64_R_SYM
+#define ELF_R_TYPE ELF64_R_TYPE
+#endif
+
+/* The 64-bit MIPS ELF ABI uses an unusual reloc format. */
+typedef struct
+{
+ Elf32_Word r_sym; /* Symbol index */
+ unsigned char r_ssym; /* Special symbol for 2nd relocation */
+ unsigned char r_type3; /* 3rd relocation type */
+ unsigned char r_type2; /* 2nd relocation type */
+ unsigned char r_type1; /* 1st relocation type */
+} _Elf64_Mips_R_Info;
+
+typedef union
+{
+ Elf64_Xword r_info_number;
+ _Elf64_Mips_R_Info r_info_fields;
+} _Elf64_Mips_R_Info_union;
+
+#define ELF64_MIPS_R_SYM(i) \
+ ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym)
+
+#define ELF64_MIPS_R_TYPE(i) \
+ ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1)
+
+#if KERNEL_ELFDATA != HOST_ELFDATA
+
+static inline void __endian(const void *src, void *dest, unsigned int size)
+{
+ unsigned int i;
+ for (i = 0; i < size; i++)
+ ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1];
+}
+
+#define TO_NATIVE(x) \
+({ \
+ typeof(x) __x; \
+ __endian(&(x), &(__x), sizeof(__x)); \
+ __x; \
+})
+
+#else /* endianness matches */
+
+#define TO_NATIVE(x) (x)
+
+#endif
+
+#define NOFAIL(ptr) do_nofail((ptr), #ptr)
+void *do_nofail(void *ptr, const char *expr);
+
+struct buffer {
+ char *p;
+ int pos;
+ int size;
+};
+
+void __attribute__((format(printf, 2, 3)))
+buf_printf(struct buffer *buf, const char *fmt, ...);
+
+void
+buf_write(struct buffer *buf, const char *s, int len);
+
+struct module {
+ struct module *next;
+ const char *name;
+ int gpl_compatible;
+ struct symbol *unres;
+ int seen;
+ int skip;
+ int has_init;
+ int has_cleanup;
+ struct buffer dev_table_buf;
+ char srcversion[25];
+ int is_dot_o;
+};
+
+struct elf_info {
+ unsigned long size;
+ Elf_Ehdr *hdr;
+ Elf_Shdr *sechdrs;
+ Elf_Sym *symtab_start;
+ Elf_Sym *symtab_stop;
+ Elf_Section export_sec;
+ Elf_Section export_unused_sec;
+ Elf_Section export_gpl_sec;
+ Elf_Section export_unused_gpl_sec;
+ Elf_Section export_gpl_future_sec;
+ const char *strtab;
+ char *modinfo;
+ unsigned int modinfo_len;
+
+ /* support for 32bit section numbers */
+
+ unsigned int num_sections; /* max_secindex + 1 */
+ unsigned int secindex_strings;
+ /* if Nth symbol table entry has .st_shndx = SHN_XINDEX,
+ * take shndx from symtab_shndx_start[N] instead */
+ Elf32_Word *symtab_shndx_start;
+ Elf32_Word *symtab_shndx_stop;
+};
+
+static inline int is_shndx_special(unsigned int i)
+{
+ return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
+}
+
+/*
+ * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
+ * the way to -256..-1, to avoid conflicting with real section
+ * indices.
+ */
+#define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1))
+
+/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
+static inline unsigned int get_secindex(const struct elf_info *info,
+ const Elf_Sym *sym)
+{
+ if (is_shndx_special(sym->st_shndx))
+ return SPECIAL(sym->st_shndx);
+ if (sym->st_shndx != SHN_XINDEX)
+ return sym->st_shndx;
+ return info->symtab_shndx_start[sym - info->symtab_start];
+}
+
+/* file2alias.c */
+extern unsigned int cross_build;
+void handle_moddevtable(struct module *mod, struct elf_info *info,
+ Elf_Sym *sym, const char *symname);
+void add_moddevtable(struct buffer *buf, struct module *mod);
+
+/* sumversion.c */
+void maybe_frob_rcs_version(const char *modfilename,
+ char *version,
+ void *modinfo,
+ unsigned long modinfo_offset);
+void get_src_version(const char *modname, char sum[], unsigned sumlen);
+
+/* from modpost.c */
+void *grab_file(const char *filename, unsigned long *size);
+char* get_next_line(unsigned long *pos, void *file, unsigned long size);
+void release_file(void *file, unsigned long size);
+
+void fatal(const char *fmt, ...);
+void warn(const char *fmt, ...);
+void merror(const char *fmt, ...);
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
new file mode 100644
index 0000000..9dfcd6d
--- /dev/null
+++ b/scripts/mod/sumversion.c
@@ -0,0 +1,519 @@
+#include <netinet/in.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include "modpost.h"
+
+/*
+ * Stolen form Cryptographic API.
+ *
+ * MD4 Message Digest Algorithm (RFC1320).
+ *
+ * Implementation derived from Andrew Tridgell and Steve French's
+ * CIFS MD4 implementation, and the cryptoapi implementation
+ * originally based on the public domain implementation written
+ * by Colin Plumb in 1993.
+ *
+ * Copyright (c) Andrew Tridgell 1997-1998.
+ * Modified by Steve French (sfrench at us.ibm.com) 2002
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 David S. Miller (davem at redhat.com)
+ * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#define MD4_DIGEST_SIZE 16
+#define MD4_HMAC_BLOCK_SIZE 64
+#define MD4_BLOCK_WORDS 16
+#define MD4_HASH_WORDS 4
+
+struct md4_ctx {
+ uint32_t hash[MD4_HASH_WORDS];
+ uint32_t block[MD4_BLOCK_WORDS];
+ uint64_t byte_count;
+};
+
+static inline uint32_t lshift(uint32_t x, unsigned int s)
+{
+ x &= 0xFFFFFFFF;
+ return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
+}
+
+static inline uint32_t F(uint32_t x, uint32_t y, uint32_t z)
+{
+ return (x & y) | ((~x) & z);
+}
+
+static inline uint32_t G(uint32_t x, uint32_t y, uint32_t z)
+{
+ return (x & y) | (x & z) | (y & z);
+}
+
+static inline uint32_t H(uint32_t x, uint32_t y, uint32_t z)
+{
+ return x ^ y ^ z;
+}
+
+#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
+#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (uint32_t)0x5A827999,s))
+#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (uint32_t)0x6ED9EBA1,s))
+
+/* XXX: this stuff can be optimized */
+static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words)
+{
+ while (words--) {
+ *buf = ntohl(*buf);
+ buf++;
+ }
+}
+
+static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words)
+{
+ while (words--) {
+ *buf = htonl(*buf);
+ buf++;
+ }
+}
+
+static void md4_transform(uint32_t *hash, uint32_t const *in)
+{
+ uint32_t a, b, c, d;
+
+ a = hash[0];
+ b = hash[1];
+ c = hash[2];
+ d = hash[3];
+
+ ROUND1(a, b, c, d, in[0], 3);
+ ROUND1(d, a, b, c, in[1], 7);
+ ROUND1(c, d, a, b, in[2], 11);
+ ROUND1(b, c, d, a, in[3], 19);
+ ROUND1(a, b, c, d, in[4], 3);
+ ROUND1(d, a, b, c, in[5], 7);
+ ROUND1(c, d, a, b, in[6], 11);
+ ROUND1(b, c, d, a, in[7], 19);
+ ROUND1(a, b, c, d, in[8], 3);
+ ROUND1(d, a, b, c, in[9], 7);
+ ROUND1(c, d, a, b, in[10], 11);
+ ROUND1(b, c, d, a, in[11], 19);
+ ROUND1(a, b, c, d, in[12], 3);
+ ROUND1(d, a, b, c, in[13], 7);
+ ROUND1(c, d, a, b, in[14], 11);
+ ROUND1(b, c, d, a, in[15], 19);
+
+ ROUND2(a, b, c, d,in[ 0], 3);
+ ROUND2(d, a, b, c, in[4], 5);
+ ROUND2(c, d, a, b, in[8], 9);
+ ROUND2(b, c, d, a, in[12], 13);
+ ROUND2(a, b, c, d, in[1], 3);
+ ROUND2(d, a, b, c, in[5], 5);
+ ROUND2(c, d, a, b, in[9], 9);
+ ROUND2(b, c, d, a, in[13], 13);
+ ROUND2(a, b, c, d, in[2], 3);
+ ROUND2(d, a, b, c, in[6], 5);
+ ROUND2(c, d, a, b, in[10], 9);
+ ROUND2(b, c, d, a, in[14], 13);
+ ROUND2(a, b, c, d, in[3], 3);
+ ROUND2(d, a, b, c, in[7], 5);
+ ROUND2(c, d, a, b, in[11], 9);
+ ROUND2(b, c, d, a, in[15], 13);
+
+ ROUND3(a, b, c, d,in[ 0], 3);
+ ROUND3(d, a, b, c, in[8], 9);
+ ROUND3(c, d, a, b, in[4], 11);
+ ROUND3(b, c, d, a, in[12], 15);
+ ROUND3(a, b, c, d, in[2], 3);
+ ROUND3(d, a, b, c, in[10], 9);
+ ROUND3(c, d, a, b, in[6], 11);
+ ROUND3(b, c, d, a, in[14], 15);
+ ROUND3(a, b, c, d, in[1], 3);
+ ROUND3(d, a, b, c, in[9], 9);
+ ROUND3(c, d, a, b, in[5], 11);
+ ROUND3(b, c, d, a, in[13], 15);
+ ROUND3(a, b, c, d, in[3], 3);
+ ROUND3(d, a, b, c, in[11], 9);
+ ROUND3(c, d, a, b, in[7], 11);
+ ROUND3(b, c, d, a, in[15], 15);
+
+ hash[0] += a;
+ hash[1] += b;
+ hash[2] += c;
+ hash[3] += d;
+}
+
+static inline void md4_transform_helper(struct md4_ctx *ctx)
+{
+ le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(uint32_t));
+ md4_transform(ctx->hash, ctx->block);
+}
+
+static void md4_init(struct md4_ctx *mctx)
+{
+ mctx->hash[0] = 0x67452301;
+ mctx->hash[1] = 0xefcdab89;
+ mctx->hash[2] = 0x98badcfe;
+ mctx->hash[3] = 0x10325476;
+ mctx->byte_count = 0;
+}
+
+static void md4_update(struct md4_ctx *mctx,
+ const unsigned char *data, unsigned int len)
+{
+ const uint32_t avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
+
+ mctx->byte_count += len;
+
+ if (avail > len) {
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, len);
+ return;
+ }
+
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, avail);
+
+ md4_transform_helper(mctx);
+ data += avail;
+ len -= avail;
+
+ while (len >= sizeof(mctx->block)) {
+ memcpy(mctx->block, data, sizeof(mctx->block));
+ md4_transform_helper(mctx);
+ data += sizeof(mctx->block);
+ len -= sizeof(mctx->block);
+ }
+
+ memcpy(mctx->block, data, len);
+}
+
+static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len)
+{
+ const unsigned int offset = mctx->byte_count & 0x3f;
+ char *p = (char *)mctx->block + offset;
+ int padding = 56 - (offset + 1);
+
+ *p++ = 0x80;
+ if (padding < 0) {
+ memset(p, 0x00, padding + sizeof (uint64_t));
+ md4_transform_helper(mctx);
+ p = (char *)mctx->block;
+ padding = 56;
+ }
+
+ memset(p, 0, padding);
+ mctx->block[14] = mctx->byte_count << 3;
+ mctx->block[15] = mctx->byte_count >> 29;
+ le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
+ sizeof(uint64_t)) / sizeof(uint32_t));
+ md4_transform(mctx->hash, mctx->block);
+ cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t));
+
+ snprintf(out, len, "%08X%08X%08X%08X",
+ mctx->hash[0], mctx->hash[1], mctx->hash[2], mctx->hash[3]);
+}
+
+static inline void add_char(unsigned char c, struct md4_ctx *md)
+{
+ md4_update(md, &c, 1);
+}
+
+static int parse_string(const char *file, unsigned long len,
+ struct md4_ctx *md)
+{
+ unsigned long i;
+
+ add_char(file[0], md);
+ for (i = 1; i < len; i++) {
+ add_char(file[i], md);
+ if (file[i] == '"' && file[i-1] != '\\')
+ break;
+ }
+ return i;
+}
+
+static int parse_comment(const char *file, unsigned long len)
+{
+ unsigned long i;
+
+ for (i = 2; i < len; i++) {
+ if (file[i-1] == '*' && file[i] == '/')
+ break;
+ }
+ return i;
+}
+
+/* FIXME: Handle .s files differently (eg. # starts comments) --RR */
+static int parse_file(const char *fname, struct md4_ctx *md)
+{
+ char *file;
+ unsigned long i, len;
+
+ file = grab_file(fname, &len);
+ if (!file)
+ return 0;
+
+ for (i = 0; i < len; i++) {
+ /* Collapse and ignore \ and CR. */
+ if (file[i] == '\\' && (i+1 < len) && file[i+1] == '\n') {
+ i++;
+ continue;
+ }
+
+ /* Ignore whitespace */
+ if (isspace(file[i]))
+ continue;
+
+ /* Handle strings as whole units */
+ if (file[i] == '"') {
+ i += parse_string(file+i, len - i, md);
+ continue;
+ }
+
+ /* Comments: ignore */
+ if (file[i] == '/' && file[i+1] == '*') {
+ i += parse_comment(file+i, len - i);
+ continue;
+ }
+
+ add_char(file[i], md);
+ }
+ release_file(file, len);
+ return 1;
+}
+/* Check whether the file is a static library or not */
+static int is_static_library(const char *objfile)
+{
+ int len = strlen(objfile);
+ if (objfile[len - 2] == '.' && objfile[len - 1] == 'a')
+ return 1;
+ else
+ return 0;
+}
+
+/* We have dir/file.o. Open dir/.file.o.cmd, look for source_ and deps_ line
+ * to figure out source files. */
+static int parse_source_files(const char *objfile, struct md4_ctx *md)
+{
+ char *cmd, *file, *line, *dir;
+ const char *base;
+ unsigned long flen, pos = 0;
+ int dirlen, ret = 0, check_files = 0;
+
+ cmd = NOFAIL(malloc(strlen(objfile) + sizeof("..cmd")));
+
+ base = strrchr(objfile, '/');
+ if (base) {
+ base++;
+ dirlen = base - objfile;
+ sprintf(cmd, "%.*s.%s.cmd", dirlen, objfile, base);
+ } else {
+ dirlen = 0;
+ sprintf(cmd, ".%s.cmd", objfile);
+ }
+ dir = NOFAIL(malloc(dirlen + 1));
+ strncpy(dir, objfile, dirlen);
+ dir[dirlen] = '\0';
+
+ file = grab_file(cmd, &flen);
+ if (!file) {
+ warn("could not find %s for %s\n", cmd, objfile);
+ goto out;
+ }
+
+ /* There will be a line like so:
+ deps_drivers/net/dummy.o := \
+ drivers/net/dummy.c \
+ $(wildcard include/config/net/fastroute.h) \
+ include/linux/module.h \
+
+ Sum all files in the same dir or subdirs.
+ */
+ while ((line = get_next_line(&pos, file, flen)) != NULL) {
+ char* p = line;
+
+ if (strncmp(line, "source_", sizeof("source_")-1) == 0) {
+ p = strrchr(line, ' ');
+ if (!p) {
+ warn("malformed line: %s\n", line);
+ goto out_file;
+ }
+ p++;
+ if (!parse_file(p, md)) {
+ warn("could not open %s: %s\n",
+ p, strerror(errno));
+ goto out_file;
+ }
+ continue;
+ }
+ if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) {
+ check_files = 1;
+ continue;
+ }
+ if (!check_files)
+ continue;
+
+ /* Continue until line does not end with '\' */
+ if ( *(p + strlen(p)-1) != '\\')
+ break;
+ /* Terminate line at first space, to get rid of final ' \' */
+ while (*p) {
+ if (isspace(*p)) {
+ *p = '\0';
+ break;
+ }
+ p++;
+ }
+
+ /* Check if this file is in same dir as objfile */
+ if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) {
+ if (!parse_file(line, md)) {
+ warn("could not open %s: %s\n",
+ line, strerror(errno));
+ goto out_file;
+ }
+
+ }
+
+ }
+
+ /* Everyone parsed OK */
+ ret = 1;
+out_file:
+ release_file(file, flen);
+out:
+ free(dir);
+ free(cmd);
+ return ret;
+}
+
+/* Calc and record src checksum. */
+void get_src_version(const char *modname, char sum[], unsigned sumlen)
+{
+ void *file;
+ unsigned long len;
+ struct md4_ctx md;
+ char *sources, *end, *fname;
+ const char *basename;
+ char filelist[PATH_MAX + 1];
+ char *modverdir = getenv("MODVERDIR");
+
+ if (!modverdir)
+ modverdir = ".";
+
+ /* Source files for module are in .tmp_versions/modname.mod,
+ after the first line. */
+ if (strrchr(modname, '/'))
+ basename = strrchr(modname, '/') + 1;
+ else
+ basename = modname;
+ sprintf(filelist, "%s/%.*s.mod", modverdir,
+ (int) strlen(basename) - 2, basename);
+
+ file = grab_file(filelist, &len);
+ if (!file)
+ /* not a module or .mod file missing - ignore */
+ return;
+
+ sources = strchr(file, '\n');
+ if (!sources) {
+ warn("malformed versions file for %s\n", modname);
+ goto release;
+ }
+
+ sources++;
+ end = strchr(sources, '\n');
+ if (!end) {
+ warn("bad ending versions file for %s\n", modname);
+ goto release;
+ }
+ *end = '\0';
+
+ md4_init(&md);
+ while ((fname = strsep(&sources, " ")) != NULL) {
+ if (!*fname)
+ continue;
+ if (!(is_static_library(fname)) &&
+ !parse_source_files(fname, &md))
+ goto release;
+ }
+
+ md4_final_ascii(&md, sum, sumlen);
+release:
+ release_file(file, len);
+}
+
+static void write_version(const char *filename, const char *sum,
+ unsigned long offset)
+{
+ int fd;
+
+ fd = open(filename, O_RDWR);
+ if (fd < 0) {
+ warn("changing sum in %s failed: %s\n",
+ filename, strerror(errno));
+ return;
+ }
+
+ if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
+ warn("changing sum in %s:%lu failed: %s\n",
+ filename, offset, strerror(errno));
+ goto out;
+ }
+
+ if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
+ warn("writing sum in %s failed: %s\n",
+ filename, strerror(errno));
+ goto out;
+ }
+out:
+ close(fd);
+}
+
+static int strip_rcs_crap(char *version)
+{
+ unsigned int len, full_len;
+
+ if (strncmp(version, "$Revision", strlen("$Revision")) != 0)
+ return 0;
+
+ /* Space for version string follows. */
+ full_len = strlen(version) + strlen(version + strlen(version) + 1) + 2;
+
+ /* Move string to start with version number: prefix will be
+ * $Revision$ or $Revision: */
+ len = strlen("$Revision");
+ if (version[len] == ':' || version[len] == '$')
+ len++;
+ while (isspace(version[len]))
+ len++;
+ memmove(version, version+len, full_len-len);
+ full_len -= len;
+
+ /* Preserve up to next whitespace. */
+ len = 0;
+ while (version[len] && !isspace(version[len]))
+ len++;
+ memmove(version + len, version + strlen(version),
+ full_len - strlen(version));
+ return 1;
+}
+
+/* Clean up RCS-style version numbers. */
+void maybe_frob_rcs_version(const char *modfilename,
+ char *version,
+ void *modinfo,
+ unsigned long version_offset)
+{
+ if (strip_rcs_crap(version))
+ write_version(modfilename, version, version_offset);
+}
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
new file mode 100755
index 0000000..bd6dca8
--- /dev/null
+++ b/scripts/setlocalversion
@@ -0,0 +1,176 @@
+#!/bin/sh
+#
+# This scripts adds local version information from the version
+# control systems git, mercurial (hg) and subversion (svn).
+#
+# If something goes wrong, send a mail the kernel build mailinglist
+# (see MAINTAINERS) and CC Nico Schottelius
+# <nico-linuxsetlocalversion -at- schottelius.org>.
+#
+#
+
+usage() {
+ echo "Usage: $0 [--save-scmversion] [srctree]" >&2
+ exit 1
+}
+
+scm_only=false
+srctree=.
+if test "$1" = "--save-scmversion"; then
+ scm_only=true
+ shift
+fi
+if test $# -gt 0; then
+ srctree=$1
+ shift
+fi
+if test $# -gt 0 -o ! -d "$srctree"; then
+ usage
+fi
+
+scm_version()
+{
+ local short
+ short=false
+
+ cd "$srctree"
+ if test -e .scmversion; then
+ cat .scmversion
+ return
+ fi
+ if test "$1" = "--short"; then
+ short=true
+ fi
+
+ # Check for git and a git repo.
+ if test -d .git && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
+
+ # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
+ # it, because this version is defined in the top level Makefile.
+ if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+
+ # If only the short version is requested, don't bother
+ # running further git commands
+ if $short; then
+ echo "+"
+ return
+ fi
+ # If we are past a tagged commit (like
+ # "v2.6.30-rc5-302-g72357d5"), we pretty print it.
+ if atag="`git describe 2>/dev/null`"; then
+ echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+
+ # If we don't have a tag at all we print -g{commitish}.
+ else
+ printf '%s%s' -g $head
+ fi
+ fi
+
+ # Is this git on svn?
+ if git config --get svn-remote.svn.url >/dev/null; then
+ printf -- '-svn%s' "`git svn find-rev $head`"
+ fi
+
+ # Update index only on r/w media
+ [ -w . ] && git update-index --refresh --unmerged > /dev/null
+
+ # Check for uncommitted changes
+ if git diff-index --name-only HEAD | grep -qv "^scripts/package"; then
+ printf '%s' -dirty
+ fi
+
+ # All done with git
+ return
+ fi
+
+ # Check for mercurial and a mercurial repo.
+ if test -d .hg && hgid=`hg id 2>/dev/null`; then
+ # Do we have an tagged version? If so, latesttagdistance == 1
+ if [ "`hg log -r . --template '{latesttagdistance}'`" == "1" ]; then
+ id=`hg log -r . --template '{latesttag}'`
+ printf '%s%s' -hg "$id"
+ else
+ tag=`printf '%s' "$hgid" | cut -d' ' -f2`
+ if [ -z "$tag" -o "$tag" = tip ]; then
+ id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
+ printf '%s%s' -hg "$id"
+ fi
+ fi
+
+ # Are there uncommitted changes?
+ # These are represented by + after the changeset id.
+ case "$hgid" in
+ *+|*+\ *) printf '%s' -dirty ;;
+ esac
+
+ # All done with mercurial
+ return
+ fi
+
+ # Check for svn and a svn repo.
+ if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
+ rev=`echo $rev | awk '{print $NF}'`
+ printf -- '-svn%s' "$rev"
+
+ # All done with svn
+ return
+ fi
+}
+
+collect_files()
+{
+ local file res
+
+ for file; do
+ case "$file" in
+ *\~*)
+ continue
+ ;;
+ esac
+ if test -e "$file"; then
+ res="$res$(cat "$file")"
+ fi
+ done
+ echo "$res"
+}
+
+if $scm_only; then
+ if test ! -e .scmversion; then
+ res=$(scm_version)
+ echo "$res" >.scmversion
+ fi
+ exit
+fi
+
+if test -e include/config/auto.conf; then
+ . include/config/auto.conf
+else
+ echo "Error: kernelrelease not valid - run 'make prepare' to update it"
+ exit 1
+fi
+
+# localversion* files in the build and source directory
+res="$(collect_files localversion*)"
+if test ! "$srctree" -ef .; then
+ res="$res$(collect_files "$srctree"/localversion*)"
+fi
+
+# CONFIG_LOCALVERSION and LOCALVERSION (if set)
+res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"
+
+# scm version string if not at a tagged commit
+if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then
+ # full scm version string
+ res="$res$(scm_version)"
+else
+ # append a plus sign if the repository is not in a clean
+ # annotated or signed tagged state (as git describe only
+ # looks at signed or annotated tags - git tag -a/-s) and
+ # LOCALVERSION= is not specified
+ if test "${LOCALVERSION+set}" != "set"; then
+ scm=$(scm_version --short)
+ res="$res${scm:++}"
+ fi
+fi
+
+echo "$res"
--
1.8.2.1
More information about the U-Boot
mailing list