summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Kconfig8
-rw-r--r--Makefile17
-rw-r--r--common/Kconfig12
-rw-r--r--scripts/kconfig/.gitignore6
-rw-r--r--scripts/kconfig/Makefile346
-rw-r--r--scripts/kconfig/POTFILES.in12
-rwxr-xr-xscripts/kconfig/check.sh13
-rw-r--r--scripts/kconfig/conf.c215
-rw-r--r--scripts/kconfig/confdata.c228
-rw-r--r--scripts/kconfig/expr.c479
-rw-r--r--scripts/kconfig/expr.h110
-rwxr-xr-xscripts/kconfig/gconf-cfg.sh30
-rw-r--r--scripts/kconfig/gconf.c82
-rw-r--r--scripts/kconfig/kconf_id.c52
-rw-r--r--scripts/kconfig/kxgettext.c235
-rw-r--r--scripts/kconfig/list.h7
-rw-r--r--scripts/kconfig/lkc.h41
-rw-r--r--scripts/kconfig/lkc_proto.h105
-rwxr-xr-xscripts/kconfig/lxdialog/check-lxdialog.sh91
-rw-r--r--scripts/kconfig/lxdialog/checklist.c4
-rw-r--r--scripts/kconfig/lxdialog/dialog.h8
-rw-r--r--scripts/kconfig/lxdialog/inputbox.c4
-rw-r--r--scripts/kconfig/lxdialog/menubox.c10
-rw-r--r--scripts/kconfig/lxdialog/textbox.c2
-rw-r--r--scripts/kconfig/lxdialog/yesno.c4
-rwxr-xr-xscripts/kconfig/mconf-cfg.sh47
-rw-r--r--scripts/kconfig/mconf.c177
-rw-r--r--scripts/kconfig/menu.c269
-rwxr-xr-xscripts/kconfig/merge_config.sh63
-rw-r--r--scripts/kconfig/nconf-cfg.sh47
-rw-r--r--scripts/kconfig/nconf.c175
-rw-r--r--scripts/kconfig/nconf.gui.c22
-rw-r--r--scripts/kconfig/nconf.h5
-rw-r--r--scripts/kconfig/preprocess.c572
-rwxr-xr-xscripts/kconfig/qconf-cfg.sh32
-rw-r--r--scripts/kconfig/qconf.cc765
-rw-r--r--scripts/kconfig/qconf.h150
-rwxr-xr-xscripts/kconfig/streamline_config.pl53
-rw-r--r--scripts/kconfig/symbol.c335
-rw-r--r--scripts/kconfig/tests/auto_submenu/Kconfig50
-rw-r--r--scripts/kconfig/tests/auto_submenu/__init__.py12
-rw-r--r--scripts/kconfig/tests/auto_submenu/expected_stdout10
-rw-r--r--scripts/kconfig/tests/choice/Kconfig54
-rw-r--r--scripts/kconfig/tests/choice/__init__.py40
-rw-r--r--scripts/kconfig/tests/choice/alldef_expected_config5
-rw-r--r--scripts/kconfig/tests/choice/allmod_expected_config9
-rw-r--r--scripts/kconfig/tests/choice/allno_expected_config5
-rw-r--r--scripts/kconfig/tests/choice/allyes_expected_config9
-rw-r--r--scripts/kconfig/tests/choice/oldask0_expected_stdout10
-rw-r--r--scripts/kconfig/tests/choice/oldask1_config2
-rw-r--r--scripts/kconfig/tests/choice/oldask1_expected_stdout15
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/Kconfig19
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/__init__.py15
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/config2
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/expected_config3
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout4
-rw-r--r--scripts/kconfig/tests/conftest.py291
-rw-r--r--scripts/kconfig/tests/err_recursive_dep/Kconfig63
-rw-r--r--scripts/kconfig/tests/err_recursive_dep/__init__.py10
-rw-r--r--scripts/kconfig/tests/err_recursive_dep/expected_stderr38
-rw-r--r--scripts/kconfig/tests/err_recursive_inc/Kconfig1
-rw-r--r--scripts/kconfig/tests/err_recursive_inc/Kconfig.inc14
-rw-r--r--scripts/kconfig/tests/err_recursive_inc/Kconfig.inc23
-rw-r--r--scripts/kconfig/tests/err_recursive_inc/Kconfig.inc31
-rw-r--r--scripts/kconfig/tests/err_recursive_inc/__init__.py10
-rw-r--r--scripts/kconfig/tests/err_recursive_inc/expected_stderr6
-rw-r--r--scripts/kconfig/tests/inter_choice/Kconfig23
-rw-r--r--scripts/kconfig/tests/inter_choice/__init__.py14
-rw-r--r--scripts/kconfig/tests/inter_choice/defconfig1
-rw-r--r--scripts/kconfig/tests/inter_choice/expected_config4
-rw-r--r--scripts/kconfig/tests/new_choice_with_dep/Kconfig37
-rw-r--r--scripts/kconfig/tests/new_choice_with_dep/__init__.py14
-rw-r--r--scripts/kconfig/tests/new_choice_with_dep/config3
-rw-r--r--scripts/kconfig/tests/new_choice_with_dep/expected_stdout10
-rw-r--r--scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig14
-rw-r--r--scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py19
-rw-r--r--scripts/kconfig/tests/no_write_if_dep_unmet/config1
-rw-r--r--scripts/kconfig/tests/no_write_if_dep_unmet/expected_config5
-rw-r--r--scripts/kconfig/tests/preprocess/builtin_func/Kconfig27
-rw-r--r--scripts/kconfig/tests/preprocess/builtin_func/__init__.py9
-rw-r--r--scripts/kconfig/tests/preprocess/builtin_func/expected_stderr5
-rw-r--r--scripts/kconfig/tests/preprocess/builtin_func/expected_stdout1
-rw-r--r--scripts/kconfig/tests/preprocess/circular_expansion/Kconfig5
-rw-r--r--scripts/kconfig/tests/preprocess/circular_expansion/__init__.py11
-rw-r--r--scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr1
-rw-r--r--scripts/kconfig/tests/preprocess/escape/Kconfig44
-rw-r--r--scripts/kconfig/tests/preprocess/escape/__init__.py8
-rw-r--r--scripts/kconfig/tests/preprocess/escape/expected_stderr10
-rw-r--r--scripts/kconfig/tests/preprocess/variable/Kconfig53
-rw-r--r--scripts/kconfig/tests/preprocess/variable/__init__.py8
-rw-r--r--scripts/kconfig/tests/preprocess/variable/expected_stderr9
-rw-r--r--scripts/kconfig/tests/pytest.ini7
-rw-r--r--scripts/kconfig/tests/rand_nested_choice/Kconfig33
-rw-r--r--scripts/kconfig/tests/rand_nested_choice/__init__.py16
-rw-r--r--scripts/kconfig/tests/rand_nested_choice/expected_stdout02
-rw-r--r--scripts/kconfig/tests/rand_nested_choice/expected_stdout14
-rw-r--r--scripts/kconfig/tests/rand_nested_choice/expected_stdout25
-rw-r--r--scripts/kconfig/util.c93
-rw-r--r--scripts/kconfig/zconf.gperf48
-rw-r--r--scripts/kconfig/zconf.hash.c (renamed from scripts/kconfig/zconf.hash.c_shipped)0
-rw-r--r--scripts/kconfig/zconf.l194
-rw-r--r--scripts/kconfig/zconf.y163
102 files changed, 4213 insertions, 2212 deletions
diff --git a/Kconfig b/Kconfig
index 5c99e666c0..2f2f1a6e3c 100644
--- a/Kconfig
+++ b/Kconfig
@@ -2,13 +2,9 @@
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/kconfig-language.txt.
#
-mainmenu "Barebox/$ARCH $KERNELVERSION Configuration"
+mainmenu "Barebox/$(ARCH) $(KERNELVERSION) Configuration"
-config SRCARCH
- string
- option env="SRCARCH"
-
-source "arch/$SRCARCH/Kconfig"
+source "arch/$(SRCARCH)/Kconfig"
source common/Kconfig
source commands/Kconfig
diff --git a/Makefile b/Makefile
index b014341db8..105c0d7f92 100644
--- a/Makefile
+++ b/Makefile
@@ -284,6 +284,7 @@ GENKSYMS = scripts/genksyms/genksyms
DEPMOD = /sbin/depmod
KALLSYMS = scripts/kallsyms
PERL = perl
+PYTHON3 = python3
CHECK = sparse
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
@@ -323,7 +324,7 @@ KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(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 MAKE AWK GENKSYMS PERL UTS_MACHINE
+export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL PYTHON3 UTS_MACHINE
export LEX YACC
export HOSTCXX HOSTCXXFLAGS HOSTLDFLAGS HOST_LOADLIBES LDFLAGS_MODULE CHECK CHECKFLAGS
@@ -409,11 +410,9 @@ include $(srctree)/arch/$(ARCH)/Makefile
export KBUILD_DEFCONFIG
config: scripts_basic outputmakefile FORCE
- $(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@
%config: scripts_basic outputmakefile FORCE
- $(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@
else
@@ -442,13 +441,11 @@ ifeq ($(dot-config),1)
# 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/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
- $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
-
+# The actual configuration files used during the build are stored in
+# include/generated/ and include/config/. Update them if .config is newer than
+# include/config/auto.conf (which mirrors .config).
+include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
+ $(Q)$(MAKE) -f $(srctree)/Makefile syncconfig
else
# Dummy target needed, because used as prerequisite
include/config/auto.conf: ;
diff --git a/common/Kconfig b/common/Kconfig
index 2ad92158c1..3ec3d46d40 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1,16 +1,8 @@
-config ARCH
- string
- option env="ARCH"
-
-config KERNELVERSION
- string
- option env="KERNELVERSION"
-
config DEFCONFIG_LIST
string
option defconfig_list
- default "$ARCH_DEFCONFIG"
- default "arch/$ARCH/defconfig"
+ default ARCH_DEFCONFIG
+ default "arch/$(ARCH)/defconfig"
config GREGORIAN_CALENDER
bool
diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
index bdbabbe08c..0aabc1d6a1 100644
--- a/scripts/kconfig/.gitignore
+++ b/scripts/kconfig/.gitignore
@@ -1,12 +1,7 @@
#
# Generated files
#
-config*
-zconf.hash.c
*.moc
-gconf.glade.h
-*.pot
-*.mo
#
# configuration programs
@@ -16,4 +11,3 @@ mconf
nconf
qconf
gconf
-kxgettext
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index f9203d7f34..63b609243d 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -1,9 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
# ===========================================================================
# Kernel configuration targets
# These targets are used from top-level makefile
-PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \
- localmodconfig localyesconfig
+PHONY += xconfig gconfig menuconfig config localmodconfig localyesconfig \
+ build_menuconfig build_nconfig build_gconfig build_xconfig
ifdef KBUILD_KCONFIG
Kconfig := $(KBUILD_KCONFIG)
@@ -11,127 +12,120 @@ else
Kconfig := Kconfig
endif
+ifeq ($(quiet),silent_)
+silent := -s
+endif
+
# We need this, in case the user has it in its environment
unexport CONFIG_
xconfig: $(obj)/qconf
- $< $(Kconfig)
+ $< $(silent) $(Kconfig)
gconfig: $(obj)/gconf
- $< $(Kconfig)
+ $< $(silent) $(Kconfig)
menuconfig: $(obj)/mconf
- $< $(Kconfig)
+ $< $(silent) $(Kconfig)
config: $(obj)/conf
- $< --oldaskconfig $(Kconfig)
+ $< $(silent) --oldaskconfig $(Kconfig)
nconfig: $(obj)/nconf
- $< $(Kconfig)
+ $< $(silent) $(Kconfig)
+
+build_menuconfig: $(obj)/mconf
-oldconfig: $(obj)/conf
- $< --$@ $(Kconfig)
+build_nconfig: $(obj)/nconf
-silentoldconfig: $(obj)/conf
- $(Q)mkdir -p include/config include/generated
- $< --$@ $(Kconfig)
+build_gconfig: $(obj)/gconf
-localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
- $(Q)mkdir -p include/config include/generated
- $(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
+build_xconfig: $(obj)/qconf
+
+localyesconfig localmodconfig: $(obj)/conf
+ $(Q)perl $(srctree)/$(src)/streamline_config.pl --$@ $(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); \
+ $< $(silent) --oldconfig $(Kconfig); \
mv -f .config.old.1 .config.old) \
else \
mv -f .tmp.config .config; \
- $(obj)/conf --silentoldconfig $(Kconfig); \
+ $< $(silent) --oldconfig $(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)
+# These targets map 1:1 to the commandline options of 'conf'
+#
+# Note:
+# syncconfig has become an internal implementation detail and is now
+# deprecated for external use
+simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \
+ alldefconfig randconfig listnewconfig olddefconfig syncconfig
+PHONY += $(simple-targets)
+
+$(simple-targets): $(obj)/conf
+ $< $(silent) --$@ $(Kconfig)
+
+PHONY += savedefconfig defconfig
savedefconfig: $(obj)/conf
- $< --$@=defconfig $(Kconfig)
+ $< $(silent) --$@=defconfig $(Kconfig)
defconfig: $(obj)/conf
ifeq ($(KBUILD_DEFCONFIG),)
- $< --defconfig $(Kconfig)
+ $< $(silent) --defconfig $(Kconfig)
+else
+ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),)
+ @$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
+ $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
else
- @echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
- $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
+ @$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'"
+ $(Q)$(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG)
+endif
endif
%_defconfig: $(obj)/conf
- $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
+ $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
-configfiles=$(wildcard $(srctree)/kernel/configs/$(1).config $(srctree)/arch/$(SRCARCH)/configs/$(1).config)
+configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/configs/$@)
-define mergeconfig
-$(if $(wildcard $(objtree)/.config),, $(error You need an existing .config for this target))
-$(if $(call configfiles,$(1)),, $(error No configuration exists for this target on this architecture))
-$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m -O $(objtree) $(objtree)/.config $(call configfiles,$(1))
-$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
-endef
+%.config: $(obj)/conf
+ $(if $(call configfiles),, $(error No configuration exists for this target on this architecture))
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles)
+ +$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
PHONY += kvmconfig
-kvmconfig:
- $(call mergeconfig,kvm_guest)
+kvmconfig: kvm_guest.config
+ @:
+
+PHONY += xenconfig
+xenconfig: xen.config
+ @:
PHONY += tinyconfig
-tinyconfig: allnoconfig
- $(call mergeconfig,tiny)
+tinyconfig:
+ $(Q)$(MAKE) -f $(srctree)/Makefile allnoconfig tiny.config
+
+# CHECK: -o cache_dir=<path> working?
+PHONY += testconfig
+testconfig: $(obj)/conf
+ $(PYTHON3) -B -m pytest $(srctree)/$(src)/tests \
+ -o cache_dir=$(abspath $(obj)/tests/.cache) \
+ $(if $(findstring 1,$(KBUILD_VERBOSE)),--capture=no)
+clean-dirs += tests/.cache
# 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 ' 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'
@@ -140,173 +134,83 @@ help:
@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'
- @echo ' kvmconfig - Enable additional options for guest kernel support'
+ @echo ' olddefconfig - Same as oldconfig but sets new symbols to their'
+ @echo ' default value without prompting'
+ @echo ' kvmconfig - Enable additional options for kvm guest kernel support'
+ @echo ' xenconfig - Enable additional options for xen dom0 and guest kernel support'
@echo ' tinyconfig - Configure the tiniest possible kernel'
-
-# 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
+ @echo ' testconfig - Run Kconfig unit tests (requires python3 and pytest)'
# ===========================================================================
# 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 nconf mconf kxgettext qconf gconf
-
-clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck
-clean-files += zconf.hash.c gconf.glade.h
-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) $(HOSTLDLIBS_mconf)
+hostprogs-y := conf
-always := dochecklxdialog
-
-# Add environment specific flags
-HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS))
+targets += zconf.lex.c
# 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
-
-HOSTLDLIBS_qconf = $(KC_QT_LIBS)
-HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS)
-
-HOSTLDLIBS_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
-
-HOSTLDLIBS_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
-
-HOSTLDLIBS_nconf = $(shell \
- pkg-config --libs menuw panelw ncursesw 2>/dev/null \
- || pkg-config --libs menu panel ncurses 2>/dev/null \
- || echo "-lmenu -lpanel -lncurses" )
-$(obj)/qconf.o: $(obj)/.tmp_qtcheck
-
-ifeq ($(MAKECMDGOALS),xconfig)
-$(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
+# nconf: Used for the nconfig target based on ncurses
+hostprogs-y += nconf
+nconf-objs := nconf.o zconf.tab.o nconf.gui.o
-$(obj)/gconf.o: $(obj)/.tmp_gtkcheck
-
-ifeq ($(MAKECMDGOALS),gconfig)
--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
+HOSTLDLIBS_nconf = $(shell . $(obj)/.nconf-cfg && echo $$libs)
+HOSTCFLAGS_nconf.o = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
+HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
+
+$(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/.nconf-cfg
-$(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c
+# mconf: Used for the menuconfig target based on lxdialog
+hostprogs-y += mconf
+lxdialog := checklist.o inputbox.o menubox.o textbox.o util.o yesno.o
+mconf-objs := mconf.o zconf.tab.o $(addprefix lxdialog/, $(lxdialog))
+
+HOSTLDLIBS_mconf = $(shell . $(obj)/.mconf-cfg && echo $$libs)
+$(foreach f, mconf.o $(lxdialog), \
+ $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/.mconf-cfg && echo $$$$cflags)))
+
+$(obj)/mconf.o: $(obj)/.mconf-cfg
+$(addprefix $(obj)/lxdialog/, $(lxdialog)): $(obj)/.mconf-cfg
+
+# qconf: Used for the xconfig target based on Qt
+hostprogs-y += qconf
+qconf-cxxobjs := qconf.o
+qconf-objs := zconf.tab.o
-$(obj)/qconf.o: $(obj)/qconf.moc
+HOSTLDLIBS_qconf = $(shell . $(obj)/.qconf-cfg && echo $$libs)
+HOSTCXXFLAGS_qconf.o = $(shell . $(obj)/.qconf-cfg && echo $$cflags)
+
+$(obj)/qconf.o: $(obj)/.qconf-cfg $(obj)/qconf.moc
quiet_cmd_moc = MOC $@
- cmd_moc = $(KC_QT_MOC) -i $< -o $@
+ cmd_moc = $(shell . $(obj)/.qconf-cfg && echo $$moc) -i $< -o $@
-$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck
+$(obj)/%.moc: $(src)/%.h $(obj)/.qconf-cfg
$(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
+# gconf: Used for the gconfig target based on GTK+
+hostprogs-y += gconf
+gconf-objs := gconf.o zconf.tab.o
+
+HOSTLDLIBS_gconf = $(shell . $(obj)/.gconf-cfg && echo $$libs)
+HOSTCFLAGS_gconf.o = $(shell . $(obj)/.gconf-cfg && echo $$cflags)
+
+$(obj)/gconf.o: $(obj)/.gconf-cfg
+
+$(obj)/zconf.tab.o: $(obj)/zconf.lex.c
+
+# check if necessary packages are available, and configure build flags
+define filechk_conf_cfg
+ $(CONFIG_SHELL) $<
+endef
+
+$(obj)/.%conf-cfg: $(src)/%conf-cfg.sh FORCE
+ $(call filechk,conf_cfg)
+
+clean-files += .*conf-cfg
diff --git a/scripts/kconfig/POTFILES.in b/scripts/kconfig/POTFILES.in
deleted file mode 100644
index 9674573969..0000000000
--- a/scripts/kconfig/POTFILES.in
+++ /dev/null
@@ -1,12 +0,0 @@
-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
deleted file mode 100755
index 55b79ba1ba..0000000000
--- a/scripts/kconfig/check.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/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
index fef75fc756..98e0c7a346 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -3,8 +3,8 @@
* Released under the terms of the GNU GPL v2.0.
*/
-#include <locale.h>
#include <ctype.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -19,11 +19,10 @@
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,
+ syncconfig,
oldconfig,
allnoconfig,
allyesconfig,
@@ -34,14 +33,14 @@ enum input_mode {
savedefconfig,
listnewconfig,
olddefconfig,
-} input_mode = oldaskconfig;
+};
+static enum input_mode input_mode = oldaskconfig;
static int indent = 1;
static int tty_stdio;
-static int valid_stdin = 1;
static int sync_kconfig;
static int conf_cnt;
-static char line[128];
+static char line[PATH_MAX];
static struct menu *rootEntry;
static void print_help(struct menu *menu)
@@ -71,14 +70,14 @@ static void strip(char *str)
*p-- = 0;
}
-static void check_stdin(void)
+/* Helper function to facilitate fgets() by Jean Sacren. */
+static void xfgets(char *str, int size, FILE *in)
{
- if (!valid_stdin) {
- printf(_("aborted!\n\n"));
- printf(_("Console input/output is redirected. "));
- printf(_("Run 'make oldconfig' to update configuration.\n\n"));
- exit(1);
- }
+ if (!fgets(str, size, in))
+ fprintf(stderr, "\nError in reading or end of file.\n");
+
+ if (!tty_stdio)
+ printf("%s", str);
}
static int conf_askvalue(struct symbol *sym, const char *def)
@@ -86,7 +85,7 @@ 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) "));
+ printf("(NEW) ");
line[0] = '\n';
line[1] = 0;
@@ -100,18 +99,15 @@ static int conf_askvalue(struct symbol *sym, const char *def)
switch (input_mode) {
case oldconfig:
- case silentoldconfig:
+ case syncconfig:
if (sym_has_value(sym)) {
printf("%s\n", def);
return 0;
}
- check_stdin();
/* fall through */
case oldaskconfig:
fflush(stdout);
- xfgets(line, 128, stdin);
- if (!tty_stdio)
- printf("\n");
+ xfgets(line, sizeof(line), stdin);
return 1;
default:
break;
@@ -136,7 +132,7 @@ static int conf_string(struct menu *menu)
const char *def;
while (1) {
- printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
+ printf("%*s%s ", indent - 1, "", menu->prompt->text);
printf("(%s) ", sym->name);
def = sym_get_string_value(sym);
if (sym_get_string_value(sym))
@@ -169,7 +165,7 @@ static int conf_sym(struct menu *menu)
tristate oldval, newval;
while (1) {
- printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
+ printf("%*s%s ", indent - 1, "", menu->prompt->text);
if (sym->name)
printf("(%s) ", sym->name);
putchar('[');
@@ -191,9 +187,7 @@ static int conf_sym(struct menu *menu)
printf("/m");
if (oldval != yes && sym_tristate_within_range(sym, yes))
printf("/y");
- if (menu_has_help(menu))
- printf("/?");
- printf("] ");
+ printf("/?] ");
if (!conf_askvalue(sym, sym_get_string_value(sym)))
return 0;
strip(line);
@@ -256,7 +250,7 @@ static int conf_choice(struct menu *menu)
case no:
return 1;
case mod:
- printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
+ printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
return 0;
case yes:
break;
@@ -266,7 +260,7 @@ static int conf_choice(struct menu *menu)
while (1) {
int cnt, def;
- printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
+ printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
def_sym = sym_get_choice_value(sym);
cnt = def = 0;
line[0] = 0;
@@ -274,7 +268,7 @@ static int conf_choice(struct menu *menu)
if (!menu_is_visible(child))
continue;
if (!child->sym) {
- printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
+ printf("%*c %s\n", indent, '*', menu_get_prompt(child));
continue;
}
cnt++;
@@ -283,35 +277,31 @@ static int conf_choice(struct menu *menu)
printf("%*c", indent, '>');
} else
printf("%*c", indent, ' ');
- printf(" %d. %s", cnt, _(menu_get_prompt(child)));
+ 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(" (NEW)");
printf("\n");
}
- printf(_("%*schoice"), indent - 1, "");
+ 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("]: ");
+ printf("[1-%d?]: ", cnt);
switch (input_mode) {
case oldconfig:
- case silentoldconfig:
+ case syncconfig:
if (!is_new) {
cnt = def;
printf("%d\n", cnt);
break;
}
- check_stdin();
/* fall through */
case oldaskconfig:
fflush(stdout);
- xfgets(line, 128, stdin);
+ xfgets(line, sizeof(line), stdin);
strip(line);
if (line[0] == '?') {
print_help(menu);
@@ -367,10 +357,11 @@ static void conf(struct menu *menu)
switch (prop->type) {
case P_MENU:
- if ((input_mode == silentoldconfig ||
- input_mode == listnewconfig ||
- input_mode == olddefconfig) &&
- rootEntry != menu) {
+ /*
+ * Except in oldaskconfig mode, we show only menus that
+ * contain new symbols.
+ */
+ if (input_mode != oldaskconfig && rootEntry != menu) {
check_conf(menu);
return;
}
@@ -380,7 +371,7 @@ static void conf(struct menu *menu)
if (prompt)
printf("%*c\n%*c %s\n%*c\n",
indent, '*',
- indent, '*', _(prompt),
+ indent, '*', prompt,
indent, '*');
default:
;
@@ -430,12 +421,22 @@ static void check_conf(struct menu *menu)
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);
+ if (sym->name) {
+ const char *str;
+
+ if (sym->type == S_STRING) {
+ str = sym_get_string_value(sym);
+ str = sym_escape_string_value(str);
+ printf("%s%s=%s\n", CONFIG_, sym->name, str);
+ free((void *)str);
+ } else {
+ str = sym_get_string_value(sym);
+ printf("%s%s=%s\n", CONFIG_, sym->name, str);
+ }
}
- } else if (input_mode != olddefconfig) {
+ } else {
if (!conf_cnt++)
- printf(_("*\n* Restart config...\n*\n"));
+ printf("*\n* Restart config...\n*\n");
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
@@ -449,7 +450,7 @@ static void check_conf(struct menu *menu)
static struct option long_opts[] = {
{"oldaskconfig", no_argument, NULL, oldaskconfig},
{"oldconfig", no_argument, NULL, oldconfig},
- {"silentoldconfig", no_argument, NULL, silentoldconfig},
+ {"syncconfig", no_argument, NULL, syncconfig},
{"defconfig", optional_argument, NULL, defconfig},
{"savedefconfig", required_argument, NULL, savedefconfig},
{"allnoconfig", no_argument, NULL, allnoconfig},
@@ -459,26 +460,20 @@ static struct option long_opts[] = {
{"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("Usage: %s [-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(" --syncconfig Similar to oldconfig but generates configuration in\n"
+ " include/{generated/,config/}\n");
+ printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\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");
@@ -494,17 +489,23 @@ int main(int ac, char **av)
int opt;
const char *name, *defconfig_file = NULL /* gcc uninit */;
struct stat tmpstat;
+ int no_conf_write = 0;
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
+ tty_stdio = isatty(0) && isatty(1);
- tty_stdio = isatty(0) && isatty(1) && isatty(2);
-
- while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
+ while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
+ if (opt == 's') {
+ conf_set_message_callback(NULL);
+ continue;
+ }
input_mode = (enum input_mode)opt;
switch (opt) {
- case silentoldconfig:
+ case syncconfig:
+ /*
+ * syncconfig is invoked during the build stage.
+ * Suppress distracting "configuration written to ..."
+ */
+ conf_set_message_callback(NULL);
sync_kconfig = 1;
break;
case defconfig:
@@ -552,7 +553,7 @@ int main(int ac, char **av)
}
}
if (ac == optind) {
- printf(_("%s: Kconfig file missing\n"), av[0]);
+ fprintf(stderr, "%s: Kconfig file missing\n", av[0]);
conf_usage(progname);
exit(1);
}
@@ -562,12 +563,12 @@ int main(int ac, char **av)
if (sync_kconfig) {
name = conf_get_configname();
if (stat(name, &tmpstat)) {
- fprintf(stderr, _("***\n"
+ 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);
+ "***\n", name);
exit(1);
}
}
@@ -577,14 +578,16 @@ int main(int ac, char **av)
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);
+ fprintf(stderr,
+ "***\n"
+ "*** Can't find default configuration \"%s\"!\n"
+ "***\n",
+ defconfig_file);
exit(1);
}
break;
case savedefconfig:
- case silentoldconfig:
+ case syncconfig:
case oldaskconfig:
case oldconfig:
case listnewconfig:
@@ -602,7 +605,7 @@ int main(int ac, char **av)
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"),
+ "*** Can't read seed configuration \"%s\"!\n",
name);
exit(1);
}
@@ -619,7 +622,7 @@ int main(int ac, char **av)
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"),
+ "*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n",
name);
exit(1);
}
@@ -629,15 +632,15 @@ int main(int ac, char **av)
}
if (sync_kconfig) {
- if (conf_get_changed()) {
- name = getenv("KCONFIG_NOSILENTUPDATE");
- if (name && *name) {
+ name = getenv("KCONFIG_NOSILENTUPDATE");
+ if (name && *name) {
+ if (conf_get_changed()) {
fprintf(stderr,
- _("\n*** The configuration requires explicit update.\n\n"));
+ "\n*** The configuration requires explicit update.\n\n");
return 1;
}
+ no_conf_write = 1;
}
- valid_stdin = tty_stdio;
}
switch (input_mode) {
@@ -665,54 +668,48 @@ int main(int ac, char **av)
case oldaskconfig:
rootEntry = &rootmenu;
conf(&rootmenu);
- input_mode = silentoldconfig;
+ input_mode = oldconfig;
/* fall through */
case oldconfig:
case listnewconfig:
- case olddefconfig:
- case silentoldconfig:
+ case syncconfig:
/* Update until a loop caused no more changes */
do {
conf_cnt = 0;
check_conf(&rootmenu);
- } while (conf_cnt &&
- (input_mode != listnewconfig &&
- input_mode != olddefconfig));
+ } while (conf_cnt);
+ break;
+ case olddefconfig:
+ default:
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 (input_mode == savedefconfig) {
if (conf_write_defconfig(defconfig_file)) {
- fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
+ 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"));
+ if (!no_conf_write && conf_write(NULL)) {
+ fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
exit(1);
}
+
+ /*
+ * Create auto.conf if it does not exist.
+ * This prevents GNU Make 4.1 or older from emitting
+ * "include/config/auto.conf: No such file or directory"
+ * in the top-level Makefile
+ *
+ * syncconfig always creates or updates auto.conf because it is
+ * used during the build.
+ */
+ if (conf_write_autoconf(sync_kconfig) && sync_kconfig) {
+ fprintf(stderr,
+ "\n*** Error during sync of the configuration.\n\n");
+ return 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
index ce12bd555f..91d0a5c014 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -16,6 +16,69 @@
#include "lkc.h"
+/* return true if 'path' exists, false otherwise */
+static bool is_present(const char *path)
+{
+ struct stat st;
+
+ return !stat(path, &st);
+}
+
+/* return true if 'path' exists and it is a directory, false otherwise */
+static bool is_dir(const char *path)
+{
+ struct stat st;
+
+ if (stat(path, &st))
+ return 0;
+
+ return S_ISDIR(st.st_mode);
+}
+
+/*
+ * Create the parent directory of the given path.
+ *
+ * For example, if 'include/config/auto.conf' is given, create 'include/config'.
+ */
+static int make_parent_dir(const char *path)
+{
+ char tmp[PATH_MAX + 1];
+ char *p;
+
+ strncpy(tmp, path, sizeof(tmp));
+ tmp[sizeof(tmp) - 1] = 0;
+
+ /* Remove the base name. Just return if nothing is left */
+ p = strrchr(tmp, '/');
+ if (!p)
+ return 0;
+ *(p + 1) = 0;
+
+ /* Just in case it is an absolute path */
+ p = tmp;
+ while (*p == '/')
+ p++;
+
+ while ((p = strchr(p, '/'))) {
+ *p = 0;
+
+ /* skip if the directory exists */
+ if (!is_dir(tmp) && mkdir(tmp, 0755))
+ return -1;
+
+ *p = '/';
+ while (*p == '/')
+ p++;
+ }
+
+ return 0;
+}
+
+struct conf_printer {
+ void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
+ void (*print_comment)(FILE *, const char *, void *);
+};
+
static void conf_warning(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
@@ -23,9 +86,9 @@ 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;
+static int conf_lineno, conf_warnings;
-const char conf_defname[] = "arch/$ARCH/defconfig";
+const char conf_defname[] = "arch/$(ARCH)/defconfig";
static void conf_warning(const char *fmt, ...)
{
@@ -38,16 +101,16 @@ static void conf_warning(const char *fmt, ...)
conf_warnings++;
}
-static void conf_default_message_callback(const char *fmt, va_list ap)
+static void conf_default_message_callback(const char *s)
{
printf("#\n# ");
- vprintf(fmt, ap);
+ printf("%s", s);
printf("\n#\n");
}
-static void (*conf_message_callback) (const char *fmt, va_list ap) =
+static void (*conf_message_callback)(const char *s) =
conf_default_message_callback;
-void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
+void conf_set_message_callback(void (*fn)(const char *s))
{
conf_message_callback = fn;
}
@@ -55,10 +118,16 @@ void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
static void conf_message(const char *fmt, ...)
{
va_list ap;
+ char buf[4096];
+
+ if (!conf_message_callback)
+ return;
va_start(ap, fmt);
- if (conf_message_callback)
- conf_message_callback(fmt, ap);
+
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ conf_message_callback(buf);
+ va_end(ap);
}
const char *conf_get_configname(void)
@@ -75,43 +144,16 @@ const char *conf_get_autoconfig_name(void)
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);
+ name = expand_string(conf_defname);
env = getenv(SRCTREE);
if (env) {
sprintf(fullname, "%s/%s", env, name);
- if (!stat(fullname, &buf))
+ if (is_present(fullname))
return fullname;
}
return name;
@@ -172,7 +214,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
case S_HEX:
done:
if (sym_string_valid(sym, p)) {
- sym->def[def].val = strdup(p);
+ sym->def[def].val = xstrdup(p);
sym->flags |= def_flags;
} else {
if (def != S_DEF_AUTO)
@@ -195,7 +237,7 @@ static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
if (new_size > *n) {
new_size += LINE_GROWTH - 1;
new_size *= 2;
- nline = realloc(*lineptr, new_size);
+ nline = xrealloc(*lineptr, new_size);
if (!nline)
return -1;
@@ -261,20 +303,18 @@ int conf_read_simple(const char *name, int def)
if (in)
goto load;
sym_add_change_count(1);
- if (!sym_defconfig_list) {
- if (modules_sym)
- sym_calc_value(modules_sym);
+ if (!sym_defconfig_list)
return 1;
- }
for_all_defaults(sym_defconfig_list, prop) {
if (expr_calc_value(prop->visible.expr) == no ||
prop->expr->type != E_SYMBOL)
continue;
- name = conf_expand_value(prop->expr->left.sym->name);
+ sym_calc_value(prop->expr->left.sym);
+ name = sym_get_string_value(prop->expr->left.sym);
in = zconf_fopen(name);
if (in) {
- conf_message(_("using defaults found in %s"),
+ conf_message("using defaults found in %s",
name);
goto load;
}
@@ -287,7 +327,6 @@ load:
conf_filename = name;
conf_lineno = 0;
conf_warnings = 0;
- conf_unsaved = 0;
def_flags = SYMBOL_DEF << def;
for_all_symbols(i, sym) {
@@ -372,7 +411,9 @@ load:
continue;
} else {
if (line[0] != '\r' && line[0] != '\n')
- conf_warning("unexpected data");
+ conf_warning("unexpected data: %.*s",
+ (int)strcspn(line, "\r\n"), line);
+
continue;
}
setsym:
@@ -398,25 +439,27 @@ setsym:
}
free(line);
fclose(in);
-
- if (modules_sym)
- sym_calc_value(modules_sym);
return 0;
}
int conf_read(const char *name)
{
struct symbol *sym;
+ int conf_unsaved = 0;
int i;
sym_set_change_count(0);
- if (conf_read_simple(name, S_DEF_USER))
+ if (conf_read_simple(name, S_DEF_USER)) {
+ sym_calc_value(modules_sym);
return 1;
+ }
+
+ sym_calc_value(modules_sym);
for_all_symbols(i, sym) {
sym_calc_value(sym);
- if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
+ if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
continue;
if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
/* check that calculated value agrees with saved value */
@@ -744,10 +787,9 @@ int conf_write(const char *name)
dirname[0] = 0;
if (name && name[0]) {
- struct stat st;
char *slash;
- if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
+ if (is_dir(name)) {
strcpy(dirname, name);
strcat(dirname, "/");
basename = conf_get_configname();
@@ -825,32 +867,66 @@ next:
return 1;
}
- conf_message(_("configuration written to %s"), newname);
+ conf_message("configuration written to %s", newname);
sym_set_change_count(0);
return 0;
}
+/* write a dependency file as used by kbuild to track dependencies */
+static int conf_write_dep(const char *name)
+{
+ 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());
+
+ env_write_dep(out, conf_get_autoconfig_name());
+
+ fprintf(out, "\n$(deps_config): ;\n");
+ fclose(out);
+
+ if (make_parent_dir(name))
+ return 1;
+ rename("..config.tmp", name);
+ 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);
+ sym_calc_value(modules_sym);
+ if (make_parent_dir("include/config/foo.h"))
+ return 1;
if (chdir("include/config"))
return 1;
res = 0;
for_all_symbols(i, sym) {
sym_calc_value(sym);
- if ((sym->flags & SYMBOL_AUTO) || !sym->name)
+ if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
continue;
if (sym->flags & SYMBOL_WRITE) {
if (sym->flags & SYMBOL_DEF_AUTO) {
@@ -915,19 +991,12 @@ static int conf_split_config(void)
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++ = '/';
+
+ if (make_parent_dir(path)) {
+ res = 1;
+ goto out;
}
+
/* Try it again. */
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
@@ -944,16 +1013,20 @@ out:
return res;
}
-int conf_write_autoconf(void)
+int conf_write_autoconf(int overwrite)
{
struct symbol *sym;
const char *name;
+ const char *autoconf_name = conf_get_autoconfig_name();
FILE *out, *tristate, *out_h;
int i;
+ if (!overwrite && is_present(autoconf_name))
+ return 0;
+
sym_clear_all_valid();
- file_write_dep("include/config/auto.conf.cmd");
+ conf_write_dep("include/config/auto.conf.cmd");
if (conf_split_config())
return 1;
@@ -1000,19 +1073,26 @@ int conf_write_autoconf(void)
name = getenv("KCONFIG_AUTOHEADER");
if (!name)
name = "include/generated/autoconf.h";
+ if (make_parent_dir(name))
+ return 1;
if (rename(".tmpconfig.h", name))
return 1;
+
name = getenv("KCONFIG_TRISTATE");
if (!name)
name = "include/config/tristate.conf";
+ if (make_parent_dir(name))
+ return 1;
if (rename(".tmpconfig_tristate", name))
return 1;
- name = conf_get_autoconfig_name();
+
+ if (make_parent_dir(autoconf_name))
+ return 1;
/*
* 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))
+ if (rename(".tmpconfig", autoconf_name))
return 1;
return 0;
@@ -1116,7 +1196,7 @@ void set_all_choice_values(struct symbol *csym)
bool conf_set_all_new_symbols(enum conf_def_mode mode)
{
struct symbol *sym, *csym;
- int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y
+ int i, cnt, pby, pty, ptm; /* pby: probability of bool = y
* pty: probability of tristate = y
* ptm: probability of tristate = m
*/
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index d6626521f9..e1a39e9084 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -11,6 +11,9 @@
#define DEBUG_EXPR 0
+static int expr_eq(struct expr *e1, struct expr *e2);
+static struct expr *expr_eliminate_yn(struct expr *e);
+
struct expr *expr_alloc_symbol(struct symbol *sym)
{
struct expr *e = xcalloc(1, sizeof(*e));
@@ -76,6 +79,10 @@ struct expr *expr_copy(const struct expr *org)
e->left.expr = expr_copy(org->left.expr);
break;
case E_EQUAL:
+ case E_GEQ:
+ case E_GTH:
+ case E_LEQ:
+ case E_LTH:
case E_UNEQUAL:
e->left.sym = org->left.sym;
e->right.sym = org->right.sym;
@@ -87,7 +94,7 @@ struct expr *expr_copy(const struct expr *org)
e->right.expr = expr_copy(org->right.expr);
break;
default:
- printf("can't copy type %d\n", e->type);
+ fprintf(stderr, "can't copy type %d\n", e->type);
free(e);
e = NULL;
break;
@@ -106,8 +113,12 @@ void expr_free(struct expr *e)
break;
case E_NOT:
expr_free(e->left.expr);
- return;
+ break;
case E_EQUAL:
+ case E_GEQ:
+ case E_GTH:
+ case E_LEQ:
+ case E_LTH:
case E_UNEQUAL:
break;
case E_OR:
@@ -116,7 +127,7 @@ void expr_free(struct expr *e)
expr_free(e->right.expr);
break;
default:
- printf("how to free type %d?\n", e->type);
+ fprintf(stderr, "how to free type %d?\n", e->type);
break;
}
free(e);
@@ -127,8 +138,18 @@ static int trans_count;
#define e1 (*ep1)
#define e2 (*ep2)
+/*
+ * expr_eliminate_eq() helper.
+ *
+ * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
+ * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
+ * against all other leaves. Two equal leaves are both replaced with either 'y'
+ * or 'n' as appropriate for 'type', to be eliminated later.
+ */
static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
+ /* Recurse down to leaves */
+
if (e1->type == type) {
__expr_eliminate_eq(type, &e1->left.expr, &e2);
__expr_eliminate_eq(type, &e1->right.expr, &e2);
@@ -139,12 +160,18 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
__expr_eliminate_eq(type, &e1, &e2->right.expr);
return;
}
+
+ /* e1 and e2 are leaves. Compare them. */
+
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;
+
+ /* e1 and e2 are equal leaves. Prepare them for elimination. */
+
trans_count++;
expr_free(e1); expr_free(e2);
switch (type) {
@@ -161,6 +188,35 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
}
}
+/*
+ * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
+ * Example reductions:
+ *
+ * ep1: A && B -> ep1: y
+ * ep2: A && B && C -> ep2: C
+ *
+ * ep1: A || B -> ep1: n
+ * ep2: A || B || C -> ep2: C
+ *
+ * ep1: A && (B && FOO) -> ep1: FOO
+ * ep2: (BAR && B) && A -> ep2: BAR
+ *
+ * ep1: A && (B || C) -> ep1: y
+ * ep2: (C || B) && A -> ep2: y
+ *
+ * Comparisons are done between all operands at the same "level" of && or ||.
+ * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
+ * following operands will be compared:
+ *
+ * - 'e1', 'e2 || e3', and 'e4 || e5', against each other
+ * - e2 against e3
+ * - e4 against e5
+ *
+ * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
+ * '(e1 && e2) && e3' are both a single level.
+ *
+ * See __expr_eliminate_eq() as well.
+ */
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
{
if (!e1 || !e2)
@@ -186,7 +242,13 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
#undef e1
#undef e2
-int expr_eq(struct expr *e1, struct expr *e2)
+/*
+ * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
+ * &&/|| expressions are considered equal if every operand in one expression
+ * equals some operand in the other (operands do not need to appear in the same
+ * order), recursively.
+ */
+static int expr_eq(struct expr *e1, struct expr *e2)
{
int res, old_count;
@@ -194,6 +256,10 @@ int expr_eq(struct expr *e1, struct expr *e2)
return 0;
switch (e1->type) {
case E_EQUAL:
+ case E_GEQ:
+ case E_GTH:
+ case E_LEQ:
+ case E_LTH:
case E_UNEQUAL:
return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
case E_SYMBOL:
@@ -228,7 +294,18 @@ int expr_eq(struct expr *e1, struct expr *e2)
return 0;
}
-struct expr *expr_eliminate_yn(struct expr *e)
+/*
+ * Recursively performs the following simplifications in-place (as well as the
+ * corresponding simplifications with swapped operands):
+ *
+ * expr && n -> n
+ * expr && y -> expr
+ * expr || n -> expr
+ * expr || y -> y
+ *
+ * Returns the optimized expression.
+ */
+static struct expr *expr_eliminate_yn(struct expr *e)
{
struct expr *tmp;
@@ -501,12 +578,21 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
return NULL;
}
+/*
+ * expr_eliminate_dups() helper.
+ *
+ * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
+ * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
+ * against all other leaves to look for simplifications.
+ */
static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
#define e1 (*ep1)
#define e2 (*ep2)
struct expr *tmp;
+ /* Recurse down to leaves */
+
if (e1->type == type) {
expr_eliminate_dups1(type, &e1->left.expr, &e2);
expr_eliminate_dups1(type, &e1->right.expr, &e2);
@@ -517,6 +603,9 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
expr_eliminate_dups1(type, &e1, &e2->right.expr);
return;
}
+
+ /* e1 and e2 are leaves. Compare and process them. */
+
if (e1 == e2)
return;
@@ -553,62 +642,17 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
#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
-}
-
+/*
+ * Rewrites 'e' in-place to remove ("join") duplicate and other redundant
+ * operands.
+ *
+ * Example simplifications:
+ *
+ * A || B || A -> A || B
+ * A && B && A=y -> A=y && B
+ *
+ * Returns the deduplicated expression.
+ */
struct expr *expr_eliminate_dups(struct expr *e)
{
int oldcount;
@@ -621,11 +665,11 @@ struct expr *expr_eliminate_dups(struct expr *e)
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)
+ /* No simplifications done in this pass. We're done */
break;
e = expr_eliminate_yn(e);
}
@@ -633,6 +677,12 @@ struct expr *expr_eliminate_dups(struct expr *e)
return e;
}
+/*
+ * Performs various simplifications involving logical operators and
+ * comparisons.
+ *
+ * Allocates and returns a new expression.
+ */
struct expr *expr_transform(struct expr *e)
{
struct expr *tmp;
@@ -641,6 +691,10 @@ struct expr *expr_transform(struct expr *e)
return NULL;
switch (e->type) {
case E_EQUAL:
+ case E_GEQ:
+ case E_GTH:
+ case E_LEQ:
+ case E_LTH:
case E_UNEQUAL:
case E_SYMBOL:
case E_LIST:
@@ -713,6 +767,22 @@ struct expr *expr_transform(struct expr *e)
e = tmp;
e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
break;
+ case E_LEQ:
+ case E_GEQ:
+ // !a<='x' -> a>'x'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = e->type == E_LEQ ? E_GTH : E_LTH;
+ break;
+ case E_LTH:
+ case E_GTH:
+ // !a<'x' -> a>='x'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
+ break;
case E_OR:
// !(a || b) -> !a && !b
tmp = e->left.expr;
@@ -783,6 +853,10 @@ int expr_contains_symbol(struct expr *dep, struct symbol *sym)
case E_SYMBOL:
return dep->left.sym == sym;
case E_EQUAL:
+ case E_GEQ:
+ case E_GTH:
+ case E_LEQ:
+ case E_LTH:
case E_UNEQUAL:
return dep->left.sym == sym ||
dep->right.sym == sym;
@@ -823,57 +897,20 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
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
-}
-
+/*
+ * Inserts explicit comparisons of type 'type' to symbol 'sym' into the
+ * expression 'e'.
+ *
+ * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
+ *
+ * A -> A!=n
+ * !A -> A=n
+ * A && B -> !(A=n || B=n)
+ * A || B -> !(A=n && B=n)
+ * A && (B || C) -> !(A=n || (B=n && C=n))
+ *
+ * Allocates and returns a new expression.
+ */
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
{
struct expr *e1, *e2;
@@ -908,6 +945,10 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
case E_NOT:
return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
case E_UNEQUAL:
+ case E_LTH:
+ case E_LEQ:
+ case E_GTH:
+ case E_GEQ:
case E_EQUAL:
if (type == E_EQUAL) {
if (sym == &symbol_yes)
@@ -935,10 +976,60 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
return NULL;
}
+enum string_value_kind {
+ k_string,
+ k_signed,
+ k_unsigned,
+ k_invalid
+};
+
+union string_value {
+ unsigned long long u;
+ signed long long s;
+};
+
+static enum string_value_kind expr_parse_string(const char *str,
+ enum symbol_type type,
+ union string_value *val)
+{
+ char *tail;
+ enum string_value_kind kind;
+
+ errno = 0;
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ val->s = !strcmp(str, "n") ? 0 :
+ !strcmp(str, "m") ? 1 :
+ !strcmp(str, "y") ? 2 : -1;
+ return k_signed;
+ case S_INT:
+ val->s = strtoll(str, &tail, 10);
+ kind = k_signed;
+ break;
+ case S_HEX:
+ val->u = strtoull(str, &tail, 16);
+ kind = k_unsigned;
+ break;
+ case S_STRING:
+ case S_UNKNOWN:
+ val->s = strtoll(str, &tail, 0);
+ kind = k_signed;
+ break;
+ default:
+ return k_invalid;
+ }
+ return !errno && !*tail && tail > str && isxdigit(tail[-1])
+ ? kind : k_string;
+}
+
tristate expr_calc_value(struct expr *e)
{
tristate val1, val2;
const char *str1, *str2;
+ enum string_value_kind k1 = k_string, k2 = k_string;
+ union string_value lval = {}, rval = {};
+ int res;
if (!e)
return yes;
@@ -959,31 +1050,70 @@ tristate expr_calc_value(struct expr *e)
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_GEQ:
+ case E_GTH:
+ case E_LEQ:
+ case E_LTH:
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;
+ break;
default:
printf("expr_calc_value: %d?\n", e->type);
return no;
}
+
+ 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);
+
+ if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {
+ k1 = expr_parse_string(str1, e->left.sym->type, &lval);
+ k2 = expr_parse_string(str2, e->right.sym->type, &rval);
+ }
+
+ if (k1 == k_string || k2 == k_string)
+ res = strcmp(str1, str2);
+ else if (k1 == k_invalid || k2 == k_invalid) {
+ if (e->type != E_EQUAL && e->type != E_UNEQUAL) {
+ printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2);
+ return no;
+ }
+ res = strcmp(str1, str2);
+ } else if (k1 == k_unsigned || k2 == k_unsigned)
+ res = (lval.u > rval.u) - (lval.u < rval.u);
+ else /* if (k1 == k_signed && k2 == k_signed) */
+ res = (lval.s > rval.s) - (lval.s < rval.s);
+
+ switch(e->type) {
+ case E_EQUAL:
+ return res ? no : yes;
+ case E_GEQ:
+ return res >= 0 ? yes : no;
+ case E_GTH:
+ return res > 0 ? yes : no;
+ case E_LEQ:
+ return res <= 0 ? yes : no;
+ case E_LTH:
+ return res < 0 ? yes : no;
+ case E_UNEQUAL:
+ return res ? yes : no;
+ default:
+ printf("expr_calc_value: relation %d?\n", e->type);
+ return no;
+ }
}
-int expr_compare_type(enum expr_type t1, enum expr_type t2)
+static 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_LEQ:
+ case E_LTH:
+ case E_GEQ:
+ case E_GTH:
+ if (t2 == E_EQUAL || t2 == E_UNEQUAL)
+ return 1;
case E_EQUAL:
case E_UNEQUAL:
if (t2 == E_NOT)
@@ -1005,52 +1135,11 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2)
}
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)
+void expr_print(struct expr *e,
+ void (*fn)(void *, struct symbol *, const char *),
+ void *data, int prevtoken)
{
if (!e) {
fn(data, NULL, "y");
@@ -1078,6 +1167,24 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
fn(data, NULL, "=");
fn(data, e->right.sym, e->right.sym->name);
break;
+ case E_LEQ:
+ case E_LTH:
+ if (e->left.sym->name)
+ fn(data, e->left.sym, e->left.sym->name);
+ else
+ fn(data, NULL, "<choice>");
+ fn(data, NULL, e->type == E_LEQ ? "<=" : "<");
+ fn(data, e->right.sym, e->right.sym->name);
+ break;
+ case E_GEQ:
+ case E_GTH:
+ if (e->left.sym->name)
+ fn(data, e->left.sym, e->left.sym->name);
+ else
+ fn(data, NULL, "<choice>");
+ fn(data, NULL, e->type == E_GEQ ? ">=" : ">");
+ 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);
@@ -1166,3 +1273,33 @@ void expr_gstr_print(struct expr *e, struct gstr *gs)
{
expr_print(e, expr_print_gstr_helper, gs, E_NONE);
}
+
+/*
+ * Transform the top level "||" tokens into newlines and prepend each
+ * line with a minus. This makes expressions much easier to read.
+ * Suitable for reverse dependency expressions.
+ */
+static void expr_print_revdep(struct expr *e,
+ void (*fn)(void *, struct symbol *, const char *),
+ void *data, tristate pr_type, const char **title)
+{
+ if (e->type == E_OR) {
+ expr_print_revdep(e->left.expr, fn, data, pr_type, title);
+ expr_print_revdep(e->right.expr, fn, data, pr_type, title);
+ } else if (expr_calc_value(e) == pr_type) {
+ if (*title) {
+ fn(data, NULL, *title);
+ *title = NULL;
+ }
+
+ fn(data, NULL, " - ");
+ expr_print(e, fn, data, E_NONE);
+ fn(data, NULL, "\n");
+ }
+}
+
+void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
+ tristate pr_type, const char *title)
+{
+ expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);
+}
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 412ea8a2ab..7c329e1790 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -29,7 +29,9 @@ typedef enum tristate {
} tristate;
enum expr_type {
- E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE
+ E_NONE, E_OR, E_AND, E_NOT,
+ E_EQUAL, E_UNEQUAL, E_LTH, E_LEQ, E_GTH, E_GEQ,
+ E_LIST, E_SYMBOL, E_RANGE
};
union expr_data {
@@ -72,17 +74,61 @@ enum {
S_DEF_COUNT
};
+/*
+ * Represents a configuration symbol.
+ *
+ * Choices are represented as a special kind of symbol and have the
+ * SYMBOL_CHOICE bit set in 'flags'.
+ */
struct symbol {
+ /* The next symbol in the same bucket in the symbol hash table */
struct symbol *next;
+
+ /* The name of the symbol, e.g. "FOO" for 'config FOO' */
char *name;
+
+ /* S_BOOLEAN, S_TRISTATE, ... */
enum symbol_type type;
+
+ /*
+ * The calculated value of the symbol. The SYMBOL_VALID bit is set in
+ * 'flags' when this is up to date. Note that this value might differ
+ * from the user value set in e.g. a .config file, due to visibility.
+ */
struct symbol_value curr;
+
+ /*
+ * Values for the symbol provided from outside. def[S_DEF_USER] holds
+ * the .config value.
+ */
struct symbol_value def[S_DEF_COUNT];
+
+ /*
+ * An upper bound on the tristate value the user can set for the symbol
+ * if it is a boolean or tristate. Calculated from prompt dependencies,
+ * which also inherit dependencies from enclosing menus, choices, and
+ * ifs. If 'n', the user value will be ignored.
+ *
+ * Symbols lacking prompts always have visibility 'n'.
+ */
tristate visible;
+
+ /* SYMBOL_* flags */
int flags;
+
+ /* List of properties. See prop_type. */
struct property *prop;
+
+ /* Dependencies from enclosing menus, choices, and ifs */
struct expr_value dir_dep;
+
+ /* Reverse dependencies through being selected by other symbols */
struct expr_value rev_dep;
+
+ /*
+ * "Weak" reverse dependencies through being implied by other symbols
+ */
+ struct expr_value implied;
};
#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)
@@ -95,7 +141,7 @@ struct symbol {
#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */
#define SYMBOL_CHANGED 0x0400 /* ? */
-#define SYMBOL_AUTO 0x1000 /* value from environment variable */
+#define SYMBOL_NO_WRITE 0x1000 /* Symbol for internal use only; it will not be written */
#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
#define SYMBOL_WARNED 0x8000 /* warning has been issued */
@@ -125,17 +171,20 @@ struct symbol {
* config BAZ
* int "BAZ Value"
* range 1..255
+ *
+ * Please, also check zconf.y:print_symbol() when modifying the
+ * list of property types!
*/
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_MENU, /* prompt associated with a menu or menuconfig symbol */
P_DEFAULT, /* default y */
P_CHOICE, /* choice value */
P_SELECT, /* select BAR */
+ P_IMPLY, /* imply BAR */
P_RANGE, /* range 7..100 (for a symbol) */
- P_ENV, /* value from environment variable */
P_SYMBOL, /* where a symbol is defined */
};
@@ -162,22 +211,67 @@ struct property {
for (st = sym->prop; st; st = st->next) \
if (st->text)
+/*
+ * Represents a node in the menu tree, as seen in e.g. menuconfig (though used
+ * for all front ends). Each symbol, menu, etc. defined in the Kconfig files
+ * gets a node. A symbol defined in multiple locations gets one node at each
+ * location.
+ */
struct menu {
+ /* The next menu node at the same level */
struct menu *next;
+
+ /* The parent menu node, corresponding to e.g. a menu or choice */
struct menu *parent;
+
+ /* The first child menu node, for e.g. menus and choices */
struct menu *list;
+
+ /*
+ * The symbol associated with the menu node. Choices are implemented as
+ * a special kind of symbol. NULL for menus, comments, and ifs.
+ */
struct symbol *sym;
+
+ /*
+ * The prompt associated with the node. This holds the prompt for a
+ * symbol as well as the text for a menu or comment, along with the
+ * type (P_PROMPT, P_MENU, etc.)
+ */
struct property *prompt;
+
+ /*
+ * 'visible if' dependencies. If more than one is given, they will be
+ * ANDed together.
+ */
struct expr *visibility;
+
+ /*
+ * Ordinary dependencies from e.g. 'depends on' and 'if', ANDed
+ * together
+ */
struct expr *dep;
+
+ /* MENU_* flags */
unsigned int flags;
+
+ /* Any help text associated with the node */
char *help;
+
+ /* The location where the menu node appears in the Kconfig files */
struct file *file;
int lineno;
+
+ /* For use by front ends that need to store auxiliary data */
void *data;
};
+/*
+ * Set on a menu node when the corresponding symbol changes state in some way.
+ * Can be checked by front ends.
+ */
#define MENU_CHANGED 0x0001
+
#define MENU_ROOT 0x0002
struct jump_key {
@@ -205,24 +299,20 @@ 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);
+void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
+ tristate pr_type, const char *title);
static inline int expr_is_yes(struct expr *e)
{
diff --git a/scripts/kconfig/gconf-cfg.sh b/scripts/kconfig/gconf-cfg.sh
new file mode 100755
index 0000000000..480ecd8b9f
--- /dev/null
+++ b/scripts/kconfig/gconf-cfg.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+PKG="gtk+-2.0 gmodule-2.0 libglade-2.0"
+
+if [ -z "$(command -v pkg-config)" ]; then
+ echo >&2 "*"
+ echo >&2 "* 'make gconfig' requires 'pkg-config'. Please install it."
+ echo >&2 "*"
+ exit 1
+fi
+
+if ! pkg-config --exists $PKG; then
+ 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 $PKG"
+ echo >&2 "*"
+ exit 1
+fi
+
+if ! pkg-config --atleast-version=2.0.0 gtk+-2.0; then
+ echo >&2 "*"
+ echo >&2 "* GTK+ is present but version >= 2.0.0 is required."
+ echo >&2 "*"
+ exit 1
+fi
+
+echo cflags=\"$(pkg-config --cflags $PKG)\"
+echo libs=\"$(pkg-config --libs $PKG)\"
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index d0a35b21f3..36f578415c 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -101,8 +101,8 @@ const char *dbg_sym_flags(int val)
strcat(buf, "write/");
if (val & SYMBOL_CHANGED)
strcat(buf, "changed/");
- if (val & SYMBOL_AUTO)
- strcat(buf, "auto/");
+ if (val & SYMBOL_NO_WRITE)
+ strcat(buf, "no_write/");
buf[strlen(buf) - 1] = '\0';
@@ -137,7 +137,7 @@ void init_main_window(const gchar * glade_file)
xml = glade_xml_new(glade_file, "window1", NULL);
if (!xml)
- g_error(_("GUI loading failed !\n"));
+ g_error("GUI loading failed !\n");
glade_xml_signal_autoconnect(xml);
main_wnd = glade_xml_get_widget(xml, "window1");
@@ -169,14 +169,6 @@ void init_main_window(const gchar * glade_file)
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,
@@ -184,22 +176,6 @@ void init_main_window(const gchar * glade_file)
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",
@@ -257,7 +233,7 @@ void init_left_tree(void)
column = gtk_tree_view_column_new();
gtk_tree_view_append_column(view, column);
- gtk_tree_view_column_set_title(column, _("Options"));
+ 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),
@@ -300,7 +276,7 @@ void init_right_tree(void)
column = gtk_tree_view_column_new();
gtk_tree_view_append_column(view, column);
- gtk_tree_view_column_set_title(column, _("Options"));
+ 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),
@@ -329,7 +305,7 @@ void init_right_tree(void)
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(view, -1,
- _("Name"), renderer,
+ "Name", renderer,
"text", COL_NAME,
"foreground-gdk",
COL_COLOR, NULL);
@@ -353,7 +329,7 @@ void init_right_tree(void)
COL_COLOR, NULL);
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(view, -1,
- _("Value"), renderer,
+ "Value", renderer,
"text", COL_VALUE,
"editable",
COL_EDIT,
@@ -392,7 +368,7 @@ static void text_insert_help(struct menu *menu)
{
GtkTextBuffer *buffer;
GtkTextIter start, end;
- const char *prompt = _(menu_get_prompt(menu));
+ const char *prompt = menu_get_prompt(menu);
struct gstr help = str_new();
menu_get_ext_help(menu, &help);
@@ -446,7 +422,7 @@ gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
if (!conf_get_changed())
return FALSE;
- dialog = gtk_dialog_new_with_buttons(_("Warning !"),
+ dialog = gtk_dialog_new_with_buttons("Warning !",
GTK_WINDOW(main_wnd),
(GtkDialogFlags)
(GTK_DIALOG_MODAL |
@@ -460,7 +436,7 @@ gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
gtk_dialog_set_default_response(GTK_DIALOG(dialog),
GTK_RESPONSE_CANCEL);
- label = gtk_label_new(_("\nSave configuration ?\n"));
+ label = gtk_label_new("\nSave configuration ?\n");
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
gtk_widget_show(label);
@@ -520,7 +496,7 @@ load_filename(GtkFileSelection * file_selector, gpointer user_data)
(user_data));
if (conf_read(fn))
- text_insert_msg(_("Error"), _("Unable to load configuration !"));
+ text_insert_msg("Error", "Unable to load configuration !");
else
display_tree(&rootmenu);
}
@@ -529,7 +505,7 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *fs;
- fs = gtk_file_selection_new(_("Load file..."));
+ 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);
@@ -548,7 +524,8 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
{
if (conf_write(NULL))
- text_insert_msg(_("Error"), _("Unable to save configuration !"));
+ text_insert_msg("Error", "Unable to save configuration !");
+ conf_write_autoconf(0);
}
@@ -561,7 +538,7 @@ store_filename(GtkFileSelection * file_selector, gpointer user_data)
(user_data));
if (conf_write(fn))
- text_insert_msg(_("Error"), _("Unable to save configuration !"));
+ text_insert_msg("Error", "Unable to save configuration !");
gtk_widget_destroy(GTK_WIDGET(user_data));
}
@@ -570,7 +547,7 @@ void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *fs;
- fs = gtk_file_selection_new(_("Save file as..."));
+ 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);
@@ -663,7 +640,7 @@ on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *dialog;
- const gchar *intro_text = _(
+ 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"
@@ -678,7 +655,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
"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.");
+ "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,
@@ -695,8 +672,8 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *about_text =
- _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
- "Based on the source code from Roman Zippel.\n");
+ "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
+ "Based on the source code from Roman Zippel.\n";
dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -713,9 +690,9 @@ 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"
+ "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");
+ "visit http://www.fsf.org/licenses/licenses.html\n";
dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -938,7 +915,7 @@ on_treeview2_button_press_event(GtkWidget * widget,
current = menu;
display_tree_part();
gtk_widget_set_sensitive(back_btn, TRUE);
- } else if ((col == COL_OPTION)) {
+ } else if (col == COL_OPTION) {
toggle_sym_value(menu);
gtk_tree_view_expand_row(view, path, TRUE);
}
@@ -1073,7 +1050,7 @@ static gchar **fill_row(struct menu *menu)
bzero(row, sizeof(row));
row[COL_OPTION] =
- g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
+ g_strdup_printf("%s %s", menu_get_prompt(menu),
sym && !sym_has_value(sym) ? "(NEW)" : "");
if (opt_mode == OPT_ALL && !menu_is_visible(menu))
@@ -1126,7 +1103,7 @@ static gchar **fill_row(struct menu *menu)
if (def_menu)
row[COL_VALUE] =
- g_strdup(_(menu_get_prompt(def_menu)));
+ g_strdup(menu_get_prompt(def_menu));
}
if (sym->flags & SYMBOL_CHOICEVAL)
row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
@@ -1471,10 +1448,6 @@ int main(int ac, char *av[])
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);
@@ -1498,9 +1471,12 @@ int main(int ac, char *av[])
case 'a':
//showAll = 1;
break;
+ case 's':
+ conf_set_message_callback(NULL);
+ break;
case 'h':
case '?':
- printf("%s <config>\n", av[0]);
+ printf("%s [-s] <config>\n", av[0]);
exit(0);
}
name = av[2];
diff --git a/scripts/kconfig/kconf_id.c b/scripts/kconfig/kconf_id.c
new file mode 100644
index 0000000000..b3e0ea0ac7
--- /dev/null
+++ b/scripts/kconfig/kconf_id.c
@@ -0,0 +1,52 @@
+
+static struct kconf_id kconf_id_array[] = {
+ { "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 },
+ { "---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 },
+ { "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 },
+ { "imply", T_IMPLY, 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 },
+ { "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION },
+};
+
+#define KCONF_ID_ARRAY_SIZE (sizeof(kconf_id_array)/sizeof(struct kconf_id))
+
+static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len)
+{
+ int i;
+
+ for (i = 0; i < KCONF_ID_ARRAY_SIZE; i++) {
+ struct kconf_id *id = kconf_id_array+i;
+ int l = strlen(id->name);
+
+ if (len == l && !memcmp(str, id->name, len))
+ return id;
+ }
+ return NULL;
+}
diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c
deleted file mode 100644
index 2858738b22..0000000000
--- a/scripts/kconfig/kxgettext.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
- *
- * Released under the terms of the GNU GPL v2.0
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#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
index 685d80e1bb..45cb237ab7 100644
--- a/scripts/kconfig/list.h
+++ b/scripts/kconfig/list.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LIST_H
#define LIST_H
@@ -34,7 +35,7 @@ struct list_head {
* 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.
+ * @member: the name of the list_head within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
@@ -43,7 +44,7 @@ struct list_head {
* 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.
+ * @member: the name of the list_head within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
@@ -55,7 +56,7 @@ struct list_head {
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index d5daa7af8b..9eb7c837cd 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -8,22 +8,11 @@
#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"
@@ -31,11 +20,6 @@ extern "C" {
#define PACKAGE "linux"
#endif
-#define LOCALEDIR "/usr/share/locale"
-
-#define _(text) gettext(text)
-#define N_(text) (text)
-
#ifndef CONFIG_
#define CONFIG_ "CONFIG_"
#endif
@@ -60,19 +44,16 @@ enum conf_def_mode {
#define T_OPT_MODULES 1
#define T_OPT_DEFCONFIG_LIST 2
-#define T_OPT_ENV 3
#define T_OPT_ALLNOCONFIG_Y 4
struct kconf_id {
- int name;
+ const char *name;
int token;
unsigned int flags;
enum symbol_type stype;
};
-extern int zconfdebug;
-
-int zconfparse(void);
+extern int yylineno;
void zconfdump(FILE *out);
void zconf_starthelp(void);
FILE *zconf_fopen(const char *name);
@@ -90,11 +71,6 @@ void sym_add_change_count(int count);
bool conf_set_all_new_symbols(enum conf_def_mode mode);
void set_all_choice_values(struct symbol *csym);
-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)
{
@@ -110,10 +86,8 @@ 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);
@@ -123,9 +97,11 @@ 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);
+void *xrealloc(void *p, size_t size);
+char *xstrdup(const char *s);
+char *xstrndup(const char *s, size_t n);
struct gstr {
size_t len;
@@ -137,25 +113,18 @@ struct gstr {
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)
{
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index ecdb9659b6..86c267540c 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -1,57 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
#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)));
+void conf_parse(const char *name);
+int conf_read(const char *name);
+int conf_read_simple(const char *name, int);
+int conf_write_defconfig(const char *name);
+int conf_write(const char *name);
+int conf_write_autoconf(int overwrite);
+bool conf_get_changed(void);
+void conf_set_changed_callback(void (*fn)(void));
+void conf_set_message_callback(void (*fn)(const char *s));
/* menu.c */
-P(rootmenu,struct menu,);
-
-P(menu_is_empty, bool, (struct menu *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));
+extern struct menu rootmenu;
+
+bool menu_is_empty(struct menu *menu);
+bool menu_is_visible(struct menu *menu);
+bool menu_has_prompt(struct menu *menu);
+const char * menu_get_prompt(struct menu *menu);
+struct menu * menu_get_root_menu(struct menu *menu);
+struct menu * menu_get_parent_menu(struct menu *menu);
+bool menu_has_help(struct menu *menu);
+const char * menu_get_help(struct menu *menu);
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
+void menu_get_ext_help(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));
+extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
+
+struct symbol * sym_lookup(const char *name, int flags);
+struct symbol * sym_find(const char *name);
+const char * sym_escape_string_value(const char *in);
+struct symbol ** sym_re_search(const char *pattern);
+const char * sym_type_name(enum symbol_type type);
+void sym_calc_value(struct symbol *sym);
+enum symbol_type sym_get_type(struct symbol *sym);
+bool sym_tristate_within_range(struct symbol *sym,tristate tri);
+bool sym_set_tristate_value(struct symbol *sym,tristate tri);
+tristate sym_toggle_tristate_value(struct symbol *sym);
+bool sym_string_valid(struct symbol *sym, const char *newval);
+bool sym_string_within_range(struct symbol *sym, const char *str);
+bool sym_set_string_value(struct symbol *sym, const char *newval);
+bool sym_is_changable(struct symbol *sym);
+struct property * sym_get_choice_prop(struct symbol *sym);
+const char * sym_get_string_value(struct symbol *sym);
+
+const char * prop_get_type_name(enum prop_type type);
+
+/* preprocess.c */
+enum variable_flavor {
+ VAR_SIMPLE,
+ VAR_RECURSIVE,
+ VAR_APPEND,
+};
+void env_write_dep(FILE *f, const char *auto_conf_name);
+void variable_add(const char *name, const char *value,
+ enum variable_flavor flavor);
+void variable_all_del(void);
+char *expand_string(const char *in);
+char *expand_dollar(const char **str);
+char *expand_one_token(const char **str);
/* 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));
+void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
deleted file mode 100755
index 5075ebf2d3..0000000000
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/sh
-# Check ncurses compatibility
-
-# What library to link
-ldflags()
-{
- pkg-config --libs ncursesw 2>/dev/null && exit
- pkg-config --libs ncurses 2>/dev/null && exit
- 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 pkg-config --cflags ncursesw 2>/dev/null; then
- echo '-DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1'
- elif pkg-config --cflags ncurses 2>/dev/null; then
- echo '-DCURSES_LOC="<ncurses.h>"'
- elif [ -f /usr/include/ncursesw/curses.h ]; then
- echo '-I/usr/include/ncursesw -DCURSES_LOC="<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="<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
index 8d016faa28..2e96323ad1 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -103,8 +103,8 @@ 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);
+ print_button(dialog, "Select", y, x, selected == 0);
+ print_button(dialog, " Help ", y, x + 14, selected == 1);
wmove(dialog, y, x + 1 + 14 * selected);
wrefresh(dialog);
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index fcffd5b41f..0b00be5aba 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -26,16 +26,10 @@
#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
+#include <ncurses.h>
/*
* Colors in ncurses 1.9.9e do not work properly since foreground and
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
index d58de1dc53..fe82ff6d74 100644
--- a/scripts/kconfig/lxdialog/inputbox.c
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -31,8 +31,8 @@ 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);
+ print_button(dialog, " Ok ", y, x, selected == 0);
+ print_button(dialog, " Help ", y, x + 14, selected == 1);
wmove(dialog, y, x + 1 + 14 * selected);
wrefresh(dialog);
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index 11ae9ad7ac..d70cab3613 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -157,11 +157,11 @@ 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);
+ print_button(win, "Select", y, x, selected == 0);
+ print_button(win, " Exit ", y, x + 12, selected == 1);
+ print_button(win, " Help ", y, x + 24, selected == 2);
+ print_button(win, " Save ", y, x + 36, selected == 3);
+ print_button(win, " Load ", y, x + 48, selected == 4);
wmove(win, y, x + 1 + 12 * selected);
wrefresh(win);
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
index 1773319b95..88d2818ed9 100644
--- a/scripts/kconfig/lxdialog/textbox.c
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -129,7 +129,7 @@ do_resize:
print_title(dialog, title, width);
- print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
+ print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
wnoutrefresh(dialog);
getyx(dialog, cur_y, cur_x); /* Save cursor position */
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c
index 676fb2f824..cd1223c903 100644
--- a/scripts/kconfig/lxdialog/yesno.c
+++ b/scripts/kconfig/lxdialog/yesno.c
@@ -29,8 +29,8 @@ 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);
+ print_button(dialog, " Yes ", y, x, selected == 0);
+ print_button(dialog, " No ", y, x + 13, selected == 1);
wmove(dialog, y, x + 1 + 13 * selected);
wrefresh(dialog);
diff --git a/scripts/kconfig/mconf-cfg.sh b/scripts/kconfig/mconf-cfg.sh
new file mode 100755
index 0000000000..c812872d7f
--- /dev/null
+++ b/scripts/kconfig/mconf-cfg.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+PKG="ncursesw"
+PKG2="ncurses"
+
+if [ -n "$(command -v pkg-config)" ]; then
+ if pkg-config --exists $PKG; then
+ echo cflags=\"$(pkg-config --cflags $PKG)\"
+ echo libs=\"$(pkg-config --libs $PKG)\"
+ exit 0
+ fi
+
+ if pkg-config --exists $PKG2; then
+ echo cflags=\"$(pkg-config --cflags $PKG2)\"
+ echo libs=\"$(pkg-config --libs $PKG2)\"
+ exit 0
+ fi
+fi
+
+# Check the default paths in case pkg-config is not installed.
+# (Even if it is installed, some distributions such as openSUSE cannot
+# find ncurses by pkg-config.)
+if [ -f /usr/include/ncursesw/ncurses.h ]; then
+ echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
+ echo libs=\"-lncursesw\"
+ exit 0
+fi
+
+if [ -f /usr/include/ncurses/ncurses.h ]; then
+ echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
+ echo libs=\"-lncurses\"
+ exit 0
+fi
+
+if [ -f /usr/include/ncurses.h ]; then
+ echo cflags=\"-D_GNU_SOURCE\"
+ echo libs=\"-lncurses\"
+ exit 0
+fi
+
+echo >&2 "*"
+echo >&2 "* Unable to find the ncurses package."
+echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
+echo >&2 "* depending on your distribution)."
+echo >&2 "*"
+exit 1
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 14cea7463a..143c05fec1 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -17,12 +17,11 @@
#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_(
+static const char mconf_readme[] =
"Overview\n"
"--------\n"
"This interface lets you select features and parameters for the build.\n"
@@ -171,37 +170,37 @@ static const char mconf_readme[] = N_(
" blackbg => selects a color scheme with black background\n"
" classic => theme with blue background. The classic look\n"
" bluetitle => an LCD friendly version of classic. (default)\n"
-"\n"),
-menu_instructions[] = N_(
+"\n",
+menu_instructions[] =
"Arrow keys navigate the menu. "
"<Enter> selects submenus ---> (or empty 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_(
+ "Legend: [*] built-in [ ] excluded <M> module < > module capable",
+radiolist_instructions[] =
"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_(
+ "Press <?> for additional information about this option.",
+inputbox_instructions_int[] =
"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_(
+ "Use the <TAB> key to move from the input field to the buttons below it.",
+inputbox_instructions_hex[] =
"Please enter a hexadecimal value. "
- "Use the <TAB> key to move from the input field to the buttons below it."),
-inputbox_instructions_string[] = N_(
+ "Use the <TAB> key to move from the input field to the buttons below it.",
+inputbox_instructions_string[] =
"Please enter a string value. "
- "Use the <TAB> key to move from the input field to the buttons below it."),
-setmod_text[] = N_(
+ "Use the <TAB> key to move from the input field to the buttons below it.",
+setmod_text[] =
"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_(
+ "As a result, this feature will be built as a module.",
+load_config_text[] =
"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_(
+ "last retrieved. Leave blank to abort.",
+load_config_help[] =
"\n"
"For various reasons, one may wish to keep several different\n"
"configurations available on a single machine.\n"
@@ -211,11 +210,11 @@ load_config_help[] = 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_(
+ "configuration files. You should therefore leave this blank to abort.\n",
+save_config_text[] =
"Enter a filename to which this configuration should be saved "
- "as an alternate. Leave blank to abort."),
-save_config_help[] = N_(
+ "as an alternate. Leave blank to abort.",
+save_config_help[] =
"\n"
"For various reasons, one may wish to keep different configurations\n"
"available on a single machine.\n"
@@ -225,8 +224,8 @@ save_config_help[] = 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_(
+ "leave this blank.\n",
+search_help[] =
"\n"
"Search for symbols and display their relations.\n"
"Regular expressions are allowed.\n"
@@ -246,7 +245,7 @@ search_help[] = N_(
" Selected by: BAR [=n]\n"
"-----------------------------------------------------------------\n"
"o The line 'Type:' shows the type of the configuration option for\n"
- " this symbol (boolean, tristate, string, ...)\n"
+ " this symbol (bool, 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 tells at what file / line number the symbol\n"
@@ -271,7 +270,7 @@ search_help[] = 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");
+ "\n";
static int indent;
static struct menu *current_menu;
@@ -279,6 +278,7 @@ static int child_count;
static int single_menu_mode;
static int show_all_options;
static int save_and_exit;
+static int silent;
static void conf(struct menu *menu, struct menu *active_menu);
static void conf_choice(struct menu *menu);
@@ -330,10 +330,10 @@ static void set_subtitle(void)
list_for_each_entry(sp, &trail, entries) {
if (sp->text) {
if (pos) {
- pos->next = xcalloc(sizeof(*pos), 1);
+ pos->next = xcalloc(1, sizeof(*pos));
pos = pos->next;
} else {
- subtitles = pos = xcalloc(sizeof(*pos), 1);
+ subtitles = pos = xcalloc(1, sizeof(*pos));
}
pos->text = sp->text;
}
@@ -399,19 +399,19 @@ static void search_conf(void)
struct subtitle_part stpart;
title = str_new();
- str_printf( &title, _("Enter (sub)string or regexp to search for "
- "(with or without \"%s\")"), CONFIG_);
+ str_printf( &title, "Enter (sub)string or regexp to search for "
+ "(with or without \"%s\")", CONFIG_);
again:
dialog_clear();
- dres = dialog_inputbox(_("Search Configuration Parameter"),
+ dres = dialog_inputbox("Search Configuration Parameter",
str_get(&title),
10, 75, "");
switch (dres) {
case 0:
break;
case 1:
- show_helptext(_("Search Configuration"), search_help);
+ show_helptext("Search Configuration", search_help);
goto again;
default:
str_free(&title);
@@ -442,7 +442,7 @@ again:
res = get_relations_str(sym_arr, &head);
set_subtitle();
- dres = show_textbox_ext(_("Search Results"), (char *)
+ dres = show_textbox_ext("Search Results", (char *)
str_get(&res), 0, 0, keys, &vscroll,
&hscroll, &update_text, (void *)
&data);
@@ -490,7 +490,6 @@ static void build_conf(struct menu *menu)
switch (prop->type) {
case P_MENU:
child_count++;
- prompt = _(prompt);
if (single_menu_mode) {
item_make("%s%*c%s",
menu->data ? "-->" : "++>",
@@ -507,7 +506,7 @@ static void build_conf(struct menu *menu)
case P_COMMENT:
if (prompt) {
child_count++;
- item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt));
+ item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
item_set_tag(':');
item_set_data(menu);
}
@@ -515,7 +514,7 @@ static void build_conf(struct menu *menu)
default:
if (prompt) {
child_count++;
- item_make("---%*c%s", indent + 1, ' ', _(prompt));
+ item_make("---%*c%s", indent + 1, ' ', prompt);
item_set_tag(':');
item_set_data(menu);
}
@@ -559,10 +558,10 @@ static void build_conf(struct menu *menu)
item_set_data(menu);
}
- item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
+ item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
if (val == yes) {
if (def_menu) {
- item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
+ item_add_str(" (%s)", menu_get_prompt(def_menu));
item_add_str(" --->");
if (def_menu->list) {
indent += 2;
@@ -574,7 +573,7 @@ static void build_conf(struct menu *menu)
}
} else {
if (menu == current_menu) {
- item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
+ item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
item_set_tag(':');
item_set_data(menu);
goto conf_childs;
@@ -617,17 +616,17 @@ static void build_conf(struct menu *menu)
tmp = indent - tmp + 4;
if (tmp < 0)
tmp = 0;
- item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
+ item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
- "" : _(" (NEW)"));
+ "" : " (NEW)");
item_set_tag('s');
item_set_data(menu);
goto conf_childs;
}
}
- item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
+ item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
- "" : _(" (NEW)"));
+ "" : " (NEW)");
if (menu->prompt->type == P_MENU) {
item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
return;
@@ -664,8 +663,8 @@ static void conf(struct menu *menu, struct menu *active_menu)
break;
set_subtitle();
dialog_clear();
- res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
- _(menu_instructions),
+ res = dialog_menu(prompt ? prompt : "Main Menu",
+ menu_instructions,
active_menu, &s_scroll);
if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
break;
@@ -707,7 +706,7 @@ static void conf(struct menu *menu, struct menu *active_menu)
show_help(submenu);
else {
reset_subtitle();
- show_helptext(_("README"), _(mconf_readme));
+ show_helptext("README", mconf_readme);
}
break;
case 3:
@@ -772,15 +771,14 @@ 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)
+static void conf_message_callback(const char *s)
{
- 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);
+ if (save_and_exit) {
+ if (!silent)
+ printf("%s", s);
+ } else {
+ show_textbox(NULL, s, 6, 60);
+ }
}
static void show_help(struct menu *menu)
@@ -790,13 +788,13 @@ static void show_help(struct menu *menu)
help.max_width = getmaxx(stdscr) - 10;
menu_get_ext_help(menu, &help);
- show_helptext(_(menu_get_prompt(menu)), str_get(&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));
+ const char *prompt = menu_get_prompt(menu);
struct menu *child;
struct symbol *active;
@@ -811,9 +809,9 @@ static void conf_choice(struct menu *menu)
if (!menu_is_visible(child))
continue;
if (child->sym)
- item_make("%s", _(menu_get_prompt(child)));
+ item_make("%s", menu_get_prompt(child));
else {
- item_make("*** %s ***", _(menu_get_prompt(child)));
+ item_make("*** %s ***", menu_get_prompt(child));
item_set_tag(':');
}
item_set_data(child);
@@ -823,8 +821,8 @@ static void conf_choice(struct menu *menu)
item_set_tag('X');
}
dialog_clear();
- res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
- _(radiolist_instructions),
+ res = dialog_checklist(prompt ? prompt : "Main Menu",
+ radiolist_instructions,
MENUBOX_HEIGTH_MIN,
MENUBOX_WIDTH_MIN,
CHECKLIST_HEIGTH_MIN);
@@ -865,26 +863,26 @@ static void conf_string(struct menu *menu)
switch (sym_get_type(menu->sym)) {
case S_INT:
- heading = _(inputbox_instructions_int);
+ heading = inputbox_instructions_int;
break;
case S_HEX:
- heading = _(inputbox_instructions_hex);
+ heading = inputbox_instructions_hex;
break;
case S_STRING:
- heading = _(inputbox_instructions_string);
+ heading = inputbox_instructions_string;
break;
default:
- heading = _("Internal mconf error!");
+ heading = "Internal mconf error!";
}
dialog_clear();
- res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
+ res = dialog_inputbox(prompt ? prompt : "Main Menu",
heading, 10, 75,
sym_get_string_value(menu->sym));
switch (res) {
case 0:
if (sym_set_string_value(menu->sym, dialog_input_result))
return;
- show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
+ show_textbox(NULL, "You have made an invalid entry.", 5, 43);
break;
case 1:
show_help(menu);
@@ -912,10 +910,10 @@ static void conf_load(void)
sym_set_change_count(1);
return;
}
- show_textbox(NULL, _("File does not exist!"), 5, 38);
+ show_textbox(NULL, "File does not exist!", 5, 38);
break;
case 1:
- show_helptext(_("Load Alternate Configuration"), load_config_help);
+ show_helptext("Load Alternate Configuration", load_config_help);
break;
case KEY_ESC:
return;
@@ -938,10 +936,10 @@ static void conf_save(void)
set_config_filename(dialog_input_result);
return;
}
- show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
+ show_textbox(NULL, "Can't create file! Probably a nonexistent directory.", 5, 60);
break;
case 1:
- show_helptext(_("Save Alternate Configuration"), save_config_help);
+ show_helptext("Save Alternate Configuration", save_config_help);
break;
case KEY_ESC:
return;
@@ -958,8 +956,8 @@ static int handle_exit(void)
dialog_clear();
if (conf_get_changed())
res = dialog_yesno(NULL,
- _("Do you wish to save your new configuration?\n"
- "(Press <ESC><ESC> to continue kernel configuration.)"),
+ "Do you wish to save your new configuration?\n"
+ "(Press <ESC><ESC> to continue kernel configuration.)",
6, 60);
else
res = -1;
@@ -969,24 +967,27 @@ static int handle_exit(void)
switch (res) {
case 0:
if (conf_write(filename)) {
- fprintf(stderr, _("\n\n"
+ fprintf(stderr, "\n\n"
"Error while writing of the configuration.\n"
"Your configuration changes were NOT saved."
- "\n\n"));
+ "\n\n");
return 1;
}
+ conf_write_autoconf(0);
/* fall through */
case -1:
- printf(_("\n\n"
- "*** End of the configuration.\n"
- "*** Execute 'make' to start the build or try 'make help'."
- "\n\n"));
+ if (!silent)
+ 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 (!silent)
+ fprintf(stderr, "\n\n"
+ "Your configuration changes were NOT saved."
+ "\n\n");
if (res != KEY_ESC)
res = 0;
}
@@ -1004,12 +1005,14 @@ int main(int ac, char **av)
char *mode;
int res;
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
signal(SIGINT, sig_handler);
+ if (ac > 1 && strcmp(av[1], "-s") == 0) {
+ silent = 1;
+ /* Silence conf_read() until the real callback is set up */
+ conf_set_message_callback(NULL);
+ av++;
+ }
conf_parse(av[1]);
conf_read(NULL);
@@ -1020,8 +1023,8 @@ int main(int ac, char **av)
}
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"));
+ fprintf(stderr, "Your display is too small to run Menuconfig!\n");
+ fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
return 1;
}
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 584e0fc10d..4cf15d449c 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -62,13 +62,8 @@ void menu_add_entry(struct symbol *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 = &current_entry->list;
return current_menu = current_entry;
}
@@ -79,19 +74,23 @@ void menu_end_menu(void)
current_menu = current_menu->parent;
}
-static struct expr *menu_check_dep(struct expr *e)
+/*
+ * Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running
+ * without modules
+ */
+static struct expr *rewrite_m(struct expr *e)
{
if (!e)
return e;
switch (e->type) {
case E_NOT:
- e->left.expr = menu_check_dep(e->left.expr);
+ e->left.expr = rewrite_m(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);
+ e->left.expr = rewrite_m(e->left.expr);
+ e->right.expr = rewrite_m(e->right.expr);
break;
case E_SYMBOL:
/* change 'm' into 'm' && MODULES */
@@ -106,7 +105,7 @@ static struct expr *menu_check_dep(struct expr *e)
void menu_add_dep(struct expr *dep)
{
- current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
+ current_entry->dep = expr_alloc_and(current_entry->dep, dep);
}
void menu_set_type(int type)
@@ -125,13 +124,13 @@ void menu_set_type(int type)
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)
+static 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);
+ prop->visible.expr = dep;
if (prompt) {
if (isspace(*prompt)) {
@@ -213,9 +212,7 @@ void menu_add_option(int token, char *arg)
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);
+ sym_defconfig_list->flags |= SYMBOL_NO_WRITE;
break;
case T_OPT_ALLNOCONFIG_Y:
current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
@@ -233,6 +230,8 @@ static void sym_check_prop(struct symbol *sym)
{
struct property *prop;
struct symbol *sym2;
+ char *use;
+
for (prop = sym->prop; prop; prop = prop->next) {
switch (prop->type) {
case P_DEFAULT:
@@ -250,20 +249,32 @@ static void sym_check_prop(struct symbol *sym)
"'%s': number is invalid",
sym->name);
}
+ if (sym_is_choice(sym)) {
+ struct property *choice_prop =
+ sym_get_choice_prop(sym2);
+
+ if (!choice_prop ||
+ prop_get_symbol(choice_prop) != sym)
+ prop_warn(prop,
+ "choice default symbol '%s' is not contained in the choice",
+ sym2->name);
+ }
break;
case P_SELECT:
+ case P_IMPLY:
+ use = prop->type == P_SELECT ? "select" : "imply";
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);
+ "config symbol '%s' uses %s, but is "
+ "not bool or tristate", sym->name, use);
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);
+ "'%s' has wrong type. '%s' only "
+ "accept arguments of bool and "
+ "tristate type", sym2->name, use);
break;
case P_RANGE:
if (sym->type != S_INT && sym->type != S_HEX)
@@ -288,6 +299,11 @@ void menu_finalize(struct menu *parent)
sym = parent->sym;
if (parent->list) {
+ /*
+ * This menu node has children. We (recursively) process them
+ * and propagate parent dependencies before moving on.
+ */
+
if (sym && sym_is_choice(sym)) {
if (sym->type == S_UNKNOWN) {
/* find the first choice value to find out choice type */
@@ -305,65 +321,169 @@ void menu_finalize(struct menu *parent)
if (menu->sym && menu->sym->type == S_UNKNOWN)
menu_set_type(sym->type);
}
+
+ /*
+ * Use the choice itself as the parent dependency of
+ * the contained items. This turns the mode of the
+ * choice into an upper bound on the visibility of the
+ * choice value symbols.
+ */
parentdep = expr_alloc_symbol(sym);
} else if (parent->prompt)
+ /* Menu node for 'menu' */
parentdep = parent->prompt->visible.expr;
else
+ /* Menu node for 'if' */
parentdep = parent->dep;
+ /* For each child menu node... */
for (menu = parent->list; menu; menu = menu->next) {
- basedep = expr_transform(menu->dep);
+ /*
+ * Propagate parent dependencies to the child menu
+ * node, also rewriting and simplifying expressions
+ */
+ basedep = rewrite_m(menu->dep);
+ basedep = expr_transform(basedep);
basedep = expr_alloc_and(expr_copy(parentdep), basedep);
basedep = expr_eliminate_dups(basedep);
menu->dep = basedep;
+
if (menu->sym)
+ /*
+ * Note: For symbols, all prompts are included
+ * too in the symbol's own property list
+ */
prop = menu->sym->prop;
else
+ /*
+ * For non-symbol menu nodes, we just need to
+ * handle the prompt
+ */
prop = menu->prompt;
+
+ /* For each property... */
for (; prop; prop = prop->next) {
if (prop->menu != menu)
+ /*
+ * Two possibilities:
+ *
+ * 1. The property lacks dependencies
+ * and so isn't location-specific,
+ * e.g. an 'option'
+ *
+ * 2. The property belongs to a symbol
+ * defined in multiple locations and
+ * is from some other location. It
+ * will be handled there in that
+ * case.
+ *
+ * Skip the property.
+ */
continue;
- dep = expr_transform(prop->visible.expr);
+
+ /*
+ * Propagate parent dependencies to the
+ * property's condition, rewriting and
+ * simplifying expressions at the same time
+ */
+ dep = rewrite_m(prop->visible.expr);
+ dep = expr_transform(dep);
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;
+
+ /*
+ * Handle selects and implies, which modify the
+ * dependencies of the selected/implied symbol
+ */
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)));
+ } else if (prop->type == P_IMPLY) {
+ struct symbol *es = prop_get_symbol(prop);
+ es->implied.expr = expr_alloc_or(es->implied.expr,
+ expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
}
}
}
+
+ if (sym && sym_is_choice(sym))
+ expr_free(parentdep);
+
+ /*
+ * Recursively process children in the same fashion before
+ * moving on
+ */
for (menu = parent->list; menu; menu = menu->next)
menu_finalize(menu);
} else if (sym) {
+ /*
+ * Automatic submenu creation. If sym is a symbol and A, B, C,
+ * ... are consecutive items (symbols, menus, ifs, etc.) that
+ * all depend on sym, then the following menu structure is
+ * created:
+ *
+ * sym
+ * +-A
+ * +-B
+ * +-C
+ * ...
+ *
+ * This also works recursively, giving the following structure
+ * if A is a symbol and B depends on A:
+ *
+ * sym
+ * +-A
+ * | +-B
+ * +-C
+ * ...
+ */
+
basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
basedep = expr_eliminate_dups(expr_transform(basedep));
+
+ /* Examine consecutive elements after sym */
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))
+ /* No dependency, quit */
break;
if (expr_depends_symbol(dep, sym))
+ /* Absolute dependency, put in submenu */
goto next;
+
+ /*
+ * Also consider it a dependency on sym if our
+ * dependencies contain sym and are a "superset" of
+ * sym's dependencies, e.g. '(sym || Q) && R' when sym
+ * depends on R.
+ *
+ * Note that 'R' might be from an enclosing menu or if,
+ * making this a more common case than it might seem.
+ */
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)) {
+ /* Not superset, quit */
expr_free(dep2);
break;
}
+ /* Superset, put in submenu */
expr_free(dep2);
next:
menu_finalize(menu);
menu->parent = parent;
last_menu = menu;
}
+ expr_free(basedep);
if (last_menu) {
parent->list = parent->next;
parent->next = last_menu->next;
@@ -412,6 +532,35 @@ void menu_finalize(struct menu *parent)
*ep = expr_alloc_one(E_LIST, NULL);
(*ep)->right.sym = menu->sym;
}
+
+ /*
+ * This code serves two purposes:
+ *
+ * (1) Flattening 'if' blocks, which do not specify a submenu
+ * and only add dependencies.
+ *
+ * (Automatic submenu creation might still create a submenu
+ * from an 'if' before this code runs.)
+ *
+ * (2) "Undoing" any automatic submenus created earlier below
+ * promptless symbols.
+ *
+ * Before:
+ *
+ * A
+ * if ... (or promptless symbol)
+ * +-B
+ * +-C
+ * D
+ *
+ * After:
+ *
+ * A
+ * if ... (or promptless symbol)
+ * B
+ * C
+ * D
+ */
if (menu->list && (!menu->prompt || !menu->prompt->text)) {
for (last_menu = menu->list; ; last_menu = last_menu->next) {
last_menu->parent = parent;
@@ -436,6 +585,15 @@ void menu_finalize(struct menu *parent)
sym->flags |= SYMBOL_WARNED;
}
+ /*
+ * For non-optional choices, add a reverse dependency (corresponding to
+ * a select) of '<visibility> && m'. This prevents the user from
+ * setting the choice mode to 'n' when the choice is visible.
+ *
+ * This would also work for non-choice symbols, but only non-optional
+ * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented
+ * as a type of symbol.
+ */
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,
@@ -477,7 +635,7 @@ bool menu_is_visible(struct menu *menu)
if (menu->visibility) {
if (expr_calc_value(menu->visibility) == no)
- return no;
+ return false;
}
sym = menu->sym;
@@ -550,7 +708,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
struct menu *submenu[8], *menu, *location = NULL;
struct jump_key *jump = NULL;
- str_printf(r, _("Prompt: %s\n"), _(prop->text));
+ str_printf(r, "Prompt: %s\n", prop->text);
menu = prop->menu->parent;
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
bool accessible = menu_is_visible(menu);
@@ -583,16 +741,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
}
if (i > 0) {
- str_printf(r, _(" Location:\n"));
+ str_printf(r, " Location:\n");
for (j = 4; --i >= 0; j += 2) {
menu = submenu[i];
- if (head && location && menu == location)
+ if (jump && menu == location)
jump->offset = strlen(r->s);
str_printf(r, "%*c-> %s", j, ' ',
- _(menu_get_prompt(menu)));
+ menu_get_prompt(menu));
if (menu->sym) {
str_printf(r, " (%s [=%s])", menu->sym->name ?
- menu->sym->name : _("<choice>"),
+ menu->sym->name : "<choice>",
sym_get_string_value(menu->sym));
}
str_append(r, "\n");
@@ -612,13 +770,30 @@ static struct property *get_symbol_prop(struct symbol *sym)
return prop;
}
+static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
+ enum prop_type tok, const char *prefix)
+{
+ bool hit = false;
+ struct property *prop;
+
+ for_all_properties(sym, prop, tok) {
+ if (!hit) {
+ str_append(r, prefix);
+ hit = true;
+ } else
+ str_printf(r, " && ");
+ expr_gstr_print(prop->expr, r);
+ }
+ if (hit)
+ str_append(r, "\n");
+}
+
/*
* head is optional and may be NULL
*/
-void get_symbol_str(struct gstr *r, struct symbol *sym,
+static void get_symbol_str(struct gstr *r, struct symbol *sym,
struct list_head *head)
{
- bool hit;
struct property *prop;
if (sym && sym->name) {
@@ -639,31 +814,29 @@ void get_symbol_str(struct gstr *r, struct symbol *sym,
prop = get_symbol_prop(sym);
if (prop) {
- str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
+ 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: "));
+ str_append(r, " Depends on: ");
expr_gstr_print(prop->visible.expr, r);
str_append(r, "\n");
}
}
- 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");
+ get_symbol_props_str(r, sym, P_SELECT, " Selects: ");
if (sym->rev_dep.expr) {
- str_append(r, _(" Selected by: "));
- expr_gstr_print(sym->rev_dep.expr, r);
- str_append(r, "\n");
+ expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n");
+ expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n");
+ expr_gstr_print_revdep(sym->rev_dep.expr, r, no, " Selected by [n]:\n");
}
+
+ get_symbol_props_str(r, sym, P_IMPLY, " Implies: ");
+ if (sym->implied.expr) {
+ expr_gstr_print_revdep(sym->implied.expr, r, yes, " Implied by [y]:\n");
+ expr_gstr_print_revdep(sym->implied.expr, r, mod, " Implied by [m]:\n");
+ expr_gstr_print_revdep(sym->implied.expr, r, no, " Implied by [n]:\n");
+ }
+
str_append(r, "\n\n");
}
@@ -676,7 +849,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
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"));
+ str_append(&res, "No matches found.\n");
return res;
}
@@ -691,7 +864,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
help_text = menu_get_help(menu);
}
- str_printf(help, "%s\n", _(help_text));
+ 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
index 81b0c61bb9..0ef9064996 100755
--- a/scripts/kconfig/merge_config.sh
+++ b/scripts/kconfig/merge_config.sh
@@ -32,13 +32,16 @@ usage() {
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"
+ echo " -O dir to put generated output files. Consider setting \$KCONFIG_CONFIG instead."
+ echo
+ echo "Used prefix: '$CONFIG_PREFIX'. You can redefine it with \$CONFIG_ environment variable."
}
-MAKE=true
+RUNMAKE=true
ALLTARGET=alldefconfig
WARNREDUN=false
OUTPUT=.
+CONFIG_PREFIX=${CONFIG_-CONFIG_}
while true; do
case $1 in
@@ -48,7 +51,7 @@ while true; do
continue
;;
"-m")
- MAKE=false
+ RUNMAKE=false
shift
continue
;;
@@ -77,44 +80,66 @@ while true; do
esac
done
+if [ "$#" -lt 1 ] ; then
+ usage
+ exit
+fi
+
+if [ -z "$KCONFIG_CONFIG" ]; then
+ if [ "$OUTPUT" != . ]; then
+ KCONFIG_CONFIG=$(readlink -m -- "$OUTPUT/.config")
+ else
+ KCONFIG_CONFIG=.config
+ fi
+fi
+
INITFILE=$1
shift;
+if [ ! -r "$INITFILE" ]; then
+ echo "The base file '$INITFILE' does not exist. Exit." >&2
+ exit 1
+fi
+
MERGE_LIST=$*
-SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p"
+SED_CONFIG_EXP1="s/^\(${CONFIG_PREFIX}[a-zA-Z0-9_]*\)=.*/\1/p"
+SED_CONFIG_EXP2="s/^# \(${CONFIG_PREFIX}[a-zA-Z0-9_]*\) is not set$/\1/p"
+
TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
echo "Using $INITFILE as base"
cat $INITFILE > $TMP_FILE
-# Merge files, printing warnings on overrided values
+# Merge files, printing warnings on overridden values
for MERGE_FILE in $MERGE_LIST ; do
echo "Merging $MERGE_FILE"
- CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE)
+ if [ ! -r "$MERGE_FILE" ]; then
+ echo "The merge file '$MERGE_FILE' does not exist. Exit." >&2
+ exit 1
+ fi
+ CFG_LIST=$(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $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
+ grep -q -w $CFG $TMP_FILE || continue
+ 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
+ elif [ "$WARNREDUN" = "true" ]; then
echo Value of $CFG is redundant by fragment $MERGE_FILE:
- fi
- sed -i "/$CFG[ =]/d" $TMP_FILE
fi
+ sed -i "/$CFG[ =]/d" $TMP_FILE
done
cat $MERGE_FILE >> $TMP_FILE
done
-if [ "$MAKE" = "false" ]; then
- cp $TMP_FILE $OUTPUT/.config
+if [ "$RUNMAKE" = "false" ]; then
+ cp -T -- "$TMP_FILE" "$KCONFIG_CONFIG"
echo "#"
- echo "# merged configuration written to $OUTPUT/.config (needs make)"
+ echo "# merged configuration written to $KCONFIG_CONFIG (needs make)"
echo "#"
clean_up
exit
@@ -135,10 +160,10 @@ make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET
# Check all specified config values took (might have missed-dependency issues)
-for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do
+for CFG in $(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $TMP_FILE); do
REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
- ACTUAL_VAL=$(grep -w -e "$CFG" $OUTPUT/.config)
+ ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG")
if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
echo "Value requested for $CFG not in final .config"
echo "Requested value: $REQUESTED_VAL"
diff --git a/scripts/kconfig/nconf-cfg.sh b/scripts/kconfig/nconf-cfg.sh
new file mode 100644
index 0000000000..001559ef0a
--- /dev/null
+++ b/scripts/kconfig/nconf-cfg.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+PKG="ncursesw menuw panelw"
+PKG2="ncurses menu panel"
+
+if [ -n "$(command -v pkg-config)" ]; then
+ if pkg-config --exists $PKG; then
+ echo cflags=\"$(pkg-config --cflags $PKG)\"
+ echo libs=\"$(pkg-config --libs $PKG)\"
+ exit 0
+ fi
+
+ if pkg-config --exists $PKG2; then
+ echo cflags=\"$(pkg-config --cflags $PKG2)\"
+ echo libs=\"$(pkg-config --libs $PKG2)\"
+ exit 0
+ fi
+fi
+
+# Check the default paths in case pkg-config is not installed.
+# (Even if it is installed, some distributions such as openSUSE cannot
+# find ncurses by pkg-config.)
+if [ -f /usr/include/ncursesw/ncurses.h ]; then
+ echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
+ echo libs=\"-lncursesw -lmenuw -lpanelw\"
+ exit 0
+fi
+
+if [ -f /usr/include/ncurses/ncurses.h ]; then
+ echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
+ echo libs=\"-lncurses -lmenu -lpanel\"
+ exit 0
+fi
+
+if [ -f /usr/include/ncurses.h ]; then
+ echo cflags=\"-D_GNU_SOURCE\"
+ echo libs=\"-lncurses -lmenu -lpanel\"
+ exit 0
+fi
+
+echo >&2 "*"
+echo >&2 "* Unable to find the ncurses package."
+echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
+echo >&2 "* depending on your distribution)."
+echo >&2 "*"
+exit 1
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 984489ef2b..1ef232ae5a 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -5,7 +5,9 @@
* Derived from menuconfig.
*
*/
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
#include <string.h>
#include <stdlib.h>
@@ -13,7 +15,7 @@
#include "nconf.h"
#include <ctype.h>
-static const char nconf_global_help[] = N_(
+static const char nconf_global_help[] =
"Help windows\n"
"------------\n"
"o Global help: Unless in a data entry window, pressing <F1> will give \n"
@@ -128,8 +130,8 @@ static const char nconf_global_help[] = N_(
"\n"
"Note that this mode can eventually be a little more CPU expensive than\n"
"the default mode, especially with a larger number of unfolded submenus.\n"
-"\n"),
-menu_no_f_instructions[] = N_(
+"\n",
+menu_no_f_instructions[] =
"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
"\n"
@@ -145,8 +147,8 @@ menu_no_f_instructions[] = N_(
"You do not have function keys support.\n"
"Press <1> instead of <F1>, <2> instead of <F2>, etc.\n"
"For verbose global help use key <1>.\n"
-"For help related to the current menu entry press <?> or <h>.\n"),
-menu_instructions[] = N_(
+"For help related to the current menu entry press <?> or <h>.\n",
+menu_instructions[] =
"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
"\n"
@@ -161,30 +163,30 @@ menu_instructions[] = N_(
"\n"
"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n"
"For verbose global help press <F1>.\n"
-"For help related to the current menu entry press <?> or <h>.\n"),
-radiolist_instructions[] = N_(
+"For help related to the current menu entry press <?> or <h>.\n",
+radiolist_instructions[] =
"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n"
"with <Space>.\n"
"For help related to the current entry press <?> or <h>.\n"
-"For global help press <F1>.\n"),
-inputbox_instructions_int[] = N_(
+"For global help press <F1>.\n",
+inputbox_instructions_int[] =
"Please enter a decimal value.\n"
"Fractions will not be accepted.\n"
-"Press <Enter> to apply, <Esc> to cancel."),
-inputbox_instructions_hex[] = N_(
+"Press <Enter> to apply, <Esc> to cancel.",
+inputbox_instructions_hex[] =
"Please enter a hexadecimal value.\n"
-"Press <Enter> to apply, <Esc> to cancel."),
-inputbox_instructions_string[] = N_(
+"Press <Enter> to apply, <Esc> to cancel.",
+inputbox_instructions_string[] =
"Please enter a string value.\n"
-"Press <Enter> to apply, <Esc> to cancel."),
-setmod_text[] = N_(
+"Press <Enter> to apply, <Esc> to cancel.",
+setmod_text[] =
"This feature depends on another feature which has been configured as a\n"
-"module. As a result, the current feature will be built as a module too."),
-load_config_text[] = N_(
+"module. As a result, the current feature will be built as a module too.",
+load_config_text[] =
"Enter the name of the configuration file you wish to load.\n"
"Accept the name shown to restore the configuration you last\n"
-"retrieved. Leave empty to abort."),
-load_config_help[] = N_(
+"retrieved. Leave empty to abort.",
+load_config_help[] =
"For various reasons, one may wish to keep several different\n"
"configurations available on a single machine.\n"
"\n"
@@ -192,11 +194,11 @@ load_config_help[] = N_(
"default one, entering its name here will allow you to load and modify\n"
"that configuration.\n"
"\n"
-"Leave empty to abort.\n"),
-save_config_text[] = N_(
+"Leave empty to abort.\n",
+save_config_text[] =
"Enter a filename to which this configuration should be saved\n"
-"as an alternate. Leave empty to abort."),
-save_config_help[] = N_(
+"as an alternate. Leave empty to abort.",
+save_config_help[] =
"For various reasons, one may wish to keep several different\n"
"configurations available on a single machine.\n"
"\n"
@@ -204,8 +206,8 @@ save_config_help[] = N_(
"and use the current configuration as an alternate to whatever\n"
"configuration options you have selected at that time.\n"
"\n"
-"Leave empty to abort.\n"),
-search_help[] = N_(
+"Leave empty to abort.\n",
+search_help[] =
"Search for symbols (configuration variable names CONFIG_*) and display\n"
"their relations. Regular expressions are supported.\n"
"Example: Search for \"^FOO\".\n"
@@ -242,7 +244,7 @@ search_help[] = N_(
"USB => find all symbols containing USB\n"
"^USB => find all symbols starting with USB\n"
"USB$ => find all symbols ending with USB\n"
-"\n");
+"\n";
struct mitem {
char str[256];
@@ -269,7 +271,7 @@ 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 const char *current_instructions = menu_instructions;
static char *dialog_input_result;
static int dialog_input_result_len;
@@ -303,7 +305,7 @@ struct function_keys {
};
static const int function_keys_num = 9;
-struct function_keys function_keys[] = {
+static struct function_keys function_keys[] = {
{
.key_str = "F1",
.func = "Help",
@@ -386,7 +388,7 @@ static void print_function_line(void)
static void handle_f1(int *key, struct menu *current_item)
{
show_scroll_win(main_window,
- _("Global help"), _(nconf_global_help));
+ "Global help", nconf_global_help);
return;
}
@@ -401,8 +403,8 @@ static void handle_f2(int *key, struct menu *current_item)
static void handle_f3(int *key, struct menu *current_item)
{
show_scroll_win(main_window,
- _("Short help"),
- _(current_instructions));
+ "Short help",
+ current_instructions);
return;
}
@@ -410,7 +412,7 @@ static void handle_f3(int *key, struct menu *current_item)
static void handle_f4(int *key, struct menu *current_item)
{
int res = btn_dialog(main_window,
- _("Show all symbols?"),
+ "Show all symbols?",
2,
" <Show All> ",
"<Don't show all>");
@@ -506,7 +508,7 @@ static int get_mext_match(const char *match_str, match_f flag)
index = (index + items_num) % items_num;
while (true) {
char *str = k_menu_items[index].str;
- if (strcasestr(str, match_str) != 0)
+ if (strcasestr(str, match_str) != NULL)
return index;
if (flag == FIND_NEXT_MATCH_UP ||
flag == MATCH_TINKER_PATTERN_UP)
@@ -651,8 +653,8 @@ static int do_exit(void)
return 0;
}
res = btn_dialog(main_window,
- _("Do you wish to save your new configuration?\n"
- "<ESC> to cancel and resume nconfig."),
+ "Do you wish to save your new configuration?\n"
+ "<ESC> to cancel and resume nconfig.",
2,
" <save> ",
"<don't save>");
@@ -668,15 +670,16 @@ static int do_exit(void)
if (res)
btn_dialog(
main_window,
- _("Error during writing of configuration.\n"
- "Your configuration changes were NOT saved."),
+ "Error during writing of configuration.\n"
+ "Your configuration changes were NOT saved.",
1,
"<OK>");
+ conf_write_autoconf(0);
break;
default:
btn_dialog(
main_window,
- _("Your configuration changes were NOT saved."),
+ "Your configuration changes were NOT saved.",
1,
"<OK>");
break;
@@ -695,12 +698,12 @@ static void search_conf(void)
int dres;
title = str_new();
- str_printf( &title, _("Enter (sub)string or regexp to search for "
- "(with or without \"%s\")"), CONFIG_);
+ str_printf( &title, "Enter (sub)string or regexp to search for "
+ "(with or without \"%s\")", CONFIG_);
again:
dres = dialog_inputbox(main_window,
- _("Search Configuration Parameter"),
+ "Search Configuration Parameter",
str_get(&title),
"", &dialog_input_result, &dialog_input_result_len);
switch (dres) {
@@ -708,7 +711,7 @@ again:
break;
case 1:
show_scroll_win(main_window,
- _("Search Configuration"), search_help);
+ "Search Configuration", search_help);
goto again;
default:
str_free(&title);
@@ -724,7 +727,7 @@ again:
res = get_relations_str(sym_arr, NULL);
free(sym_arr);
show_scroll_win(main_window,
- _("Search Results"), str_get(&res));
+ "Search Results", str_get(&res));
str_free(&res);
str_free(&title);
}
@@ -752,7 +755,7 @@ static void build_conf(struct menu *menu)
switch (ptype) {
case P_MENU:
child_count++;
- prompt = _(prompt);
+ prompt = prompt;
if (single_menu_mode) {
item_make(menu, 'm',
"%s%*c%s",
@@ -773,7 +776,7 @@ static void build_conf(struct menu *menu)
item_make(menu, ':',
" %*c*** %s ***",
indent + 1, ' ',
- _(prompt));
+ prompt);
}
break;
default:
@@ -781,7 +784,7 @@ static void build_conf(struct menu *menu)
child_count++;
item_make(menu, ':', "---%*c%s",
indent + 1, ' ',
- _(prompt));
+ prompt);
}
}
} else
@@ -827,11 +830,11 @@ static void build_conf(struct menu *menu)
}
item_add_str("%*c%s", indent + 1,
- ' ', _(menu_get_prompt(menu)));
+ ' ', menu_get_prompt(menu));
if (val == yes) {
if (def_menu) {
item_add_str(" (%s)",
- _(menu_get_prompt(def_menu)));
+ menu_get_prompt(def_menu));
item_add_str(" --->");
if (def_menu->list) {
indent += 2;
@@ -845,7 +848,7 @@ static void build_conf(struct menu *menu)
if (menu == current_menu) {
item_make(menu, ':',
"---%*c%s", indent + 1,
- ' ', _(menu_get_prompt(menu)));
+ ' ', menu_get_prompt(menu));
goto conf_childs;
}
child_count++;
@@ -892,17 +895,17 @@ static void build_conf(struct menu *menu)
if (tmp < 0)
tmp = 0;
item_add_str("%*c%s%s", tmp, ' ',
- _(menu_get_prompt(menu)),
+ menu_get_prompt(menu),
(sym_has_value(sym) ||
!sym_is_changable(sym)) ? "" :
- _(" (NEW)"));
+ " (NEW)");
goto conf_childs;
}
}
item_add_str("%*c%s%s", indent + 1, ' ',
- _(menu_get_prompt(menu)),
+ menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
- "" : _(" (NEW)"));
+ "" : " (NEW)");
if (menu->prompt && menu->prompt->type == P_MENU) {
item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
return;
@@ -1065,7 +1068,7 @@ static int do_match(int key, struct match_state *state, int *ans)
static void conf(struct menu *menu)
{
- struct menu *submenu = 0;
+ struct menu *submenu = NULL;
const char *prompt = menu_get_prompt(menu);
struct symbol *sym;
int res;
@@ -1084,8 +1087,8 @@ static void conf(struct menu *menu)
if (!child_count)
break;
- show_menu(prompt ? _(prompt) : _("Main Menu"),
- _(menu_instructions),
+ show_menu(prompt ? prompt : "Main Menu",
+ menu_instructions,
current_index, &last_top_row);
keypad((menu_win(curses_menu)), TRUE);
while (!global_exit) {
@@ -1208,12 +1211,9 @@ static void conf(struct menu *menu)
}
}
-static void conf_message_callback(const char *fmt, va_list ap)
+static void conf_message_callback(const char *s)
{
- char buf[1024];
-
- vsnprintf(buf, sizeof(buf), fmt, ap);
- btn_dialog(main_window, buf, 1, "<OK>");
+ btn_dialog(main_window, s, 1, "<OK>");
}
static void show_help(struct menu *menu)
@@ -1225,14 +1225,14 @@ static void show_help(struct menu *menu)
help = str_new();
menu_get_ext_help(menu, &help);
- show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&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;
+ const char *prompt = menu_get_prompt(menu);
+ struct menu *child = NULL;
struct symbol *active;
int selected_index = 0;
int last_top_row = 0;
@@ -1254,13 +1254,13 @@ static void conf_choice(struct menu *menu)
if (child->sym == sym_get_choice_value(menu->sym))
item_make(child, ':', "<X> %s",
- _(menu_get_prompt(child)));
+ menu_get_prompt(child));
else if (child->sym)
item_make(child, ':', " %s",
- _(menu_get_prompt(child)));
+ menu_get_prompt(child));
else
item_make(child, ':', "*** %s ***",
- _(menu_get_prompt(child)));
+ menu_get_prompt(child));
if (child->sym == active){
last_top_row = top_row(curses_menu);
@@ -1268,8 +1268,8 @@ static void conf_choice(struct menu *menu)
}
i++;
}
- show_menu(prompt ? _(prompt) : _("Choice Menu"),
- _(radiolist_instructions),
+ show_menu(prompt ? prompt : "Choice Menu",
+ radiolist_instructions,
selected_index,
&last_top_row);
while (!global_exit) {
@@ -1356,19 +1356,19 @@ static void conf_string(struct menu *menu)
switch (sym_get_type(menu->sym)) {
case S_INT:
- heading = _(inputbox_instructions_int);
+ heading = inputbox_instructions_int;
break;
case S_HEX:
- heading = _(inputbox_instructions_hex);
+ heading = inputbox_instructions_hex;
break;
case S_STRING:
- heading = _(inputbox_instructions_string);
+ heading = inputbox_instructions_string;
break;
default:
- heading = _("Internal nconf error!");
+ heading = "Internal nconf error!";
}
res = dialog_inputbox(main_window,
- prompt ? _(prompt) : _("Main Menu"),
+ prompt ? prompt : "Main Menu",
heading,
sym_get_string_value(menu->sym),
&dialog_input_result,
@@ -1379,7 +1379,7 @@ static void conf_string(struct menu *menu)
dialog_input_result))
return;
btn_dialog(main_window,
- _("You have made an invalid entry."), 0);
+ "You have made an invalid entry.", 0);
break;
case 1:
show_help(menu);
@@ -1408,11 +1408,11 @@ static void conf_load(void)
sym_set_change_count(1);
return;
}
- btn_dialog(main_window, _("File does not exist!"), 0);
+ btn_dialog(main_window, "File does not exist!", 0);
break;
case 1:
show_scroll_win(main_window,
- _("Load Alternate Configuration"),
+ "Load Alternate Configuration",
load_config_help);
break;
case KEY_EXIT:
@@ -1439,13 +1439,13 @@ static void conf_save(void)
set_config_filename(dialog_input_result);
return;
}
- btn_dialog(main_window, _("Can't create file! "
- "Probably a nonexistent directory."),
+ 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 Alternate Configuration",
save_config_help);
break;
case KEY_EXIT:
@@ -1454,7 +1454,7 @@ static void conf_save(void)
}
}
-void setup_windows(void)
+static void setup_windows(void)
{
int lines, columns;
@@ -1478,10 +1478,11 @@ int main(int ac, char **av)
int lines, columns;
char *mode;
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
+ if (ac > 1 && strcmp(av[1], "-s") == 0) {
+ /* Silence conf_read() until the real callback is set up */
+ conf_set_message_callback(NULL);
+ av++;
+ }
conf_parse(av[1]);
conf_read(NULL);
@@ -1534,8 +1535,8 @@ int main(int ac, char **av)
/* check for KEY_FUNC(1) */
if (has_key(KEY_F(1)) == FALSE) {
show_scroll_win(main_window,
- _("Instructions"),
- _(menu_no_f_instructions));
+ "Instructions",
+ menu_no_f_instructions);
}
conf_set_message_callback(conf_message_callback);
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
index 8275f0e551..88874acfda 100644
--- a/scripts/kconfig/nconf.gui.c
+++ b/scripts/kconfig/nconf.gui.c
@@ -6,6 +6,7 @@
*
*/
#include "nconf.h"
+#include "lkc.h"
/* a list of all the different widgets we use */
attributes_t attributes[ATTR_MAX+1] = {0};
@@ -129,7 +130,7 @@ static void no_colors_theme(void)
mkattrn(FUNCTION_TEXT, A_REVERSE);
}
-void set_colors()
+void set_colors(void)
{
start_color();
use_default_colors();
@@ -192,7 +193,7 @@ const char *get_line(const char *text, int line_no)
int lines = 0;
if (!text)
- return 0;
+ return NULL;
for (i = 0; text[i] != '\0' && lines < line_no; i++)
if (text[i] == '\n')
@@ -364,15 +365,17 @@ int dialog_inputbox(WINDOW *main_window,
WINDOW *prompt_win;
WINDOW *form_win;
PANEL *panel;
- int i, x, y;
+ int i, x, y, lines, columns, win_lines, win_cols;
int res = -1;
int cursor_position = strlen(init);
int cursor_form_win;
char *result = *resultp;
+ getmaxyx(stdscr, lines, columns);
+
if (strlen(init)+1 > *result_len) {
*result_len = strlen(init)+1;
- *resultp = result = realloc(result, *result_len);
+ *resultp = result = xrealloc(result, *result_len);
}
/* find the widest line of msg: */
@@ -386,14 +389,19 @@ int dialog_inputbox(WINDOW *main_window,
if (title)
prompt_width = max(prompt_width, strlen(title));
+ win_lines = min(prompt_lines+6, lines-2);
+ win_cols = min(prompt_width+7, columns-2);
+ prompt_lines = max(win_lines-6, 0);
+ prompt_width = max(win_cols-7, 0);
+
/* place dialog in middle of screen */
- y = (getmaxy(stdscr)-(prompt_lines+4))/2;
- x = (getmaxx(stdscr)-(prompt_width+4))/2;
+ y = (lines-win_lines)/2;
+ x = (columns-win_cols)/2;
strncpy(result, init, *result_len);
/* create the windows */
- win = newwin(prompt_lines+6, prompt_width+7, y, x);
+ win = newwin(win_lines, win_cols, 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);
diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h
index 0d5261705e..2b9e19f603 100644
--- a/scripts/kconfig/nconf.h
+++ b/scripts/kconfig/nconf.h
@@ -14,8 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <locale.h>
-#include <curses.h>
+#include <ncurses.h>
#include <menu.h>
#include <panel.h>
#include <form.h>
@@ -24,8 +23,6 @@
#include <time.h>
#include <sys/time.h>
-#include "ncurses.h"
-
#define max(a, b) ({\
typeof(a) _a = a;\
typeof(b) _b = b;\
diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c
new file mode 100644
index 0000000000..5ca2df790d
--- /dev/null
+++ b/scripts/kconfig/preprocess.c
@@ -0,0 +1,572 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "list.h"
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+static char *expand_string_with_args(const char *in, int argc, char *argv[]);
+
+static void __attribute__((noreturn)) pperror(const char *format, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s:%d: ", current_file->name, yylineno);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+
+ exit(1);
+}
+
+/*
+ * Environment variables
+ */
+static LIST_HEAD(env_list);
+
+struct env {
+ char *name;
+ char *value;
+ struct list_head node;
+};
+
+static void env_add(const char *name, const char *value)
+{
+ struct env *e;
+
+ e = xmalloc(sizeof(*e));
+ e->name = xstrdup(name);
+ e->value = xstrdup(value);
+
+ list_add_tail(&e->node, &env_list);
+}
+
+static void env_del(struct env *e)
+{
+ list_del(&e->node);
+ free(e->name);
+ free(e->value);
+ free(e);
+}
+
+/* The returned pointer must be freed when done */
+static char *env_expand(const char *name)
+{
+ struct env *e;
+ const char *value;
+
+ if (!*name)
+ return NULL;
+
+ list_for_each_entry(e, &env_list, node) {
+ if (!strcmp(name, e->name))
+ return xstrdup(e->value);
+ }
+
+ value = getenv(name);
+ if (!value)
+ return NULL;
+
+ /*
+ * We need to remember all referenced environment variables.
+ * They will be written out to include/config/auto.conf.cmd
+ */
+ env_add(name, value);
+
+ return xstrdup(value);
+}
+
+void env_write_dep(FILE *f, const char *autoconfig_name)
+{
+ struct env *e, *tmp;
+
+ list_for_each_entry_safe(e, tmp, &env_list, node) {
+ fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value);
+ fprintf(f, "%s: FORCE\n", autoconfig_name);
+ fprintf(f, "endif\n");
+ env_del(e);
+ }
+}
+
+/*
+ * Built-in functions
+ */
+struct function {
+ const char *name;
+ unsigned int min_args;
+ unsigned int max_args;
+ char *(*func)(int argc, char *argv[]);
+};
+
+static char *do_error_if(int argc, char *argv[])
+{
+ if (!strcmp(argv[0], "y"))
+ pperror("%s", argv[1]);
+
+ return NULL;
+}
+
+static char *do_filename(int argc, char *argv[])
+{
+ return xstrdup(current_file->name);
+}
+
+static char *do_info(int argc, char *argv[])
+{
+ printf("%s\n", argv[0]);
+
+ return xstrdup("");
+}
+
+static char *do_lineno(int argc, char *argv[])
+{
+ char buf[16];
+
+ sprintf(buf, "%d", yylineno);
+
+ return xstrdup(buf);
+}
+
+static char *do_shell(int argc, char *argv[])
+{
+ FILE *p;
+ char buf[256];
+ char *cmd;
+ size_t nread;
+ int i;
+
+ cmd = argv[0];
+
+ p = popen(cmd, "r");
+ if (!p) {
+ perror(cmd);
+ exit(1);
+ }
+
+ nread = fread(buf, 1, sizeof(buf), p);
+ if (nread == sizeof(buf))
+ nread--;
+
+ /* remove trailing new lines */
+ while (nread > 0 && buf[nread - 1] == '\n')
+ nread--;
+
+ buf[nread] = 0;
+
+ /* replace a new line with a space */
+ for (i = 0; i < nread; i++) {
+ if (buf[i] == '\n')
+ buf[i] = ' ';
+ }
+
+ if (pclose(p) == -1) {
+ perror(cmd);
+ exit(1);
+ }
+
+ return xstrdup(buf);
+}
+
+static char *do_warning_if(int argc, char *argv[])
+{
+ if (!strcmp(argv[0], "y"))
+ fprintf(stderr, "%s:%d: %s\n",
+ current_file->name, yylineno, argv[1]);
+
+ return xstrdup("");
+}
+
+static const struct function function_table[] = {
+ /* Name MIN MAX Function */
+ { "error-if", 2, 2, do_error_if },
+ { "filename", 0, 0, do_filename },
+ { "info", 1, 1, do_info },
+ { "lineno", 0, 0, do_lineno },
+ { "shell", 1, 1, do_shell },
+ { "warning-if", 2, 2, do_warning_if },
+};
+
+#define FUNCTION_MAX_ARGS 16
+
+static char *function_expand(const char *name, int argc, char *argv[])
+{
+ const struct function *f;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(function_table); i++) {
+ f = &function_table[i];
+ if (strcmp(f->name, name))
+ continue;
+
+ if (argc < f->min_args)
+ pperror("too few function arguments passed to '%s'",
+ name);
+
+ if (argc > f->max_args)
+ pperror("too many function arguments passed to '%s'",
+ name);
+
+ return f->func(argc, argv);
+ }
+
+ return NULL;
+}
+
+/*
+ * Variables (and user-defined functions)
+ */
+static LIST_HEAD(variable_list);
+
+struct variable {
+ char *name;
+ char *value;
+ enum variable_flavor flavor;
+ int exp_count;
+ struct list_head node;
+};
+
+static struct variable *variable_lookup(const char *name)
+{
+ struct variable *v;
+
+ list_for_each_entry(v, &variable_list, node) {
+ if (!strcmp(name, v->name))
+ return v;
+ }
+
+ return NULL;
+}
+
+static char *variable_expand(const char *name, int argc, char *argv[])
+{
+ struct variable *v;
+ char *res;
+
+ v = variable_lookup(name);
+ if (!v)
+ return NULL;
+
+ if (argc == 0 && v->exp_count)
+ pperror("Recursive variable '%s' references itself (eventually)",
+ name);
+
+ if (v->exp_count > 1000)
+ pperror("Too deep recursive expansion");
+
+ v->exp_count++;
+
+ if (v->flavor == VAR_RECURSIVE)
+ res = expand_string_with_args(v->value, argc, argv);
+ else
+ res = xstrdup(v->value);
+
+ v->exp_count--;
+
+ return res;
+}
+
+void variable_add(const char *name, const char *value,
+ enum variable_flavor flavor)
+{
+ struct variable *v;
+ char *new_value;
+ bool append = false;
+
+ v = variable_lookup(name);
+ if (v) {
+ /* For defined variables, += inherits the existing flavor */
+ if (flavor == VAR_APPEND) {
+ flavor = v->flavor;
+ append = true;
+ } else {
+ free(v->value);
+ }
+ } else {
+ /* For undefined variables, += assumes the recursive flavor */
+ if (flavor == VAR_APPEND)
+ flavor = VAR_RECURSIVE;
+
+ v = xmalloc(sizeof(*v));
+ v->name = xstrdup(name);
+ v->exp_count = 0;
+ list_add_tail(&v->node, &variable_list);
+ }
+
+ v->flavor = flavor;
+
+ if (flavor == VAR_SIMPLE)
+ new_value = expand_string(value);
+ else
+ new_value = xstrdup(value);
+
+ if (append) {
+ v->value = xrealloc(v->value,
+ strlen(v->value) + strlen(new_value) + 2);
+ strcat(v->value, " ");
+ strcat(v->value, new_value);
+ free(new_value);
+ } else {
+ v->value = new_value;
+ }
+}
+
+static void variable_del(struct variable *v)
+{
+ list_del(&v->node);
+ free(v->name);
+ free(v->value);
+ free(v);
+}
+
+void variable_all_del(void)
+{
+ struct variable *v, *tmp;
+
+ list_for_each_entry_safe(v, tmp, &variable_list, node)
+ variable_del(v);
+}
+
+/*
+ * Evaluate a clause with arguments. argc/argv are arguments from the upper
+ * function call.
+ *
+ * Returned string must be freed when done
+ */
+static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
+{
+ char *tmp, *name, *res, *endptr, *prev, *p;
+ int new_argc = 0;
+ char *new_argv[FUNCTION_MAX_ARGS];
+ int nest = 0;
+ int i;
+ unsigned long n;
+
+ tmp = xstrndup(str, len);
+
+ /*
+ * If variable name is '1', '2', etc. It is generally an argument
+ * from a user-function call (i.e. local-scope variable). If not
+ * available, then look-up global-scope variables.
+ */
+ n = strtoul(tmp, &endptr, 10);
+ if (!*endptr && n > 0 && n <= argc) {
+ res = xstrdup(argv[n - 1]);
+ goto free_tmp;
+ }
+
+ prev = p = tmp;
+
+ /*
+ * Split into tokens
+ * The function name and arguments are separated by a comma.
+ * For example, if the function call is like this:
+ * $(foo,$(x),$(y))
+ *
+ * The input string for this helper should be:
+ * foo,$(x),$(y)
+ *
+ * and split into:
+ * new_argv[0] = 'foo'
+ * new_argv[1] = '$(x)'
+ * new_argv[2] = '$(y)'
+ */
+ while (*p) {
+ if (nest == 0 && *p == ',') {
+ *p = 0;
+ if (new_argc >= FUNCTION_MAX_ARGS)
+ pperror("too many function arguments");
+ new_argv[new_argc++] = prev;
+ prev = p + 1;
+ } else if (*p == '(') {
+ nest++;
+ } else if (*p == ')') {
+ nest--;
+ }
+
+ p++;
+ }
+ new_argv[new_argc++] = prev;
+
+ /*
+ * Shift arguments
+ * new_argv[0] represents a function name or a variable name. Put it
+ * into 'name', then shift the rest of the arguments. This simplifies
+ * 'const' handling.
+ */
+ name = expand_string_with_args(new_argv[0], argc, argv);
+ new_argc--;
+ for (i = 0; i < new_argc; i++)
+ new_argv[i] = expand_string_with_args(new_argv[i + 1],
+ argc, argv);
+
+ /* Search for variables */
+ res = variable_expand(name, new_argc, new_argv);
+ if (res)
+ goto free;
+
+ /* Look for built-in functions */
+ res = function_expand(name, new_argc, new_argv);
+ if (res)
+ goto free;
+
+ /* Last, try environment variable */
+ if (new_argc == 0) {
+ res = env_expand(name);
+ if (res)
+ goto free;
+ }
+
+ res = xstrdup("");
+free:
+ for (i = 0; i < new_argc; i++)
+ free(new_argv[i]);
+ free(name);
+free_tmp:
+ free(tmp);
+
+ return res;
+}
+
+/*
+ * Expand a string that follows '$'
+ *
+ * For example, if the input string is
+ * ($(FOO)$($(BAR)))$(BAZ)
+ * this helper evaluates
+ * $($(FOO)$($(BAR)))
+ * and returns a new string containing the expansion (note that the string is
+ * recursively expanded), also advancing 'str' to point to the next character
+ * after the corresponding closing parenthesis, in this case, *str will be
+ * $(BAR)
+ */
+static char *expand_dollar_with_args(const char **str, int argc, char *argv[])
+{
+ const char *p = *str;
+ const char *q;
+ int nest = 0;
+
+ /*
+ * In Kconfig, variable/function references always start with "$(".
+ * Neither single-letter variables as in $A nor curly braces as in ${CC}
+ * are supported. '$' not followed by '(' loses its special meaning.
+ */
+ if (*p != '(') {
+ *str = p;
+ return xstrdup("$");
+ }
+
+ p++;
+ q = p;
+ while (*q) {
+ if (*q == '(') {
+ nest++;
+ } else if (*q == ')') {
+ if (nest-- == 0)
+ break;
+ }
+ q++;
+ }
+
+ if (!*q)
+ pperror("unterminated reference to '%s': missing ')'", p);
+
+ /* Advance 'str' to after the expanded initial portion of the string */
+ *str = q + 1;
+
+ return eval_clause(p, q - p, argc, argv);
+}
+
+char *expand_dollar(const char **str)
+{
+ return expand_dollar_with_args(str, 0, NULL);
+}
+
+static char *__expand_string(const char **str, bool (*is_end)(char c),
+ int argc, char *argv[])
+{
+ const char *in, *p;
+ char *expansion, *out;
+ size_t in_len, out_len;
+
+ out = xmalloc(1);
+ *out = 0;
+ out_len = 1;
+
+ p = in = *str;
+
+ while (1) {
+ if (*p == '$') {
+ in_len = p - in;
+ p++;
+ expansion = expand_dollar_with_args(&p, argc, argv);
+ out_len += in_len + strlen(expansion);
+ out = xrealloc(out, out_len);
+ strncat(out, in, in_len);
+ strcat(out, expansion);
+ free(expansion);
+ in = p;
+ continue;
+ }
+
+ if (is_end(*p))
+ break;
+
+ p++;
+ }
+
+ in_len = p - in;
+ out_len += in_len;
+ out = xrealloc(out, out_len);
+ strncat(out, in, in_len);
+
+ /* Advance 'str' to the end character */
+ *str = p;
+
+ return out;
+}
+
+static bool is_end_of_str(char c)
+{
+ return !c;
+}
+
+/*
+ * Expand variables and functions in the given string. Undefined variables
+ * expand to an empty string.
+ * The returned string must be freed when done.
+ */
+static char *expand_string_with_args(const char *in, int argc, char *argv[])
+{
+ return __expand_string(&in, is_end_of_str, argc, argv);
+}
+
+char *expand_string(const char *in)
+{
+ return expand_string_with_args(in, 0, NULL);
+}
+
+static bool is_end_of_token(char c)
+{
+ /* Why are '.' and '/' valid characters for symbols? */
+ return !(isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/');
+}
+
+/*
+ * Expand variables in a token. The parsing stops when a token separater
+ * (in most cases, it is a whitespace) is encountered. 'str' is updated to
+ * point to the next character.
+ *
+ * The returned string must be freed when done.
+ */
+char *expand_one_token(const char **str)
+{
+ return __expand_string(str, is_end_of_token, 0, NULL);
+}
diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh
new file mode 100755
index 0000000000..02ccc0ae10
--- /dev/null
+++ b/scripts/kconfig/qconf-cfg.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+PKG="Qt5Core Qt5Gui Qt5Widgets"
+PKG2="QtCore QtGui"
+
+if [ -z "$(command -v pkg-config)" ]; then
+ echo >&2 "*"
+ echo >&2 "* 'make xconfig' requires 'pkg-config'. Please install it."
+ echo >&2 "*"
+ exit 1
+fi
+
+if pkg-config --exists $PKG; then
+ echo cflags=\"-std=c++11 -fPIC $(pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets)\"
+ echo libs=\"$(pkg-config --libs $PKG)\"
+ echo moc=\"$(pkg-config --variable=host_bins Qt5Core)/moc\"
+ exit 0
+fi
+
+if pkg-config --exists $PKG2; then
+ echo cflags=\"$(pkg-config --cflags $PKG2)\"
+ echo libs=\"$(pkg-config --libs $PKG2)\"
+ echo moc=\"$(pkg-config --variable=moc_location QtCore)\"
+ exit 0
+fi
+
+echo >&2 "*"
+echo >&2 "* Could not find Qt via pkg-config."
+echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH"
+echo >&2 "*"
+exit 1
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 9d3b04b076..ef4310f255 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -1,32 +1,17 @@
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>
* 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 <QMainWindow>
+#include <QList>
#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 <QAction>
+#include <QFileDialog>
+#include <QMenu>
#include <qapplication.h>
#include <qdesktopwidget.h>
@@ -49,24 +34,15 @@
#include "qconf.moc"
#include "images.c"
-#ifdef _
-# undef _
-# define _ qgettext
-#endif
static QApplication *configApp;
static ConfigSettings *configSettings;
-Q3Action *ConfigMainWindow::saveAction;
+QAction *ConfigMainWindow::saveAction;
static inline QString qgettext(const char* str)
{
- return QString::fromLocal8Bit(gettext(str));
-}
-
-static inline QString qgettext(const QString& str)
-{
- return QString::fromLocal8Bit(gettext(str.latin1()));
+ return QString::fromLocal8Bit(str);
}
ConfigSettings::ConfigSettings()
@@ -77,14 +53,22 @@ ConfigSettings::ConfigSettings()
/**
* Reads a list of integer values from the application settings.
*/
-Q3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
+QList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
{
- Q3ValueList<int> result;
- QStringList entryList = readListEntry(key, ok);
- QStringList::Iterator it;
+ QList<int> result;
+
+ if (contains(key))
+ {
+ QStringList entryList = value(key).toStringList();
+ QStringList::Iterator it;
- for (it = entryList.begin(); it != entryList.end(); ++it)
- result.push_back((*it).toInt());
+ for (it = entryList.begin(); it != entryList.end(); ++it)
+ result.push_back((*it).toInt());
+
+ *ok = true;
+ }
+ else
+ *ok = false;
return result;
}
@@ -92,14 +76,16 @@ Q3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
/**
* Writes a list of integer values to the application settings.
*/
-bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& value)
+bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value)
{
QStringList stringList;
- Q3ValueList<int>::ConstIterator it;
+ QList<int>::ConstIterator it;
for (it = value.begin(); it != value.end(); ++it)
stringList.push_back(QString::number(*it));
- return writeEntry(key, stringList);
+ setValue(key, stringList);
+
+ return true;
}
@@ -109,9 +95,6 @@ bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& valu
*/
void ConfigItem::okRename(int col)
{
- Parent::okRename(col);
- sym_set_string_value(menu->sym, text(dataColIdx).latin1());
- listView()->updateList(this);
}
/*
@@ -135,7 +118,7 @@ void ConfigItem::updateMenu(void)
sym = menu->sym;
prop = menu->prompt;
- prompt = _(menu_get_prompt(menu));
+ prompt = qgettext(menu_get_prompt(menu));
if (prop) switch (prop->type) {
case P_MENU:
@@ -149,11 +132,11 @@ void ConfigItem::updateMenu(void)
} else {
if (sym)
break;
- setPixmap(promptColIdx, 0);
+ setPixmap(promptColIdx, QIcon());
}
goto set_prompt;
case P_COMMENT:
- setPixmap(promptColIdx, 0);
+ setPixmap(promptColIdx, QIcon());
goto set_prompt;
default:
;
@@ -170,7 +153,7 @@ void ConfigItem::updateMenu(void)
char ch;
if (!sym_is_changable(sym) && list->optMode == normalOpt) {
- setPixmap(promptColIdx, 0);
+ setPixmap(promptColIdx, QIcon());
setText(noColIdx, QString::null);
setText(modColIdx, QString::null);
setText(yesColIdx, QString::null);
@@ -216,9 +199,6 @@ void ConfigItem::updateMenu(void)
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);
@@ -227,7 +207,7 @@ void ConfigItem::updateMenu(void)
break;
}
if (!sym_has_value(sym) && visible)
- prompt += _(" (NEW)");
+ prompt += " (NEW)";
set_prompt:
setText(promptColIdx, prompt);
}
@@ -250,18 +230,6 @@ void ConfigItem::testUpdateMenu(bool v)
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
@@ -274,7 +242,7 @@ void ConfigItem::init(void)
menu->data = this;
if (list->mode != fullMode)
- setOpen(TRUE);
+ setExpanded(true);
sym_calc_value(menu->sym);
}
updateMenu();
@@ -299,7 +267,7 @@ ConfigItem::~ConfigItem(void)
ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
: Parent(parent)
{
- connect(this, SIGNAL(lostFocus()), SLOT(hide()));
+ connect(this, SIGNAL(editingFinished()), SLOT(hide()));
}
void ConfigLineEdit::show(ConfigItem* i)
@@ -320,7 +288,7 @@ void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
break;
case Qt::Key_Return:
case Qt::Key_Enter:
- sym_set_string_value(item->menu->sym, text().latin1());
+ sym_set_string_value(item->menu->sym, text().toLatin1());
parent()->updateList(item);
break;
default:
@@ -333,39 +301,39 @@ void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
}
ConfigList::ConfigList(ConfigView* p, const char *name)
- : Parent(p, name),
+ : Parent(p),
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),
+ showName(false), showRange(false), showData(false), mode(singleMode), 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());
+ setObjectName(name);
+ setSortingEnabled(false);
+ setRootIsDecorated(true);
- connect(this, SIGNAL(selectionChanged(void)),
+ setVerticalScrollMode(ScrollPerPixel);
+ setHorizontalScrollMode(ScrollPerPixel);
+
+ setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value");
+
+ connect(this, SIGNAL(itemSelectionChanged(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);
+ showName = configSettings->value("/showName", false).toBool();
+ showRange = configSettings->value("/showRange", false).toBool();
+ showData = configSettings->value("/showData", false).toBool();
+ optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt();
configSettings->endGroup();
connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
}
- for (i = 0; i < colNr; i++)
- colMap[i] = colRevMap[i] = -1;
- addColumn(promptColIdx, _("Option"));
+ addColumn(promptColIdx);
reinit();
}
@@ -390,26 +358,26 @@ void ConfigList::reinit(void)
removeColumn(nameColIdx);
if (showName)
- addColumn(nameColIdx, _("Name"));
+ addColumn(nameColIdx);
if (showRange) {
- addColumn(noColIdx, "N");
- addColumn(modColIdx, "M");
- addColumn(yesColIdx, "Y");
+ addColumn(noColIdx);
+ addColumn(modColIdx);
+ addColumn(yesColIdx);
}
if (showData)
- addColumn(dataColIdx, _("Value"));
+ addColumn(dataColIdx);
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);
+ if (!objectName().isEmpty()) {
+ configSettings->beginGroup(objectName());
+ configSettings->setValue("/showName", showName);
+ configSettings->setValue("/showRange", showRange);
+ configSettings->setValue("/showData", showData);
+ configSettings->setValue("/optionMode", (int)optMode);
configSettings->endGroup();
}
}
@@ -431,7 +399,10 @@ void ConfigList::updateSelection(void)
struct menu *menu;
enum prop_type type;
- ConfigItem* item = (ConfigItem*)selectedItem();
+ if (selectedItems().count() == 0)
+ return;
+
+ ConfigItem* item = (ConfigItem*)selectedItems().first();
if (!item)
return;
@@ -451,21 +422,23 @@ void ConfigList::updateList(ConfigItem* item)
if (!rootEntry) {
if (mode != listMode)
goto update;
- Q3ListViewItemIterator it(this);
+ QTreeWidgetItemIterator it(this);
ConfigItem* item;
- for (; it.current(); ++it) {
- item = (ConfigItem*)it.current();
+ while (*it) {
+ item = (ConfigItem*)(*it);
if (!item->menu)
continue;
item->testUpdateMenu(menu_is_visible(item->menu));
+
+ ++it;
}
return;
}
if (rootEntry != &rootmenu && (mode == singleMode ||
(mode == symbolMode && rootEntry->parent != &rootmenu))) {
- item = firstChild();
+ item = (ConfigItem *)topLevelItem(0);
if (!item)
item = new ConfigItem(this, 0, true);
last = item;
@@ -479,12 +452,14 @@ void ConfigList::updateList(ConfigItem* item)
item->testUpdateMenu(true);
updateMenuList(item, rootEntry);
- triggerUpdate();
+ update();
+ resizeColumnToContents(0);
return;
}
update:
updateMenuList(this, rootEntry);
- triggerUpdate();
+ update();
+ resizeColumnToContents(0);
}
void ConfigList::setValue(ConfigItem* item, tristate val)
@@ -506,7 +481,7 @@ void ConfigList::setValue(ConfigItem* item, tristate val)
if (!sym_set_tristate_value(sym, val))
return;
if (oldval == no && item->menu->list)
- item->setOpen(TRUE);
+ item->setExpanded(true);
parent()->updateList(item);
break;
}
@@ -524,7 +499,7 @@ void ConfigList::changeValue(ConfigItem* item)
sym = menu->sym;
if (!sym) {
if (item->menu->list)
- item->setOpen(!item->isOpen());
+ item->setExpanded(!item->isExpanded());
return;
}
@@ -536,9 +511,9 @@ void ConfigList::changeValue(ConfigItem* item)
newexpr = sym_toggle_tristate_value(sym);
if (item->menu->list) {
if (oldexpr == newexpr)
- item->setOpen(!item->isOpen());
+ item->setExpanded(!item->isExpanded());
else if (oldexpr == no)
- item->setOpen(TRUE);
+ item->setExpanded(true);
}
if (oldexpr != newexpr)
parent()->updateList(item);
@@ -546,10 +521,7 @@ void ConfigList::changeValue(ConfigItem* item)
case S_INT:
case S_HEX:
case S_STRING:
- if (colMap[dataColIdx] >= 0)
- item->startRename(colMap[dataColIdx]);
- else
- parent()->lineEdit->show(item);
+ parent()->lineEdit->show(item);
break;
}
}
@@ -566,8 +538,10 @@ void ConfigList::setRootMenu(struct menu *menu)
updateMenuList(this, 0);
rootEntry = menu;
updateListAll();
- setSelected(currentItem(), hasFocus());
- ensureItemVisible(currentItem());
+ if (currentItem()) {
+ currentItem()->setSelected(hasFocus());
+ scrollToItem(currentItem());
+ }
}
void ConfigList::setParentMenu(void)
@@ -580,13 +554,16 @@ void ConfigList::setParentMenu(void)
return;
setRootMenu(menu_get_parent_menu(rootEntry->parent));
- Q3ListViewItemIterator it(this);
- for (; (item = (ConfigItem*)it.current()); it++) {
+ QTreeWidgetItemIterator it(this);
+ while (*it) {
+ item = (ConfigItem *)(*it);
if (item->menu == oldroot) {
setCurrentItem(item);
- ensureItemVisible(item);
+ scrollToItem(item);
break;
}
+
+ ++it;
}
}
@@ -597,8 +574,7 @@ void ConfigList::setParentMenu(void)
* 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)
+void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
{
struct menu* child;
ConfigItem* item;
@@ -607,8 +583,11 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
enum prop_type type;
if (!menu) {
- while ((item = parent->firstChild()))
- delete item;
+ while (parent->childCount() > 0)
+ {
+ delete parent->takeChild(0);
+ }
+
return;
}
@@ -660,9 +639,74 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
}
}
+void ConfigList::updateMenuList(ConfigList *parent, struct menu* menu)
+{
+ struct menu* child;
+ ConfigItem* item;
+ ConfigItem* last;
+ bool visible;
+ enum prop_type type;
+
+ if (!menu) {
+ while (parent->topLevelItemCount() > 0)
+ {
+ delete parent->takeTopLevelItem(0);
+ }
+
+ return;
+ }
+
+ last = (ConfigItem*)parent->topLevelItem(0);
+ if (last && !last->goParent)
+ last = 0;
+ for (child = menu->list; child; child = child->next) {
+ item = last ? last->nextSibling() : (ConfigItem*)parent->topLevelItem(0);
+ 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 = (ConfigItem*)parent->topLevelItem(0);
+ if (last == item)
+ last = 0;
+ else while (last->nextSibling() != item)
+ last = last->nextSibling();
+ delete item;
+ }
+ }
+}
+
void ConfigList::keyPressEvent(QKeyEvent* ev)
{
- Q3ListViewItem* i = currentItem();
+ QTreeWidgetItem* i = currentItem();
ConfigItem* item;
struct menu *menu;
enum prop_type type;
@@ -714,20 +758,20 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
ev->accept();
}
-void ConfigList::contentsMousePressEvent(QMouseEvent* e)
+void ConfigList::mousePressEvent(QMouseEvent* e)
{
//QPoint p(contentsToViewport(e->pos()));
//printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
- Parent::contentsMousePressEvent(e);
+ Parent::mousePressEvent(e);
}
-void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
+void ConfigList::mouseReleaseEvent(QMouseEvent* e)
{
- QPoint p(contentsToViewport(e->pos()));
+ QPoint p = e->pos();
ConfigItem* item = (ConfigItem*)itemAt(p);
struct menu *menu;
enum prop_type ptype;
- const QPixmap* pm;
+ QIcon icon;
int idx, x;
if (!item)
@@ -735,14 +779,13 @@ void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
menu = item->menu;
x = header()->offset() + p.x();
- idx = colRevMap[header()->sectionAt(x)];
+ idx = header()->logicalIndexAt(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()) {
+ icon = item->pixmap(promptColIdx);
+ if (!icon.isNull()) {
+ int off = header()->sectionPosition(0) + visualRect(indexAt(p)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly.
+ if (x >= off && x < off + icon.availableSizes().first().width()) {
if (item->goParent) {
emit parentSelected();
break;
@@ -773,19 +816,19 @@ void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
skip:
//printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
- Parent::contentsMouseReleaseEvent(e);
+ Parent::mouseReleaseEvent(e);
}
-void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
+void ConfigList::mouseMoveEvent(QMouseEvent* e)
{
//QPoint p(contentsToViewport(e->pos()));
//printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
- Parent::contentsMouseMoveEvent(e);
+ Parent::mouseMoveEvent(e);
}
-void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
+void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
{
- QPoint p(contentsToViewport(e->pos()));
+ QPoint p = e->pos(); // TODO: Check if this works(was contentsToViewport).
ConfigItem* item = (ConfigItem*)itemAt(p);
struct menu *menu;
enum prop_type ptype;
@@ -807,7 +850,7 @@ void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
skip:
//printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
- Parent::contentsMouseDoubleClickEvent(e);
+ Parent::mouseDoubleClickEvent(e);
}
void ConfigList::focusInEvent(QFocusEvent *e)
@@ -818,7 +861,7 @@ void ConfigList::focusInEvent(QFocusEvent *e)
ConfigItem* item = (ConfigItem *)currentItem();
if (item) {
- setSelected(item, TRUE);
+ item->setSelected(true);
menu = item->menu;
}
emit gotFocus(menu);
@@ -828,33 +871,33 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
{
if (e->y() <= header()->geometry().bottom()) {
if (!headerPopup) {
- Q3Action *action;
+ QAction *action;
- headerPopup = new Q3PopupMenu(this);
- action = new Q3Action(NULL, _("Show Name"), 0, this);
- action->setToggleAction(TRUE);
+ headerPopup = new QMenu(this);
+ action = new QAction("Show Name", this);
+ action->setCheckable(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);
+ action->setChecked(showName);
+ headerPopup->addAction(action);
+ action = new QAction("Show Range", this);
+ action->setCheckable(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);
+ action->setChecked(showRange);
+ headerPopup->addAction(action);
+ action = new QAction("Show Data", this);
+ action->setCheckable(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);
+ action->setChecked(showData);
+ headerPopup->addAction(action);
}
headerPopup->exec(e->globalPos());
e->accept();
@@ -868,11 +911,17 @@ QAction *ConfigView::showAllAction;
QAction *ConfigView::showPromptAction;
ConfigView::ConfigView(QWidget* parent, const char *name)
- : Parent(parent, name)
+ : Parent(parent)
{
- list = new ConfigList(this, name);
+ setObjectName(name);
+ QVBoxLayout *verticalLayout = new QVBoxLayout(this);
+ verticalLayout->setContentsMargins(0, 0, 0, 0);
+
+ list = new ConfigList(this);
+ verticalLayout->addWidget(list);
lineEdit = new ConfigLineEdit(this);
lineEdit->hide();
+ verticalLayout->addWidget(lineEdit);
this->nextView = viewList;
viewList = this;
@@ -931,10 +980,13 @@ void ConfigView::setShowData(bool b)
void ConfigList::setAllOpen(bool open)
{
- Q3ListViewItemIterator it(this);
+ QTreeWidgetItemIterator it(this);
- for (; it.current(); it++)
- it.current()->setOpen(open);
+ while (*it) {
+ (*it)->setExpanded(open);
+
+ ++it;
+ }
}
void ConfigView::updateList(ConfigItem* item)
@@ -954,11 +1006,14 @@ void ConfigView::updateListAll(void)
}
ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
- : Parent(parent, name), sym(0), _menu(0)
+ : Parent(parent), sym(0), _menu(0)
{
- if (name) {
- configSettings->beginGroup(name);
- _showDebug = configSettings->readBoolEntry("/showDebug", false);
+ setObjectName(name);
+
+
+ if (!objectName().isEmpty()) {
+ configSettings->beginGroup(objectName());
+ setShowDebug(configSettings->value("/showDebug", false).toBool());
configSettings->endGroup();
connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
}
@@ -966,9 +1021,9 @@ ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
void ConfigInfoView::saveSettings(void)
{
- if (name()) {
- configSettings->beginGroup(name());
- configSettings->writeEntry("/showDebug", showDebug());
+ if (!objectName().isEmpty()) {
+ configSettings->beginGroup(objectName());
+ configSettings->setValue("/showDebug", showDebug());
configSettings->endGroup();
}
}
@@ -1022,7 +1077,7 @@ void ConfigInfoView::menuInfo(void)
if (sym) {
if (_menu->prompt) {
head += "<big><b>";
- head += print_filter(_(_menu->prompt->text));
+ head += print_filter(_menu->prompt->text);
head += "</b></big>";
if (sym->name) {
head += " (";
@@ -1053,7 +1108,7 @@ void ConfigInfoView::menuInfo(void)
str_free(&help_gstr);
} else if (_menu->prompt) {
head += "<big><b>";
- head += print_filter(_(_menu->prompt->text));
+ head += print_filter(_menu->prompt->text);
head += "</b></big><br><br>";
if (showDebug()) {
if (_menu->prompt->visible.expr) {
@@ -1088,13 +1143,12 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
case P_PROMPT:
case P_MENU:
debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
- debug += print_filter(_(prop->text));
+ 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);
@@ -1127,8 +1181,8 @@ 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()) {
+ for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
+ switch (res[i].toLatin1()) {
case '<':
res.replace(i, 1, "&lt;");
i += 4;
@@ -1167,37 +1221,42 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
*text += str2;
}
-Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
+QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
{
- Q3PopupMenu* popup = Parent::createPopupMenu(pos);
- Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup);
- action->setToggleAction(TRUE);
+ QMenu* popup = Parent::createStandardContextMenu(pos);
+ QAction* action = new QAction("Show Debug Info", popup);
+ action->setCheckable(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);
+ action->setChecked(showDebug());
+ popup->addSeparator();
+ popup->addAction(action);
return popup;
}
-void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
+void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e)
{
- Parent::contentsContextMenuEvent(e);
+ Parent::contextMenuEvent(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));
+ : Parent(parent), result(NULL)
+{
+ setObjectName(name);
+ setWindowTitle("Search Config");
+
+ QVBoxLayout* layout1 = new QVBoxLayout(this);
+ layout1->setContentsMargins(11, 11, 11, 11);
+ layout1->setSpacing(6);
+ QHBoxLayout* layout2 = new QHBoxLayout(0);
+ layout2->setContentsMargins(0, 0, 0, 0);
+ layout2->setSpacing(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);
+ searchButton = new QPushButton("Search", this);
+ searchButton->setAutoDefault(false);
connect(searchButton, SIGNAL(clicked()), SLOT(search()));
layout2->addWidget(searchButton);
layout1->addLayout(layout2);
@@ -1215,19 +1274,19 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
layout1->addWidget(split);
if (name) {
- int x, y, width, height;
+ QVariant x, y;
+ int width, height;
bool ok;
configSettings->beginGroup(name);
- width = configSettings->readNumEntry("/window width", parent->width() / 2);
- height = configSettings->readNumEntry("/window height", parent->height() / 2);
+ width = configSettings->value("/window width", parent->width() / 2).toInt();
+ height = configSettings->value("/window height", parent->height() / 2).toInt();
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);
+ x = configSettings->value("/window x");
+ y = configSettings->value("/window y");
+ if ((x.isValid())&&(y.isValid()))
+ move(x.toInt(), y.toInt());
+ QList<int> sizes = configSettings->readSizes("/split", &ok);
if (ok)
split->setSizes(sizes);
configSettings->endGroup();
@@ -1237,12 +1296,12 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
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());
+ if (!objectName().isEmpty()) {
+ configSettings->beginGroup(objectName());
+ configSettings->setValue("/window x", pos().x());
+ configSettings->setValue("/window y", pos().y());
+ configSettings->setValue("/window width", size().width());
+ configSettings->setValue("/window height", size().height());
configSettings->writeSizes("/split", split->sizes());
configSettings->endGroup();
}
@@ -1258,7 +1317,7 @@ void ConfigSearchWindow::search(void)
list->list->clear();
info->clear();
- result = sym_re_search(editField->text().latin1());
+ result = sym_re_search(editField->text().toLatin1());
if (!result)
return;
for (p = result; *p; p++) {
@@ -1275,29 +1334,25 @@ ConfigMainWindow::ConfigMainWindow(void)
: searchWindow(0)
{
QMenuBar* menu;
- bool ok;
- int x, y, width, height;
+ bool ok = true;
+ QVariant x, y;
+ int 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);
+ setWindowTitle(title);
- width = configSettings->readNumEntry("/window width", d->width() - 64);
- height = configSettings->readNumEntry("/window height", d->height() - 64);
+ width = configSettings->value("/window width", d->width() - 64).toInt();
+ height = configSettings->value("/window height", d->height() - 64).toInt();
resize(width, height);
- x = configSettings->readNumEntry("/window x", 0, &ok);
- if (ok)
- y = configSettings->readNumEntry("/window y", 0, &ok);
- if (ok)
- move(x, y);
+ x = configSettings->value("/window x");
+ y = configSettings->value("/window y");
+ if ((x.isValid())&&(y.isValid()))
+ move(x.toInt(), y.toInt());
split1 = new QSplitter(this);
split1->setOrientation(Qt::Horizontal);
@@ -1314,127 +1369,116 @@ ConfigMainWindow::ConfigMainWindow(void)
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()));
+ toolBar = new QToolBar("Tools", this);
+ addToolBar(toolBar);
+
+ backAction = new QAction(QPixmap(xpm_back), "Back", this);
+ connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
+ backAction->setEnabled(false);
+ QAction *quitAction = new QAction("&Quit", this);
+ quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
+ connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
+ QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
+ loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
+ connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
+ saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
+ saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
+ connect(saveAction, SIGNAL(triggered(bool)), 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);
+ QAction *saveAsAction = new QAction("Save &As...", this);
+ connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
+ QAction *searchAction = new QAction("&Find", this);
+ searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
+ connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
+ singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
+ singleViewAction->setCheckable(true);
+ connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
+ splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
+ splitViewAction->setCheckable(true);
+ connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
+ fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
+ fullViewAction->setCheckable(true);
+ connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
+
+ QAction *showNameAction = new QAction("Show Name", this);
+ showNameAction->setCheckable(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);
+ showNameAction->setChecked(configView->showName());
+ QAction *showRangeAction = new QAction("Show Range", this);
+ showRangeAction->setCheckable(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);
+ QAction *showDataAction = new QAction("Show Data", this);
+ showDataAction->setCheckable(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,
+ optGroup->setExclusive(true);
+ connect(optGroup, SIGNAL(triggered(QAction*)), configView,
SLOT(setOptionMode(QAction *)));
- connect(optGroup, SIGNAL(selected(QAction *)), menuView,
+ connect(optGroup, SIGNAL(triggered(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);
+ configView->showNormalAction = new QAction("Show Normal Options", optGroup);
+ configView->showAllAction = new QAction("Show All Options", optGroup);
+ configView->showPromptAction = new QAction("Show Prompt Options", optGroup);
+ configView->showNormalAction->setCheckable(true);
+ configView->showAllAction->setCheckable(true);
+ configView->showPromptAction->setCheckable(true);
+
+ QAction *showDebugAction = new QAction("Show Debug Info", this);
+ showDebugAction->setCheckable(true);
connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
- connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
- showDebugAction->setOn(helpText->showDebug());
+ showDebugAction->setChecked(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()));
+ QAction *showIntroAction = new QAction("Introduction", this);
+ connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
+ QAction *showAboutAction = new QAction("About", this);
+ connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
// init tool bar
- backAction->addTo(toolBar);
+ toolBar->addAction(backAction);
toolBar->addSeparator();
- loadAction->addTo(toolBar);
- saveAction->addTo(toolBar);
+ toolBar->addAction(loadAction);
+ toolBar->addAction(saveAction);
toolBar->addSeparator();
- singleViewAction->addTo(toolBar);
- splitViewAction->addTo(toolBar);
- fullViewAction->addTo(toolBar);
+ toolBar->addAction(singleViewAction);
+ toolBar->addAction(splitViewAction);
+ toolBar->addAction(fullViewAction);
// 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);
+ QMenu* config = menu->addMenu("&File");
+ config->addAction(loadAction);
+ config->addAction(saveAction);
+ config->addAction(saveAsAction);
+ config->addSeparator();
+ config->addAction(quitAction);
// create edit menu
- Q3PopupMenu* editMenu = new Q3PopupMenu(this);
- menu->insertItem(_("&Edit"), editMenu);
- searchAction->addTo(editMenu);
+ QMenu* editMenu = menu->addMenu("&Edit");
+ editMenu->addAction(searchAction);
// 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();
+ QMenu* optionMenu = menu->addMenu("&Option");
+ optionMenu->addAction(showNameAction);
+ optionMenu->addAction(showRangeAction);
+ optionMenu->addAction(showDataAction);
+ optionMenu->addSeparator();
+ optionMenu->addActions(optGroup->actions());
+ optionMenu->addSeparator();
+ optionMenu->addAction(showDebugAction);
// create help menu
- Q3PopupMenu* helpMenu = new Q3PopupMenu(this);
- menu->insertSeparator();
- menu->insertItem(_("&Help"), helpMenu);
- showIntroAction->addTo(helpMenu);
- showAboutAction->addTo(helpMenu);
+ menu->addSeparator();
+ QMenu* helpMenu = menu->addMenu("&Help");
+ helpMenu->addAction(showIntroAction);
+ helpMenu->addAction(showAboutAction);
connect(configList, SIGNAL(menuChanged(struct menu *)),
helpText, SLOT(setInfo(struct menu *)));
@@ -1456,7 +1500,7 @@ ConfigMainWindow::ConfigMainWindow(void)
connect(helpText, SIGNAL(menuSelected(struct menu *)),
SLOT(setMenuLink(struct menu *)));
- QString listMode = configSettings->readEntry("/listMode", "symbol");
+ QString listMode = configSettings->value("/listMode", "symbol").toString();
if (listMode == "single")
showSingleView();
else if (listMode == "full")
@@ -1465,7 +1509,7 @@ ConfigMainWindow::ConfigMainWindow(void)
showSplitView();
// UI setup done, restore splitter positions
- Q3ValueList<int> sizes = configSettings->readSizes("/split1", &ok);
+ QList<int> sizes = configSettings->readSizes("/split1", &ok);
if (ok)
split1->setSizes(sizes);
@@ -1476,26 +1520,28 @@ ConfigMainWindow::ConfigMainWindow(void)
void ConfigMainWindow::loadConfig(void)
{
- QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);
+ QString s = QFileDialog::getOpenFileName(this, "", conf_get_configname());
if (s.isNull())
return;
if (conf_read(QFile::encodeName(s)))
- QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
+ 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!"));
+ QMessageBox::information(this, "qconf", "Unable to save configuration!");
return false;
}
+ conf_write_autoconf(0);
+
return true;
}
void ConfigMainWindow::saveConfigAs(void)
{
- QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);
+ QString s = QFileDialog::getSaveFileName(this, "", conf_get_configname());
if (s.isNull())
return;
saveConfig();
@@ -1512,9 +1558,9 @@ void ConfigMainWindow::changeMenu(struct menu *menu)
{
configList->setRootMenu(menu);
if (configList->rootEntry->parent == &rootmenu)
- backAction->setEnabled(FALSE);
+ backAction->setEnabled(false);
else
- backAction->setEnabled(TRUE);
+ backAction->setEnabled(true);
}
void ConfigMainWindow::setMenuLink(struct menu *menu)
@@ -1546,8 +1592,8 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
return;
item = menuList->findConfigItem(parent);
if (item) {
- menuList->setSelected(item, TRUE);
- menuList->ensureItemVisible(item);
+ item->setSelected(true);
+ menuList->scrollToItem(item);
}
list->setRootMenu(parent);
}
@@ -1562,8 +1608,8 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
if (list) {
item = list->findConfigItem(menu);
if (item) {
- list->setSelected(item, TRUE);
- list->ensureItemVisible(item);
+ item->setSelected(true);
+ list->scrollToItem(item);
list->setFocus();
}
}
@@ -1577,15 +1623,21 @@ void ConfigMainWindow::listFocusChanged(void)
void ConfigMainWindow::goBack(void)
{
- ConfigItem* item;
+ ConfigItem* item, *oldSelection;
configList->setParentMenu();
if (configList->rootEntry == &rootmenu)
- backAction->setEnabled(FALSE);
- item = (ConfigItem*)menuList->selectedItem();
+ backAction->setEnabled(false);
+
+ if (menuList->selectedItems().count() == 0)
+ return;
+
+ item = (ConfigItem*)menuList->selectedItems().first();
+ oldSelection = item;
while (item) {
if (item->menu == configList->rootEntry) {
- menuList->setSelected(item, TRUE);
+ oldSelection->setSelected(false);
+ item->setSelected(true);
break;
}
item = (ConfigItem*)item->parent();
@@ -1594,6 +1646,13 @@ void ConfigMainWindow::goBack(void)
void ConfigMainWindow::showSingleView(void)
{
+ singleViewAction->setEnabled(false);
+ singleViewAction->setChecked(true);
+ splitViewAction->setEnabled(true);
+ splitViewAction->setChecked(false);
+ fullViewAction->setEnabled(true);
+ fullViewAction->setChecked(false);
+
menuView->hide();
menuList->setRootMenu(0);
configList->mode = singleMode;
@@ -1601,28 +1660,41 @@ void ConfigMainWindow::showSingleView(void)
configList->updateListAll();
else
configList->setRootMenu(&rootmenu);
- configList->setAllOpen(TRUE);
configList->setFocus();
}
void ConfigMainWindow::showSplitView(void)
{
+ singleViewAction->setEnabled(true);
+ singleViewAction->setChecked(false);
+ splitViewAction->setEnabled(false);
+ splitViewAction->setChecked(true);
+ fullViewAction->setEnabled(true);
+ fullViewAction->setChecked(false);
+
configList->mode = symbolMode;
if (configList->rootEntry == &rootmenu)
configList->updateListAll();
else
configList->setRootMenu(&rootmenu);
- configList->setAllOpen(TRUE);
+ configList->setAllOpen(true);
configApp->processEvents();
menuList->mode = menuMode;
menuList->setRootMenu(&rootmenu);
- menuList->setAllOpen(TRUE);
+ menuList->setAllOpen(true);
menuView->show();
menuList->setFocus();
}
void ConfigMainWindow::showFullView(void)
{
+ singleViewAction->setEnabled(true);
+ singleViewAction->setChecked(false);
+ splitViewAction->setEnabled(true);
+ splitViewAction->setChecked(false);
+ fullViewAction->setEnabled(false);
+ fullViewAction->setChecked(true);
+
menuView->hide();
menuList->setRootMenu(0);
configList->mode = fullMode;
@@ -1630,7 +1702,6 @@ void ConfigMainWindow::showFullView(void)
configList->updateListAll();
else
configList->setRootMenu(&rootmenu);
- configList->setAllOpen(FALSE);
configList->setFocus();
}
@@ -1644,11 +1715,11 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
e->accept();
return;
}
- QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
+ 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"));
+ 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())
@@ -1667,7 +1738,7 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
void ConfigMainWindow::showIntro(void)
{
- static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
+ 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"
@@ -1677,25 +1748,26 @@ void ConfigMainWindow::showIntro(void)
"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");
+ "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@linux-m68k.org>.\n\n"
- "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
+ static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
+ "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\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());
+ configSettings->setValue("/window x", pos().x());
+ configSettings->setValue("/window y", pos().y());
+ configSettings->setValue("/window width", size().width());
+ configSettings->setValue("/window height", size().height());
QString entry;
switch(configList->mode) {
@@ -1714,7 +1786,7 @@ void ConfigMainWindow::saveSettings(void)
default:
break;
}
- configSettings->writeEntry("/listMode", entry);
+ configSettings->setValue("/listMode", entry);
configSettings->writeSizes("/split1", split1->sizes());
configSettings->writeSizes("/split2", split2->sizes());
@@ -1746,7 +1818,7 @@ static const char *progname;
static void usage(void)
{
- printf(_("%s <config>\n"), progname);
+ printf("%s [-s] <config>\n", progname);
exit(0);
}
@@ -1755,13 +1827,13 @@ 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 's':
+ conf_set_message_callback(NULL);
+ break;
case 'h':
case '?':
usage();
@@ -1782,7 +1854,6 @@ int main(int ac, char** av)
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();
@@ -1790,6 +1861,8 @@ int main(int ac, char** av)
configSettings->endGroup();
delete configSettings;
+ delete v;
+ delete configApp;
return 0;
}
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index bde0c6b6f9..a40036d1b0 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -3,26 +3,18 @@
* Released under the terms of the GNU GPL v2.0.
*/
-#if QT_VERSION < 0x040000
-#include <qlistview.h>
-#else
-#include <q3listview.h>
-#endif
+#include <QTextBrowser>
+#include <QTreeWidget>
+#include <QMainWindow>
+#include <QHeaderView>
#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
+#include <QPushButton>
+#include <QSettings>
+#include <QLineEdit>
+#include <QSplitter>
+#include <QCheckBox>
+#include <QDialog>
+#include "expr.h"
class ConfigView;
class ConfigList;
@@ -33,8 +25,8 @@ class ConfigMainWindow;
class ConfigSettings : public QSettings {
public:
ConfigSettings();
- Q3ValueList<int> readSizes(const QString& key, bool *ok);
- bool writeSizes(const QString& key, const Q3ValueList<int>& value);
+ QList<int> readSizes(const QString& key, bool *ok);
+ bool writeSizes(const QString& key, const QList<int>& value);
};
enum colIdx {
@@ -47,9 +39,9 @@ enum optionMode {
normalOpt = 0, allOpt, promptOpt
};
-class ConfigList : public Q3ListView {
+class ConfigList : public QTreeWidget {
Q_OBJECT
- typedef class Q3ListView Parent;
+ typedef class QTreeWidget Parent;
public:
ConfigList(ConfigView* p, const char *name = 0);
void reinit(void);
@@ -61,10 +53,10 @@ public:
protected:
void keyPressEvent(QKeyEvent *e);
- void contentsMousePressEvent(QMouseEvent *e);
- void contentsMouseReleaseEvent(QMouseEvent *e);
- void contentsMouseMoveEvent(QMouseEvent *e);
- void contentsMouseDoubleClickEvent(QMouseEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseDoubleClickEvent(QMouseEvent *e);
void focusInEvent(QFocusEvent *e);
void contextMenuEvent(QContextMenuEvent *e);
@@ -95,32 +87,23 @@ public:
}
ConfigItem* firstChild() const
{
- return (ConfigItem *)Parent::firstChild();
- }
- int mapIdx(colIdx idx)
- {
- return colMap[idx];
+ return (ConfigItem *)children().first();
}
- void addColumn(colIdx idx, const QString& label)
+ void addColumn(colIdx idx)
{
- colMap[idx] = Parent::addColumn(label);
- colRevMap[colMap[idx]] = idx;
+ showColumn(idx);
}
void removeColumn(colIdx idx)
{
- int col = colMap[idx];
- if (col >= 0) {
- Parent::removeColumn(col);
- colRevMap[col] = colMap[idx] = -1;
- }
+ hideColumn(idx);
}
void setAllOpen(bool open);
void setParentMenu(void);
bool menuSkip(struct menu *);
- template <class P>
- void updateMenuList(P*, struct menu*);
+ void updateMenuList(ConfigItem *parent, struct menu*);
+ void updateMenuList(ConfigList *parent, struct menu*);
bool updateAll;
@@ -132,30 +115,26 @@ public:
enum listMode mode;
enum optionMode optMode;
struct menu *rootEntry;
- QColorGroup disabledColorGroup;
- QColorGroup inactivedColorGroup;
- Q3PopupMenu* headerPopup;
-
-private:
- int colMap[colNr];
- int colRevMap[colNr];
+ QPalette disabledColorGroup;
+ QPalette inactivedColorGroup;
+ QMenu* headerPopup;
};
-class ConfigItem : public Q3ListViewItem {
- typedef class Q3ListViewItem Parent;
+class ConfigItem : public QTreeWidgetItem {
+ typedef class QTreeWidgetItem Parent;
public:
- ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v)
- : Parent(parent, after), menu(m), visible(v), goParent(false)
+ ConfigItem(ConfigList *parent, ConfigItem *after, struct menu *m, bool v)
+ : Parent(parent, after), nextItem(0), 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)
+ : Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false)
{
init();
}
- ConfigItem(Q3ListView *parent, ConfigItem *after, bool v)
- : Parent(parent, after), menu(0), visible(v), goParent(true)
+ ConfigItem(ConfigList *parent, ConfigItem *after, bool v)
+ : Parent(parent, after), nextItem(0), menu(0), visible(v), goParent(true)
{
init();
}
@@ -166,33 +145,43 @@ public:
void testUpdateMenu(bool v);
ConfigList* listView() const
{
- return (ConfigList*)Parent::listView();
+ return (ConfigList*)Parent::treeWidget();
}
ConfigItem* firstChild() const
{
- return (ConfigItem *)Parent::firstChild();
+ return (ConfigItem *)Parent::child(0);
}
- ConfigItem* nextSibling() const
+ ConfigItem* nextSibling()
{
- return (ConfigItem *)Parent::nextSibling();
+ ConfigItem *ret = NULL;
+ ConfigItem *_parent = (ConfigItem *)parent();
+
+ if(_parent) {
+ ret = (ConfigItem *)_parent->child(_parent->indexOfChild(this)+1);
+ } else {
+ QTreeWidget *_treeWidget = treeWidget();
+ ret = (ConfigItem *)_treeWidget->topLevelItem(_treeWidget->indexOfTopLevelItem(this)+1);
+ }
+
+ return ret;
}
void setText(colIdx idx, const QString& text)
{
- Parent::setText(listView()->mapIdx(idx), text);
+ Parent::setText(idx, text);
}
QString text(colIdx idx) const
{
- return Parent::text(listView()->mapIdx(idx));
+ return Parent::text(idx);
}
- void setPixmap(colIdx idx, const QPixmap& pm)
+ void setPixmap(colIdx idx, const QIcon &icon)
{
- Parent::setPixmap(listView()->mapIdx(idx), pm);
+ Parent::setIcon(idx, icon);
}
- const QPixmap* pixmap(colIdx idx) const
+ const QIcon pixmap(colIdx idx) const
{
- return Parent::pixmap(listView()->mapIdx(idx));
+ return icon(idx);
}
- void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
+ // TODO: Implement paintCell
ConfigItem* nextItem;
struct menu *menu;
@@ -216,9 +205,9 @@ public:
ConfigItem *item;
};
-class ConfigView : public Q3VBox {
+class ConfigView : public QWidget {
Q_OBJECT
- typedef class Q3VBox Parent;
+ typedef class QWidget Parent;
public:
ConfigView(QWidget* parent, const char *name = 0);
~ConfigView(void);
@@ -249,9 +238,9 @@ public:
static QAction *showPromptAction;
};
-class ConfigInfoView : public Q3TextBrowser {
+class ConfigInfoView : public QTextBrowser {
Q_OBJECT
- typedef class Q3TextBrowser Parent;
+ typedef class QTextBrowser Parent;
public:
ConfigInfoView(QWidget* parent, const char *name = 0);
bool showDebug(void) const { return _showDebug; }
@@ -271,8 +260,8 @@ protected:
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);
+ QMenu *createStandardContextMenu(const QPoint & pos);
+ void contextMenuEvent(QContextMenuEvent *e);
struct symbol *sym;
struct menu *_menu;
@@ -299,10 +288,10 @@ protected:
struct symbol **result;
};
-class ConfigMainWindow : public Q3MainWindow {
+class ConfigMainWindow : public QMainWindow {
Q_OBJECT
- static Q3Action *saveAction;
+ static QAction *saveAction;
static void conf_changed(void);
public:
ConfigMainWindow(void);
@@ -331,8 +320,11 @@ protected:
ConfigView *configView;
ConfigList *configList;
ConfigInfoView *helpText;
- Q3ToolBar *toolBar;
- Q3Action *backAction;
- QSplitter* split1;
- QSplitter* split2;
+ QToolBar *toolBar;
+ QAction *backAction;
+ QAction *singleViewAction;
+ QAction *splitViewAction;
+ QAction *fullViewAction;
+ QSplitter *split1;
+ QSplitter *split2;
};
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index 9cb8522d8d..4686531e2f 100755
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/env perl
#
# Copyright 2005-2009 - Steven Rostedt
# Licensed under the terms of the GNU GPL License version 2
@@ -42,6 +42,7 @@
# mv config_strip .config
# make oldconfig
#
+use warnings;
use strict;
use Getopt::Long;
@@ -137,7 +138,7 @@ my $ksource = ($ARGV[0] ? $ARGV[0] : '.');
my $kconfig = $ARGV[1];
my $lsmod_file = $ENV{'LSMOD'};
-my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
+my @makefiles = `find $ksource -name Makefile -or -name Kbuild 2>/dev/null`;
chomp @makefiles;
my %depends;
@@ -164,10 +165,10 @@ sub read_kconfig {
my $last_source = "";
# Check for any environment variables used
- while ($source =~ /\$(\w+)/ && $last_source ne $source) {
+ while ($source =~ /\$\((\w+)\)/ && $last_source ne $source) {
my $env = $1;
$last_source = $source;
- $source =~ s/\$$env/$ENV{$env}/;
+ $source =~ s/\$\($env\)/$ENV{$env}/;
}
open(my $kinfile, '<', $source) || die "Can't open $kconfig";
@@ -188,7 +189,7 @@ sub read_kconfig {
$cont = 0;
# collect any Kconfig sources
- if (/^source\s*"(.*)"/) {
+ if (/^source\s+"?([^"]+)/) {
my $kconfig = $1;
# prevent reading twice.
if (!defined($read_kconfigs{$kconfig})) {
@@ -237,7 +238,7 @@ sub read_kconfig {
}
# configs without prompts must be selected
- } elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
+ } elsif ($state ne "NONE" && /^\s*(tristate\s+\S|prompt\b)/) {
# note if the config has a prompt
$prompts{$config} = 1;
@@ -256,8 +257,8 @@ sub read_kconfig {
$iflevel-- if ($iflevel);
- # stop on "help"
- } elsif (/^\s*help\s*$/) {
+ # stop on "help" and keywords that end a menu entry
+ } elsif (/^\s*(---)?help(---)?\s*$/ || /^(comment|choice|menu)\b/) {
$state = "NONE";
}
}
@@ -454,7 +455,7 @@ sub parse_config_depends
$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") {
+ if (!defined($orig_configs{$conf}) || $orig_configs{$conf} eq "y") {
next;
}
@@ -610,6 +611,40 @@ foreach my $line (@config_file) {
next;
}
+ if (/CONFIG_MODULE_SIG_KEY="(.+)"/) {
+ my $orig_cert = $1;
+ my $default_cert = "certs/signing_key.pem";
+
+ # Check that the logic in this script still matches the one in Kconfig
+ if (!defined($depends{"MODULE_SIG_KEY"}) ||
+ $depends{"MODULE_SIG_KEY"} !~ /"\Q$default_cert\E"/) {
+ print STDERR "WARNING: MODULE_SIG_KEY assertion failure, ",
+ "update needed to ", __FILE__, " line ", __LINE__, "\n";
+ print;
+ } elsif ($orig_cert ne $default_cert && ! -f $orig_cert) {
+ print STDERR "Module signature verification enabled but ",
+ "module signing key \"$orig_cert\" not found. Resetting ",
+ "signing key to default value.\n";
+ print "CONFIG_MODULE_SIG_KEY=\"$default_cert\"\n";
+ } else {
+ print;
+ }
+ next;
+ }
+
+ if (/CONFIG_SYSTEM_TRUSTED_KEYS="(.+)"/) {
+ my $orig_keys = $1;
+
+ if (! -f $orig_keys) {
+ print STDERR "System keyring enabled but keys \"$orig_keys\" ",
+ "not found. Resetting keys to default value.\n";
+ print "CONFIG_SYSTEM_TRUSTED_KEYS=\"\"\n";
+ } else {
+ print;
+ }
+ next;
+ }
+
if (/^(CONFIG.*)=(m|y)/) {
if (defined($configs{$1})) {
if ($localyesconfig) {
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 7caabdb51c..703b9b899e 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -33,33 +33,6 @@ 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;
@@ -77,7 +50,7 @@ const char *sym_type_name(enum symbol_type type)
{
switch (type) {
case S_BOOLEAN:
- return "boolean";
+ return "bool";
case S_TRISTATE:
return "tristate";
case S_INT:
@@ -103,16 +76,7 @@ struct property *sym_get_choice_prop(struct symbol *sym)
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)
+static struct property *sym_get_default_prop(struct symbol *sym)
{
struct property *prop;
@@ -183,18 +147,52 @@ static void sym_validate_range(struct symbol *sym)
sprintf(str, "%lld", val2);
else
sprintf(str, "0x%llx", val2);
- sym->curr.val = strdup(str);
+ sym->curr.val = xstrdup(str);
+}
+
+static 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;
+ }
+}
+
+static void sym_set_all_changed(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym)
+ sym_set_changed(sym);
}
static void sym_calc_visibility(struct symbol *sym)
{
struct property *prop;
+ struct symbol *choice_sym = NULL;
tristate tri;
/* any prompt visible? */
tri = no;
+
+ if (sym_is_choice_value(sym))
+ choice_sym = prop_get_symbol(sym_get_choice_prop(sym));
+
for_all_prompts(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
+ /*
+ * Tristate choice_values with visibility 'mod' are
+ * not visible if the corresponding choice's value is
+ * 'yes'.
+ */
+ if (choice_sym && sym->type == S_TRISTATE &&
+ prop->visible.tri == mod && choice_sym->curr.tri == yes)
+ prop->visible.tri = no;
+
tri = EXPR_OR(tri, prop->visible.tri);
}
if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
@@ -209,7 +207,7 @@ static void sym_calc_visibility(struct symbol *sym)
tri = yes;
if (sym->dir_dep.expr)
tri = expr_calc_value(sym->dir_dep.expr);
- if (tri == mod)
+ if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
tri = yes;
if (sym->dir_dep.tri != tri) {
sym->dir_dep.tri = tri;
@@ -224,6 +222,15 @@ static void sym_calc_visibility(struct symbol *sym)
sym->rev_dep.tri = tri;
sym_set_changed(sym);
}
+ tri = no;
+ if (sym->implied.expr && sym->dir_dep.tri != no)
+ tri = expr_calc_value(sym->implied.expr);
+ if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ tri = yes;
+ if (sym->implied.tri != tri) {
+ sym->implied.tri = tri;
+ sym_set_changed(sym);
+ }
}
/*
@@ -290,6 +297,27 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
return def_sym;
}
+static void sym_warn_unmet_dep(struct symbol *sym)
+{
+ struct gstr gs = str_new();
+
+ str_printf(&gs,
+ "\nWARNING: unmet direct dependencies detected for %s\n",
+ sym->name);
+ str_printf(&gs,
+ " Depends on [%c]: ",
+ sym->dir_dep.tri == mod ? 'm' : 'n');
+ expr_gstr_print(sym->dir_dep.expr, &gs);
+ str_printf(&gs, "\n");
+
+ expr_gstr_print_revdep(sym->rev_dep.expr, &gs, yes,
+ " Selected by [y]:\n");
+ expr_gstr_print_revdep(sym->rev_dep.expr, &gs, mod,
+ " Selected by [m]:\n");
+
+ fputs(str_get(&gs), stderr);
+}
+
void sym_calc_value(struct symbol *sym)
{
struct symbol_value newval, oldval;
@@ -328,11 +356,13 @@ void sym_calc_value(struct symbol *sym)
sym->curr.tri = no;
return;
}
- if (!sym_is_choice_value(sym))
- sym->flags &= ~SYMBOL_WRITE;
+ sym->flags &= ~SYMBOL_WRITE;
sym_calc_visibility(sym);
+ if (sym->visible != no)
+ sym->flags |= SYMBOL_WRITE;
+
/* set default if recursively called */
sym->curr = newval;
@@ -347,7 +377,6 @@ void sym_calc_value(struct symbol *sym)
/* 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);
@@ -359,38 +388,31 @@ void sym_calc_value(struct symbol *sym)
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);
+ if (newval.tri != no)
+ sym->flags |= SYMBOL_WRITE;
+ }
+ if (sym->implied.tri != no) {
+ sym->flags |= SYMBOL_WRITE;
+ newval.tri = EXPR_OR(newval.tri, sym->implied.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);
- }
+ if (sym->dir_dep.tri < sym->rev_dep.tri)
+ sym_warn_unmet_dep(sym);
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
}
- if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ if (newval.tri == mod &&
+ (sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes))
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;
- }
+ if (sym->visible != no && sym_has_value(sym)) {
+ newval.val = sym->def[S_DEF_USER].val;
+ break;
}
prop = sym_get_default_prop(sym);
if (prop) {
@@ -432,7 +454,7 @@ void sym_calc_value(struct symbol *sym)
}
}
- if (sym->flags & SYMBOL_AUTO)
+ if (sym->flags & SYMBOL_NO_WRITE)
sym->flags &= ~SYMBOL_WRITE;
if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
@@ -447,28 +469,7 @@ void sym_clear_all_valid(void)
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);
+ sym_calc_value(modules_sym);
}
bool sym_tristate_within_range(struct symbol *sym, tristate val)
@@ -485,6 +486,8 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val)
return false;
if (sym->visible <= sym->rev_dep.tri)
return false;
+ if (sym->implied.tri == yes && val == mod)
+ return false;
if (sym_is_choice_value(sym) && sym->visible == yes)
return val == yes;
return val >= sym->rev_dep.tri && val <= sym->visible;
@@ -737,6 +740,10 @@ const char *sym_get_string_default(struct symbol *sym)
if (sym->type == S_BOOLEAN && val == mod)
val = yes;
+ /* adjust the default value if this symbol is implied by another */
+ if (val < sym->implied.tri)
+ val = sym->implied.tri;
+
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
@@ -818,7 +825,7 @@ struct symbol *sym_lookup(const char *name, int flags)
: !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
return symbol;
}
- new_name = strdup(name);
+ new_name = xstrdup(name);
} else {
new_name = NULL;
hash = 0;
@@ -863,55 +870,6 @@ struct symbol *sym_find(const char *name)
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;
@@ -1028,7 +986,7 @@ struct symbol **sym_re_search(const char *pattern)
}
if (sym_match_arr) {
qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp);
- sym_arr = malloc((cnt+1) * sizeof(struct symbol));
+ sym_arr = malloc((cnt+1) * sizeof(struct symbol *));
if (!sym_arr)
goto sym_re_search_free;
for (i = 0; i < cnt; i++)
@@ -1053,7 +1011,7 @@ static struct dep_stack {
struct dep_stack *prev, *next;
struct symbol *sym;
struct property *prop;
- struct expr *expr;
+ struct expr **expr;
} *check_top;
static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
@@ -1117,35 +1075,52 @@ static void sym_check_print_recursive(struct symbol *last_sym)
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,
+
+ 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>",
- prop_get_type_name(prop->type),
next_sym->name ? next_sym->name : "<choice>");
- } else if (stack->prop) {
+ } 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 if (stack->expr == &sym->dir_dep.expr) {
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,
+ } else if (stack->expr == &sym->rev_dep.expr) {
+ 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>");
- } else if (sym_is_choice_value(sym)) {
- fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
- menu->file->name, menu->lineno,
+ } else if (stack->expr == &sym->implied.expr) {
+ fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
+ prop->file->name, prop->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
+ } else 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 {
- fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
+ fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %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>");
}
}
+ fprintf(stderr,
+ "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"
+ "subsection \"Kconfig recursive dependency limitations\"\n"
+ "\n");
+
if (check_top == &cv_stack)
dep_stack_remove();
}
@@ -1166,6 +1141,10 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
case E_NOT:
return sym_check_expr_deps(e->left.expr);
case E_EQUAL:
+ case E_GEQ:
+ case E_GTH:
+ case E_LEQ:
+ case E_LTH:
case E_UNEQUAL:
sym = sym_check_deps(e->left.sym);
if (sym)
@@ -1176,7 +1155,7 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
default:
break;
}
- printf("Oops! How to check %d?\n", e->type);
+ fprintf(stderr, "Oops! How to check %d?\n", e->type);
return NULL;
}
@@ -1189,12 +1168,26 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
dep_stack_insert(&stack, sym);
+ stack.expr = &sym->dir_dep.expr;
+ sym2 = sym_check_expr_deps(sym->dir_dep.expr);
+ if (sym2)
+ goto out;
+
+ stack.expr = &sym->rev_dep.expr;
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
if (sym2)
goto out;
+ stack.expr = &sym->implied.expr;
+ sym2 = sym_check_expr_deps(sym->implied.expr);
+ if (sym2)
+ goto out;
+
+ stack.expr = NULL;
+
for (prop = sym->prop; prop; prop = prop->next) {
- if (prop->type == P_CHOICE || prop->type == P_SELECT)
+ if (prop->type == P_CHOICE || prop->type == P_SELECT ||
+ prop->type == P_IMPLY)
continue;
stack.prop = prop;
sym2 = sym_check_expr_deps(prop->visible.expr);
@@ -1202,7 +1195,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
break;
if (prop->type != P_DEFAULT || sym_is_choice(sym))
continue;
- stack.expr = prop->expr;
+ stack.expr = &prop->expr;
sym2 = sym_check_expr_deps(prop->expr);
if (sym2)
break;
@@ -1280,9 +1273,6 @@ struct symbol *sym_check_deps(struct symbol *sym)
sym->flags &= ~SYMBOL_CHECK;
}
- if (sym2 && sym2 == sym)
- sym2 = NULL;
-
return sym2;
}
@@ -1321,8 +1311,6 @@ 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:
@@ -1333,6 +1321,8 @@ const char *prop_get_type_name(enum prop_type type)
return "choice";
case P_SELECT:
return "select";
+ case P_IMPLY:
+ return "imply";
case P_RANGE:
return "range";
case P_SYMBOL:
@@ -1342,32 +1332,3 @@ const char *prop_get_type_name(enum prop_type type)
}
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/tests/auto_submenu/Kconfig b/scripts/kconfig/tests/auto_submenu/Kconfig
new file mode 100644
index 0000000000..c17bf2caa7
--- /dev/null
+++ b/scripts/kconfig/tests/auto_submenu/Kconfig
@@ -0,0 +1,50 @@
+config A
+ bool "A"
+ default y
+
+config A0
+ bool "A0"
+ depends on A
+ default y
+ help
+ This depends on A, so should be a submenu of A.
+
+config A0_0
+ bool "A1_0"
+ depends on A0
+ help
+ Submenus are created recursively.
+ This should be a submenu of A0.
+
+config A1
+ bool "A1"
+ depends on A
+ default y
+ help
+ This should line up with A0.
+
+choice
+ prompt "choice"
+ depends on A1
+ help
+ Choice should become a submenu as well.
+
+config A1_0
+ bool "A1_0"
+
+config A1_1
+ bool "A1_1"
+
+endchoice
+
+config B
+ bool "B"
+ help
+ This is independent of A.
+
+config C
+ bool "C"
+ depends on A
+ help
+ This depends on A, but not a consecutive item, so can/should not
+ be a submenu.
diff --git a/scripts/kconfig/tests/auto_submenu/__init__.py b/scripts/kconfig/tests/auto_submenu/__init__.py
new file mode 100644
index 0000000000..32e79b85fa
--- /dev/null
+++ b/scripts/kconfig/tests/auto_submenu/__init__.py
@@ -0,0 +1,12 @@
+"""
+Create submenu for symbols that depend on the preceding one.
+
+If a symbols has dependency on the preceding symbol, the menu entry
+should become the submenu of the preceding one, and displayed with
+deeper indentation.
+"""
+
+
+def test(conf):
+ assert conf.oldaskconfig() == 0
+ assert conf.stdout_contains('expected_stdout')
diff --git a/scripts/kconfig/tests/auto_submenu/expected_stdout b/scripts/kconfig/tests/auto_submenu/expected_stdout
new file mode 100644
index 0000000000..bf5236f39a
--- /dev/null
+++ b/scripts/kconfig/tests/auto_submenu/expected_stdout
@@ -0,0 +1,10 @@
+A (A) [Y/n/?] (NEW)
+ A0 (A0) [Y/n/?] (NEW)
+ A1_0 (A0_0) [N/y/?] (NEW)
+ A1 (A1) [Y/n/?] (NEW)
+ choice
+ > 1. A1_0 (A1_0) (NEW)
+ 2. A1_1 (A1_1) (NEW)
+ choice[1-2?]:
+B (B) [N/y/?] (NEW)
+C (C) [N/y/?] (NEW)
diff --git a/scripts/kconfig/tests/choice/Kconfig b/scripts/kconfig/tests/choice/Kconfig
new file mode 100644
index 0000000000..cc60e9ce2c
--- /dev/null
+++ b/scripts/kconfig/tests/choice/Kconfig
@@ -0,0 +1,54 @@
+config MODULES
+ bool "Enable loadable module support"
+ option modules
+ default y
+
+choice
+ prompt "boolean choice"
+ default BOOL_CHOICE1
+
+config BOOL_CHOICE0
+ bool "choice 0"
+
+config BOOL_CHOICE1
+ bool "choice 1"
+
+endchoice
+
+choice
+ prompt "optional boolean choice"
+ optional
+ default OPT_BOOL_CHOICE1
+
+config OPT_BOOL_CHOICE0
+ bool "choice 0"
+
+config OPT_BOOL_CHOICE1
+ bool "choice 1"
+
+endchoice
+
+choice
+ prompt "tristate choice"
+ default TRI_CHOICE1
+
+config TRI_CHOICE0
+ tristate "choice 0"
+
+config TRI_CHOICE1
+ tristate "choice 1"
+
+endchoice
+
+choice
+ prompt "optional tristate choice"
+ optional
+ default OPT_TRI_CHOICE1
+
+config OPT_TRI_CHOICE0
+ tristate "choice 0"
+
+config OPT_TRI_CHOICE1
+ tristate "choice 1"
+
+endchoice
diff --git a/scripts/kconfig/tests/choice/__init__.py b/scripts/kconfig/tests/choice/__init__.py
new file mode 100644
index 0000000000..9edcc52621
--- /dev/null
+++ b/scripts/kconfig/tests/choice/__init__.py
@@ -0,0 +1,40 @@
+"""
+Basic choice tests.
+
+The handling of 'choice' is a bit complicated part in Kconfig.
+
+The behavior of 'y' choice is intuitive. If choice values are tristate,
+the choice can be 'm' where each value can be enabled independently.
+Also, if a choice is marked as 'optional', the whole choice can be
+invisible.
+"""
+
+
+def test_oldask0(conf):
+ assert conf.oldaskconfig() == 0
+ assert conf.stdout_contains('oldask0_expected_stdout')
+
+
+def test_oldask1(conf):
+ assert conf.oldaskconfig('oldask1_config') == 0
+ assert conf.stdout_contains('oldask1_expected_stdout')
+
+
+def test_allyes(conf):
+ assert conf.allyesconfig() == 0
+ assert conf.config_contains('allyes_expected_config')
+
+
+def test_allmod(conf):
+ assert conf.allmodconfig() == 0
+ assert conf.config_contains('allmod_expected_config')
+
+
+def test_allno(conf):
+ assert conf.allnoconfig() == 0
+ assert conf.config_contains('allno_expected_config')
+
+
+def test_alldef(conf):
+ assert conf.alldefconfig() == 0
+ assert conf.config_contains('alldef_expected_config')
diff --git a/scripts/kconfig/tests/choice/alldef_expected_config b/scripts/kconfig/tests/choice/alldef_expected_config
new file mode 100644
index 0000000000..7a754bf4be
--- /dev/null
+++ b/scripts/kconfig/tests/choice/alldef_expected_config
@@ -0,0 +1,5 @@
+CONFIG_MODULES=y
+# CONFIG_BOOL_CHOICE0 is not set
+CONFIG_BOOL_CHOICE1=y
+# CONFIG_TRI_CHOICE0 is not set
+# CONFIG_TRI_CHOICE1 is not set
diff --git a/scripts/kconfig/tests/choice/allmod_expected_config b/scripts/kconfig/tests/choice/allmod_expected_config
new file mode 100644
index 0000000000..f1f5dcdb79
--- /dev/null
+++ b/scripts/kconfig/tests/choice/allmod_expected_config
@@ -0,0 +1,9 @@
+CONFIG_MODULES=y
+# CONFIG_BOOL_CHOICE0 is not set
+CONFIG_BOOL_CHOICE1=y
+# CONFIG_OPT_BOOL_CHOICE0 is not set
+CONFIG_OPT_BOOL_CHOICE1=y
+CONFIG_TRI_CHOICE0=m
+CONFIG_TRI_CHOICE1=m
+CONFIG_OPT_TRI_CHOICE0=m
+CONFIG_OPT_TRI_CHOICE1=m
diff --git a/scripts/kconfig/tests/choice/allno_expected_config b/scripts/kconfig/tests/choice/allno_expected_config
new file mode 100644
index 0000000000..b88ee7a431
--- /dev/null
+++ b/scripts/kconfig/tests/choice/allno_expected_config
@@ -0,0 +1,5 @@
+# CONFIG_MODULES is not set
+# CONFIG_BOOL_CHOICE0 is not set
+CONFIG_BOOL_CHOICE1=y
+# CONFIG_TRI_CHOICE0 is not set
+CONFIG_TRI_CHOICE1=y
diff --git a/scripts/kconfig/tests/choice/allyes_expected_config b/scripts/kconfig/tests/choice/allyes_expected_config
new file mode 100644
index 0000000000..e5a062a115
--- /dev/null
+++ b/scripts/kconfig/tests/choice/allyes_expected_config
@@ -0,0 +1,9 @@
+CONFIG_MODULES=y
+# CONFIG_BOOL_CHOICE0 is not set
+CONFIG_BOOL_CHOICE1=y
+# CONFIG_OPT_BOOL_CHOICE0 is not set
+CONFIG_OPT_BOOL_CHOICE1=y
+# CONFIG_TRI_CHOICE0 is not set
+CONFIG_TRI_CHOICE1=y
+# CONFIG_OPT_TRI_CHOICE0 is not set
+CONFIG_OPT_TRI_CHOICE1=y
diff --git a/scripts/kconfig/tests/choice/oldask0_expected_stdout b/scripts/kconfig/tests/choice/oldask0_expected_stdout
new file mode 100644
index 0000000000..b251bba969
--- /dev/null
+++ b/scripts/kconfig/tests/choice/oldask0_expected_stdout
@@ -0,0 +1,10 @@
+Enable loadable module support (MODULES) [Y/n/?] (NEW)
+boolean choice
+ 1. choice 0 (BOOL_CHOICE0) (NEW)
+> 2. choice 1 (BOOL_CHOICE1) (NEW)
+choice[1-2?]:
+optional boolean choice [N/y/?] (NEW)
+tristate choice [M/y/?] (NEW)
+ choice 0 (TRI_CHOICE0) [N/m/?] (NEW)
+ choice 1 (TRI_CHOICE1) [N/m/?] (NEW)
+optional tristate choice [N/m/y/?] (NEW)
diff --git a/scripts/kconfig/tests/choice/oldask1_config b/scripts/kconfig/tests/choice/oldask1_config
new file mode 100644
index 0000000000..b67bfe3c64
--- /dev/null
+++ b/scripts/kconfig/tests/choice/oldask1_config
@@ -0,0 +1,2 @@
+# CONFIG_MODULES is not set
+CONFIG_OPT_BOOL_CHOICE0=y
diff --git a/scripts/kconfig/tests/choice/oldask1_expected_stdout b/scripts/kconfig/tests/choice/oldask1_expected_stdout
new file mode 100644
index 0000000000..c2125e9bf9
--- /dev/null
+++ b/scripts/kconfig/tests/choice/oldask1_expected_stdout
@@ -0,0 +1,15 @@
+Enable loadable module support (MODULES) [N/y/?]
+boolean choice
+ 1. choice 0 (BOOL_CHOICE0) (NEW)
+> 2. choice 1 (BOOL_CHOICE1) (NEW)
+choice[1-2?]:
+optional boolean choice [Y/n/?] (NEW)
+optional boolean choice
+> 1. choice 0 (OPT_BOOL_CHOICE0)
+ 2. choice 1 (OPT_BOOL_CHOICE1) (NEW)
+choice[1-2?]:
+tristate choice
+ 1. choice 0 (TRI_CHOICE0) (NEW)
+> 2. choice 1 (TRI_CHOICE1) (NEW)
+choice[1-2?]:
+optional tristate choice [N/y/?]
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig b/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig
new file mode 100644
index 0000000000..11ac25c260
--- /dev/null
+++ b/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig
@@ -0,0 +1,19 @@
+config MODULES
+ def_bool y
+ option modules
+
+config DEP
+ tristate
+ default m
+
+choice
+ prompt "Tristate Choice"
+
+config CHOICE0
+ tristate "Choice 0"
+
+config CHOICE1
+ tristate "Choice 1"
+ depends on DEP
+
+endchoice
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py b/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py
new file mode 100644
index 0000000000..f8d728c7b1
--- /dev/null
+++ b/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py
@@ -0,0 +1,15 @@
+"""
+Hide tristate choice values with mod dependency in y choice.
+
+If tristate choice values depend on symbols set to 'm', they should be
+hidden when the choice containing them is changed from 'm' to 'y'
+(i.e. exclusive choice).
+
+Related Linux commit: fa64e5f6a35efd5e77d639125d973077ca506074
+"""
+
+
+def test(conf):
+ assert conf.oldaskconfig('config', 'y') == 0
+ assert conf.config_contains('expected_config')
+ assert conf.stdout_contains('expected_stdout')
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/config b/scripts/kconfig/tests/choice_value_with_m_dep/config
new file mode 100644
index 0000000000..3a126b7a25
--- /dev/null
+++ b/scripts/kconfig/tests/choice_value_with_m_dep/config
@@ -0,0 +1,2 @@
+CONFIG_CHOICE0=m
+CONFIG_CHOICE1=m
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/expected_config b/scripts/kconfig/tests/choice_value_with_m_dep/expected_config
new file mode 100644
index 0000000000..4d07b44954
--- /dev/null
+++ b/scripts/kconfig/tests/choice_value_with_m_dep/expected_config
@@ -0,0 +1,3 @@
+CONFIG_MODULES=y
+CONFIG_DEP=m
+CONFIG_CHOICE0=y
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout b/scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout
new file mode 100644
index 0000000000..2b50ab65c8
--- /dev/null
+++ b/scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout
@@ -0,0 +1,4 @@
+Tristate Choice [M/y/?] y
+Tristate Choice
+> 1. Choice 0 (CHOICE0)
+choice[1]: 1
diff --git a/scripts/kconfig/tests/conftest.py b/scripts/kconfig/tests/conftest.py
new file mode 100644
index 0000000000..0345ef6e32
--- /dev/null
+++ b/scripts/kconfig/tests/conftest.py
@@ -0,0 +1,291 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
+#
+
+"""
+Kconfig unit testing framework.
+
+This provides fixture functions commonly used from test files.
+"""
+
+import os
+import pytest
+import shutil
+import subprocess
+import tempfile
+
+CONF_PATH = os.path.abspath(os.path.join('scripts', 'kconfig', 'conf'))
+
+
+class Conf:
+ """Kconfig runner and result checker.
+
+ This class provides methods to run text-based interface of Kconfig
+ (scripts/kconfig/conf) and retrieve the resulted configuration,
+ stdout, and stderr. It also provides methods to compare those
+ results with expectations.
+ """
+
+ def __init__(self, request):
+ """Create a new Conf instance.
+
+ request: object to introspect the requesting test module
+ """
+ # the directory of the test being run
+ self._test_dir = os.path.dirname(str(request.fspath))
+
+ # runners
+ def _run_conf(self, mode, dot_config=None, out_file='.config',
+ interactive=False, in_keys=None, extra_env={}):
+ """Run text-based Kconfig executable and save the result.
+
+ mode: input mode option (--oldaskconfig, --defconfig=<file> etc.)
+ dot_config: .config file to use for configuration base
+ out_file: file name to contain the output config data
+ interactive: flag to specify the interactive mode
+ in_keys: key inputs for interactive modes
+ extra_env: additional environments
+ returncode: exit status of the Kconfig executable
+ """
+ command = [CONF_PATH, mode, 'Kconfig']
+
+ # Override 'srctree' environment to make the test as the top directory
+ extra_env['srctree'] = self._test_dir
+
+ # Run Kconfig in a temporary directory.
+ # This directory is automatically removed when done.
+ with tempfile.TemporaryDirectory() as temp_dir:
+
+ # if .config is given, copy it to the working directory
+ if dot_config:
+ shutil.copyfile(os.path.join(self._test_dir, dot_config),
+ os.path.join(temp_dir, '.config'))
+
+ ps = subprocess.Popen(command,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=temp_dir,
+ env=dict(os.environ, **extra_env))
+
+ # If input key sequence is given, feed it to stdin.
+ if in_keys:
+ ps.stdin.write(in_keys.encode('utf-8'))
+
+ while ps.poll() is None:
+ # For interactive modes such as oldaskconfig, oldconfig,
+ # send 'Enter' key until the program finishes.
+ if interactive:
+ ps.stdin.write(b'\n')
+
+ self.retcode = ps.returncode
+ self.stdout = ps.stdout.read().decode()
+ self.stderr = ps.stderr.read().decode()
+
+ # Retrieve the resulted config data only when .config is supposed
+ # to exist. If the command fails, the .config does not exist.
+ # 'listnewconfig' does not produce .config in the first place.
+ if self.retcode == 0 and out_file:
+ with open(os.path.join(temp_dir, out_file)) as f:
+ self.config = f.read()
+ else:
+ self.config = None
+
+ # Logging:
+ # Pytest captures the following information by default. In failure
+ # of tests, the captured log will be displayed. This will be useful to
+ # figure out what has happened.
+
+ print("[command]\n{}\n".format(' '.join(command)))
+
+ print("[retcode]\n{}\n".format(self.retcode))
+
+ print("[stdout]")
+ print(self.stdout)
+
+ print("[stderr]")
+ print(self.stderr)
+
+ if self.config is not None:
+ print("[output for '{}']".format(out_file))
+ print(self.config)
+
+ return self.retcode
+
+ def oldaskconfig(self, dot_config=None, in_keys=None):
+ """Run oldaskconfig.
+
+ dot_config: .config file to use for configuration base (optional)
+ in_key: key inputs (optional)
+ returncode: exit status of the Kconfig executable
+ """
+ return self._run_conf('--oldaskconfig', dot_config=dot_config,
+ interactive=True, in_keys=in_keys)
+
+ def oldconfig(self, dot_config=None, in_keys=None):
+ """Run oldconfig.
+
+ dot_config: .config file to use for configuration base (optional)
+ in_key: key inputs (optional)
+ returncode: exit status of the Kconfig executable
+ """
+ return self._run_conf('--oldconfig', dot_config=dot_config,
+ interactive=True, in_keys=in_keys)
+
+ def olddefconfig(self, dot_config=None):
+ """Run olddefconfig.
+
+ dot_config: .config file to use for configuration base (optional)
+ returncode: exit status of the Kconfig executable
+ """
+ return self._run_conf('--olddefconfig', dot_config=dot_config)
+
+ def defconfig(self, defconfig):
+ """Run defconfig.
+
+ defconfig: defconfig file for input
+ returncode: exit status of the Kconfig executable
+ """
+ defconfig_path = os.path.join(self._test_dir, defconfig)
+ return self._run_conf('--defconfig={}'.format(defconfig_path))
+
+ def _allconfig(self, mode, all_config):
+ if all_config:
+ all_config_path = os.path.join(self._test_dir, all_config)
+ extra_env = {'KCONFIG_ALLCONFIG': all_config_path}
+ else:
+ extra_env = {}
+
+ return self._run_conf('--{}config'.format(mode), extra_env=extra_env)
+
+ def allyesconfig(self, all_config=None):
+ """Run allyesconfig.
+
+ all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
+ returncode: exit status of the Kconfig executable
+ """
+ return self._allconfig('allyes', all_config)
+
+ def allmodconfig(self, all_config=None):
+ """Run allmodconfig.
+
+ all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
+ returncode: exit status of the Kconfig executable
+ """
+ return self._allconfig('allmod', all_config)
+
+ def allnoconfig(self, all_config=None):
+ """Run allnoconfig.
+
+ all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
+ returncode: exit status of the Kconfig executable
+ """
+ return self._allconfig('allno', all_config)
+
+ def alldefconfig(self, all_config=None):
+ """Run alldefconfig.
+
+ all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
+ returncode: exit status of the Kconfig executable
+ """
+ return self._allconfig('alldef', all_config)
+
+ def randconfig(self, all_config=None):
+ """Run randconfig.
+
+ all_config: fragment config file for KCONFIG_ALLCONFIG (optional)
+ returncode: exit status of the Kconfig executable
+ """
+ return self._allconfig('rand', all_config)
+
+ def savedefconfig(self, dot_config):
+ """Run savedefconfig.
+
+ dot_config: .config file for input
+ returncode: exit status of the Kconfig executable
+ """
+ return self._run_conf('--savedefconfig', out_file='defconfig')
+
+ def listnewconfig(self, dot_config=None):
+ """Run listnewconfig.
+
+ dot_config: .config file to use for configuration base (optional)
+ returncode: exit status of the Kconfig executable
+ """
+ return self._run_conf('--listnewconfig', dot_config=dot_config,
+ out_file=None)
+
+ # checkers
+ def _read_and_compare(self, compare, expected):
+ """Compare the result with expectation.
+
+ compare: function to compare the result with expectation
+ expected: file that contains the expected data
+ """
+ with open(os.path.join(self._test_dir, expected)) as f:
+ expected_data = f.read()
+ return compare(self, expected_data)
+
+ def _contains(self, attr, expected):
+ return self._read_and_compare(
+ lambda s, e: getattr(s, attr).find(e) >= 0,
+ expected)
+
+ def _matches(self, attr, expected):
+ return self._read_and_compare(lambda s, e: getattr(s, attr) == e,
+ expected)
+
+ def config_contains(self, expected):
+ """Check if resulted configuration contains expected data.
+
+ expected: file that contains the expected data
+ returncode: True if result contains the expected data, False otherwise
+ """
+ return self._contains('config', expected)
+
+ def config_matches(self, expected):
+ """Check if resulted configuration exactly matches expected data.
+
+ expected: file that contains the expected data
+ returncode: True if result matches the expected data, False otherwise
+ """
+ return self._matches('config', expected)
+
+ def stdout_contains(self, expected):
+ """Check if resulted stdout contains expected data.
+
+ expected: file that contains the expected data
+ returncode: True if result contains the expected data, False otherwise
+ """
+ return self._contains('stdout', expected)
+
+ def stdout_matches(self, expected):
+ """Check if resulted stdout exactly matches expected data.
+
+ expected: file that contains the expected data
+ returncode: True if result matches the expected data, False otherwise
+ """
+ return self._matches('stdout', expected)
+
+ def stderr_contains(self, expected):
+ """Check if resulted stderr contains expected data.
+
+ expected: file that contains the expected data
+ returncode: True if result contains the expected data, False otherwise
+ """
+ return self._contains('stderr', expected)
+
+ def stderr_matches(self, expected):
+ """Check if resulted stderr exactly matches expected data.
+
+ expected: file that contains the expected data
+ returncode: True if result matches the expected data, False otherwise
+ """
+ return self._matches('stderr', expected)
+
+
+@pytest.fixture(scope="module")
+def conf(request):
+ """Create a Conf instance and provide it to test functions."""
+ return Conf(request)
diff --git a/scripts/kconfig/tests/err_recursive_dep/Kconfig b/scripts/kconfig/tests/err_recursive_dep/Kconfig
new file mode 100644
index 0000000000..ebdb3ffd87
--- /dev/null
+++ b/scripts/kconfig/tests/err_recursive_dep/Kconfig
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# depends on itself
+
+config A
+ bool "A"
+ depends on A
+
+# select itself
+
+config B
+ bool
+ select B
+
+# depends on each other
+
+config C1
+ bool "C1"
+ depends on C2
+
+config C2
+ bool "C2"
+ depends on C1
+
+# depends on and select
+
+config D1
+ bool "D1"
+ depends on D2
+ select D2
+
+config D2
+ bool
+
+# depends on and imply
+
+config E1
+ bool "E1"
+ depends on E2
+ imply E2
+
+config E2
+ bool "E2"
+
+# property
+
+config F1
+ bool "F1"
+ default F2
+
+config F2
+ bool "F2"
+ depends on F1
+
+# menu
+
+menu "menu depending on its content"
+ depends on G
+
+config G
+ bool "G"
+
+endmenu
diff --git a/scripts/kconfig/tests/err_recursive_dep/__init__.py b/scripts/kconfig/tests/err_recursive_dep/__init__.py
new file mode 100644
index 0000000000..5f3821b43c
--- /dev/null
+++ b/scripts/kconfig/tests/err_recursive_dep/__init__.py
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Detect recursive dependency error.
+
+Recursive dependency should be treated as an error.
+"""
+
+def test(conf):
+ assert conf.oldaskconfig() == 1
+ assert conf.stderr_contains('expected_stderr')
diff --git a/scripts/kconfig/tests/err_recursive_dep/expected_stderr b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
new file mode 100644
index 0000000000..84679b1046
--- /dev/null
+++ b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
@@ -0,0 +1,38 @@
+Kconfig:11:error: recursive dependency detected!
+Kconfig:11: symbol B is selected by B
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:5:error: recursive dependency detected!
+Kconfig:5: symbol A depends on A
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:17:error: recursive dependency detected!
+Kconfig:17: symbol C1 depends on C2
+Kconfig:21: symbol C2 depends on C1
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:32:error: recursive dependency detected!
+Kconfig:32: symbol D2 is selected by D1
+Kconfig:27: symbol D1 depends on D2
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:37:error: recursive dependency detected!
+Kconfig:37: symbol E1 depends on E2
+Kconfig:42: symbol E2 is implied by E1
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:60:error: recursive dependency detected!
+Kconfig:60: symbol G depends on G
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:51:error: recursive dependency detected!
+Kconfig:51: symbol F2 depends on F1
+Kconfig:49: symbol F1 default value contains F2
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig b/scripts/kconfig/tests/err_recursive_inc/Kconfig
new file mode 100644
index 0000000000..0e4c8750ab
--- /dev/null
+++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig
@@ -0,0 +1 @@
+source "Kconfig.inc1"
diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1 b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1
new file mode 100644
index 0000000000..00e408d653
--- /dev/null
+++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1
@@ -0,0 +1,4 @@
+
+
+
+source "Kconfig.inc2"
diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2 b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2
new file mode 100644
index 0000000000..349ea2db15
--- /dev/null
+++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2
@@ -0,0 +1,3 @@
+
+
+source "Kconfig.inc3"
diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3 b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3
new file mode 100644
index 0000000000..0e4c8750ab
--- /dev/null
+++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3
@@ -0,0 +1 @@
+source "Kconfig.inc1"
diff --git a/scripts/kconfig/tests/err_recursive_inc/__init__.py b/scripts/kconfig/tests/err_recursive_inc/__init__.py
new file mode 100644
index 0000000000..0e4c839c54
--- /dev/null
+++ b/scripts/kconfig/tests/err_recursive_inc/__init__.py
@@ -0,0 +1,10 @@
+"""
+Detect recursive inclusion error.
+
+If recursive inclusion is detected, it should fail with error messages.
+"""
+
+
+def test(conf):
+ assert conf.oldaskconfig() != 0
+ assert conf.stderr_contains('expected_stderr')
diff --git a/scripts/kconfig/tests/err_recursive_inc/expected_stderr b/scripts/kconfig/tests/err_recursive_inc/expected_stderr
new file mode 100644
index 0000000000..6b582eee21
--- /dev/null
+++ b/scripts/kconfig/tests/err_recursive_inc/expected_stderr
@@ -0,0 +1,6 @@
+Recursive inclusion detected.
+Inclusion path:
+ current file : Kconfig.inc1
+ included from: Kconfig.inc3:1
+ included from: Kconfig.inc2:3
+ included from: Kconfig.inc1:4
diff --git a/scripts/kconfig/tests/inter_choice/Kconfig b/scripts/kconfig/tests/inter_choice/Kconfig
new file mode 100644
index 0000000000..e44449f075
--- /dev/null
+++ b/scripts/kconfig/tests/inter_choice/Kconfig
@@ -0,0 +1,23 @@
+config MODULES
+ def_bool y
+ option modules
+
+choice
+ prompt "Choice"
+
+config CHOICE_VAL0
+ tristate "Choice 0"
+
+config CHOIVE_VAL1
+ tristate "Choice 1"
+
+endchoice
+
+choice
+ prompt "Another choice"
+ depends on CHOICE_VAL0
+
+config DUMMY
+ bool "dummy"
+
+endchoice
diff --git a/scripts/kconfig/tests/inter_choice/__init__.py b/scripts/kconfig/tests/inter_choice/__init__.py
new file mode 100644
index 0000000000..5c7fc365ed
--- /dev/null
+++ b/scripts/kconfig/tests/inter_choice/__init__.py
@@ -0,0 +1,14 @@
+"""
+Do not affect user-assigned choice value by another choice.
+
+Handling of state flags for choices is complecated. In old days,
+the defconfig result of a choice could be affected by another choice
+if those choices interact by 'depends on', 'select', etc.
+
+Related Linux commit: fbe98bb9ed3dae23e320c6b113e35f129538d14a
+"""
+
+
+def test(conf):
+ assert conf.defconfig('defconfig') == 0
+ assert conf.config_contains('expected_config')
diff --git a/scripts/kconfig/tests/inter_choice/defconfig b/scripts/kconfig/tests/inter_choice/defconfig
new file mode 100644
index 0000000000..162c4148e2
--- /dev/null
+++ b/scripts/kconfig/tests/inter_choice/defconfig
@@ -0,0 +1 @@
+CONFIG_CHOICE_VAL0=y
diff --git a/scripts/kconfig/tests/inter_choice/expected_config b/scripts/kconfig/tests/inter_choice/expected_config
new file mode 100644
index 0000000000..5dceefb054
--- /dev/null
+++ b/scripts/kconfig/tests/inter_choice/expected_config
@@ -0,0 +1,4 @@
+CONFIG_MODULES=y
+CONFIG_CHOICE_VAL0=y
+# CONFIG_CHOIVE_VAL1 is not set
+CONFIG_DUMMY=y
diff --git a/scripts/kconfig/tests/new_choice_with_dep/Kconfig b/scripts/kconfig/tests/new_choice_with_dep/Kconfig
new file mode 100644
index 0000000000..53ef1b86e7
--- /dev/null
+++ b/scripts/kconfig/tests/new_choice_with_dep/Kconfig
@@ -0,0 +1,37 @@
+config A
+ bool "A"
+ help
+ This is a new symbol.
+
+choice
+ prompt "Choice ?"
+ depends on A
+ help
+ "depends on A" has been newly added.
+
+config CHOICE_B
+ bool "Choice B"
+
+config CHOICE_C
+ bool "Choice C"
+ help
+ This is a new symbol, so should be asked.
+
+endchoice
+
+choice
+ prompt "Choice2 ?"
+
+config CHOICE_D
+ bool "Choice D"
+
+config CHOICE_E
+ bool "Choice E"
+
+config CHOICE_F
+ bool "Choice F"
+ depends on A
+ help
+ This is a new symbol, so should be asked.
+
+endchoice
diff --git a/scripts/kconfig/tests/new_choice_with_dep/__init__.py b/scripts/kconfig/tests/new_choice_with_dep/__init__.py
new file mode 100644
index 0000000000..f0e0ead0f3
--- /dev/null
+++ b/scripts/kconfig/tests/new_choice_with_dep/__init__.py
@@ -0,0 +1,14 @@
+"""
+Ask new choice values when they become visible.
+
+If new choice values are added with new dependency, and they become
+visible during user configuration, oldconfig should recognize them
+as (NEW), and ask the user for choice.
+
+Related Linux commit: 5d09598d488f081e3be23f885ed65cbbe2d073b5
+"""
+
+
+def test(conf):
+ assert conf.oldconfig('config', 'y') == 0
+ assert conf.stdout_contains('expected_stdout')
diff --git a/scripts/kconfig/tests/new_choice_with_dep/config b/scripts/kconfig/tests/new_choice_with_dep/config
new file mode 100644
index 0000000000..47ef95d567
--- /dev/null
+++ b/scripts/kconfig/tests/new_choice_with_dep/config
@@ -0,0 +1,3 @@
+CONFIG_CHOICE_B=y
+# CONFIG_CHOICE_D is not set
+CONFIG_CHOICE_E=y
diff --git a/scripts/kconfig/tests/new_choice_with_dep/expected_stdout b/scripts/kconfig/tests/new_choice_with_dep/expected_stdout
new file mode 100644
index 0000000000..74dc0bcb22
--- /dev/null
+++ b/scripts/kconfig/tests/new_choice_with_dep/expected_stdout
@@ -0,0 +1,10 @@
+A (A) [N/y/?] (NEW) y
+ Choice ?
+ > 1. Choice B (CHOICE_B)
+ 2. Choice C (CHOICE_C) (NEW)
+ choice[1-2?]:
+Choice2 ?
+ 1. Choice D (CHOICE_D)
+> 2. Choice E (CHOICE_E)
+ 3. Choice F (CHOICE_F) (NEW)
+choice[1-3?]:
diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig b/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig
new file mode 100644
index 0000000000..c00b8fe54f
--- /dev/null
+++ b/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig
@@ -0,0 +1,14 @@
+config A
+ bool "A"
+
+choice
+ prompt "Choice ?"
+ depends on A
+
+config CHOICE_B
+ bool "Choice B"
+
+config CHOICE_C
+ bool "Choice C"
+
+endchoice
diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py b/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py
new file mode 100644
index 0000000000..207261b0fe
--- /dev/null
+++ b/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py
@@ -0,0 +1,19 @@
+"""
+Do not write choice values to .config if the dependency is unmet.
+
+"# CONFIG_... is not set" should not be written into the .config file
+for symbols with unmet dependency.
+
+This was not working correctly for choice values because choice needs
+a bit different symbol computation.
+
+This checks that no unneeded "# COFIG_... is not set" is contained in
+the .config file.
+
+Related Linux commit: cb67ab2cd2b8abd9650292c986c79901e3073a59
+"""
+
+
+def test(conf):
+ assert conf.oldaskconfig('config', 'n') == 0
+ assert conf.config_matches('expected_config')
diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/config b/scripts/kconfig/tests/no_write_if_dep_unmet/config
new file mode 100644
index 0000000000..abd280e2f6
--- /dev/null
+++ b/scripts/kconfig/tests/no_write_if_dep_unmet/config
@@ -0,0 +1 @@
+CONFIG_A=y
diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config b/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config
new file mode 100644
index 0000000000..473228810c
--- /dev/null
+++ b/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config
@@ -0,0 +1,5 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main menu
+#
+# CONFIG_A is not set
diff --git a/scripts/kconfig/tests/preprocess/builtin_func/Kconfig b/scripts/kconfig/tests/preprocess/builtin_func/Kconfig
new file mode 100644
index 0000000000..baa3288279
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/builtin_func/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# 'info' prints the argument to stdout.
+$(info,hello world 0)
+
+# 'warning-if', if the first argument is y, sends the second argument to stderr,
+# and the message is prefixed with the current file name and line number.
+$(warning-if,y,hello world 1)
+
+# 'error-if' is similar, but it terminates the parsing immediately.
+# The following is just no-op since the first argument is not y.
+$(error-if,n,this should not be printed)
+
+# Shorthand
+warning = $(warning-if,y,$(1))
+
+# 'shell' executes a command, and returns its stdout.
+$(warning,$(shell,echo hello world 3))
+
+# Every newline in the output is replaced with a space,
+# but any trailing newlines are deleted.
+$(warning,$(shell,printf 'hello\nworld\n\n4\n\n\n'))
+
+# 'filename' is expanded to the currently parsed file name,
+# 'lineno' to the line number.
+$(warning,filename=$(filename))
+$(warning,lineno=$(lineno))
diff --git a/scripts/kconfig/tests/preprocess/builtin_func/__init__.py b/scripts/kconfig/tests/preprocess/builtin_func/__init__.py
new file mode 100644
index 0000000000..2e53ba08fc
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/builtin_func/__init__.py
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Built-in function tests.
+"""
+
+def test(conf):
+ assert conf.oldaskconfig() == 0
+ assert conf.stdout_contains('expected_stdout')
+ assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/preprocess/builtin_func/expected_stderr b/scripts/kconfig/tests/preprocess/builtin_func/expected_stderr
new file mode 100644
index 0000000000..33ea9ca384
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/builtin_func/expected_stderr
@@ -0,0 +1,5 @@
+Kconfig:8: hello world 1
+Kconfig:18: hello world 3
+Kconfig:22: hello world 4
+Kconfig:26: filename=Kconfig
+Kconfig:27: lineno=27
diff --git a/scripts/kconfig/tests/preprocess/builtin_func/expected_stdout b/scripts/kconfig/tests/preprocess/builtin_func/expected_stdout
new file mode 100644
index 0000000000..82de3a7e97
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/builtin_func/expected_stdout
@@ -0,0 +1 @@
+hello world 0
diff --git a/scripts/kconfig/tests/preprocess/circular_expansion/Kconfig b/scripts/kconfig/tests/preprocess/circular_expansion/Kconfig
new file mode 100644
index 0000000000..6838997c23
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/circular_expansion/Kconfig
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+X = $(Y)
+Y = $(X)
+$(info $(X))
diff --git a/scripts/kconfig/tests/preprocess/circular_expansion/__init__.py b/scripts/kconfig/tests/preprocess/circular_expansion/__init__.py
new file mode 100644
index 0000000000..419bda3e07
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/circular_expansion/__init__.py
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Detect circular variable expansion.
+
+If a recursively expanded variable references itself (eventually),
+it should fail with an error message.
+"""
+
+def test(conf):
+ assert conf.oldaskconfig() != 0
+ assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr b/scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr
new file mode 100644
index 0000000000..cde68fa989
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr
@@ -0,0 +1 @@
+Kconfig:5: Recursive variable 'X' references itself (eventually)
diff --git a/scripts/kconfig/tests/preprocess/escape/Kconfig b/scripts/kconfig/tests/preprocess/escape/Kconfig
new file mode 100644
index 0000000000..4e3f444455
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/escape/Kconfig
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# Shorthand
+warning = $(warning-if,y,$(1))
+
+# You can not pass commas directly to a function since they are treated as
+# delimiters. You can use the following trick to do so.
+comma := ,
+$(warning,hello$(comma) world)
+
+# Like Make, single quotes, double quotes, spaces are treated verbatim.
+# The following prints the text as-is.
+$(warning, ' " '" ' ''' "'")
+
+# Unlike Make, '$' has special meaning only when it is followed by '('.
+# No need to escape '$' itself.
+$(warning,$)
+$(warning,$$)
+$ := 1
+$(warning,$($))
+
+# You need a trick to escape '$' followed by '('
+# The following should print "$(X)". It should not be expanded further.
+dollar := $
+$(warning,$(dollar)(X))
+
+# You need a trick to treat unbalanced parentheses.
+# The following should print "(".
+left_paren := (
+$(warning,$(left_paren))
+
+# A simple expanded should not be expanded multiple times.
+# The following should print "$(X)". It should not be expanded further.
+Y := $(dollar)(X)
+$(warning,$(Y))
+
+# The following should print "$(X)" as well.
+Y = $(dollar)(X)
+$(warning,$(Y))
+
+# The following should print "$(".
+# It should not be emit "unterminated reference" error.
+unterminated := $(dollar)(
+$(warning,$(unterminated))
diff --git a/scripts/kconfig/tests/preprocess/escape/__init__.py b/scripts/kconfig/tests/preprocess/escape/__init__.py
new file mode 100644
index 0000000000..7ee8e747f5
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/escape/__init__.py
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Escape sequence tests.
+"""
+
+def test(conf):
+ assert conf.oldaskconfig() == 0
+ assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/preprocess/escape/expected_stderr b/scripts/kconfig/tests/preprocess/escape/expected_stderr
new file mode 100644
index 0000000000..1c00957dda
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/escape/expected_stderr
@@ -0,0 +1,10 @@
+Kconfig:9: hello, world
+Kconfig:13: ' " '" ' ''' "'"
+Kconfig:17: $
+Kconfig:18: $$
+Kconfig:20: 1
+Kconfig:25: $(X)
+Kconfig:30: (
+Kconfig:35: $(X)
+Kconfig:39: $(X)
+Kconfig:44: $(
diff --git a/scripts/kconfig/tests/preprocess/variable/Kconfig b/scripts/kconfig/tests/preprocess/variable/Kconfig
new file mode 100644
index 0000000000..9ce2f95cbd
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/variable/Kconfig
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# Shorthand
+warning = $(warning-if,y,$(1))
+
+# Simply expanded variable.
+X := 1
+SIMPLE := $(X)
+X := 2
+$(warning,SIMPLE = $(SIMPLE))
+
+# Recursively expanded variable.
+X := 1
+RECURSIVE = $(X)
+X := 2
+$(warning,RECURSIVE = $(RECURSIVE))
+
+# Append something to a simply expanded variable.
+Y := 3
+SIMPLE += $(Y)
+Y := 4
+$(warning,SIMPLE = $(SIMPLE))
+
+# Append something to a recursively expanded variable.
+Y := 3
+RECURSIVE += $(Y)
+Y := 4
+$(warning,RECURSIVE = $(RECURSIVE))
+
+# Use += operator to an undefined variable.
+# This works as a recursively expanded variable.
+Y := 3
+UNDEFINED_VARIABLE += $(Y)
+Y := 4
+$(warning,UNDEFINED_VARIABLE = $(UNDEFINED_VARIABLE))
+
+# You can use variable references for the lefthand side of assignment statement.
+X := A
+Y := B
+$(X)$(Y) := 5
+$(warning,AB = $(AB))
+
+# User-defined function.
+greeting = $(1), my name is $(2).
+$(warning,$(greeting,Hello,John))
+
+# The number of arguments is not checked for user-defined functions.
+# If some arguments are optional, it is useful to pass fewer parameters.
+# $(2) will be blank in this case.
+$(warning,$(greeting,Hello))
+
+# Unreferenced parameters are just ignored.
+$(warning,$(greeting,Hello,John,ignored,ignored))
diff --git a/scripts/kconfig/tests/preprocess/variable/__init__.py b/scripts/kconfig/tests/preprocess/variable/__init__.py
new file mode 100644
index 0000000000..e88b1708d6
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/variable/__init__.py
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Variable and user-defined function tests.
+"""
+
+def test(conf):
+ assert conf.oldaskconfig() == 0
+ assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/preprocess/variable/expected_stderr b/scripts/kconfig/tests/preprocess/variable/expected_stderr
new file mode 100644
index 0000000000..a4841c3fdf
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/variable/expected_stderr
@@ -0,0 +1,9 @@
+Kconfig:10: SIMPLE = 1
+Kconfig:16: RECURSIVE = 2
+Kconfig:22: SIMPLE = 1 3
+Kconfig:28: RECURSIVE = 2 4
+Kconfig:35: UNDEFINED_VARIABLE = 4
+Kconfig:41: AB = 5
+Kconfig:45: Hello, my name is John.
+Kconfig:50: Hello, my name is .
+Kconfig:53: Hello, my name is John.
diff --git a/scripts/kconfig/tests/pytest.ini b/scripts/kconfig/tests/pytest.ini
new file mode 100644
index 0000000000..85d7ce8e44
--- /dev/null
+++ b/scripts/kconfig/tests/pytest.ini
@@ -0,0 +1,7 @@
+[pytest]
+addopts = --verbose
+
+# Pytest requires that test files have unique names, because pytest imports
+# them as top-level modules. It is silly to prefix or suffix a test file with
+# the directory name that contains it. Use __init__.py for all test files.
+python_files = __init__.py
diff --git a/scripts/kconfig/tests/rand_nested_choice/Kconfig b/scripts/kconfig/tests/rand_nested_choice/Kconfig
new file mode 100644
index 0000000000..c591d51292
--- /dev/null
+++ b/scripts/kconfig/tests/rand_nested_choice/Kconfig
@@ -0,0 +1,33 @@
+choice
+ prompt "choice"
+
+config A
+ bool "A"
+
+config B
+ bool "B"
+
+if B
+choice
+ prompt "sub choice"
+
+config C
+ bool "C"
+
+config D
+ bool "D"
+
+if D
+choice
+ prompt "subsub choice"
+
+config E
+ bool "E"
+
+endchoice
+endif # D
+
+endchoice
+endif # B
+
+endchoice
diff --git a/scripts/kconfig/tests/rand_nested_choice/__init__.py b/scripts/kconfig/tests/rand_nested_choice/__init__.py
new file mode 100644
index 0000000000..e729a4e852
--- /dev/null
+++ b/scripts/kconfig/tests/rand_nested_choice/__init__.py
@@ -0,0 +1,16 @@
+"""
+Set random values recursively in nested choices.
+
+Kconfig can create a choice-in-choice structure by using 'if' statement.
+randconfig should correctly set random choice values.
+
+Related Linux commit: 3b9a19e08960e5cdad5253998637653e592a3c29
+"""
+
+
+def test(conf):
+ for i in range(20):
+ assert conf.randconfig() == 0
+ assert (conf.config_contains('expected_stdout0') or
+ conf.config_contains('expected_stdout1') or
+ conf.config_contains('expected_stdout2'))
diff --git a/scripts/kconfig/tests/rand_nested_choice/expected_stdout0 b/scripts/kconfig/tests/rand_nested_choice/expected_stdout0
new file mode 100644
index 0000000000..05450f3d4e
--- /dev/null
+++ b/scripts/kconfig/tests/rand_nested_choice/expected_stdout0
@@ -0,0 +1,2 @@
+CONFIG_A=y
+# CONFIG_B is not set
diff --git a/scripts/kconfig/tests/rand_nested_choice/expected_stdout1 b/scripts/kconfig/tests/rand_nested_choice/expected_stdout1
new file mode 100644
index 0000000000..37ab295841
--- /dev/null
+++ b/scripts/kconfig/tests/rand_nested_choice/expected_stdout1
@@ -0,0 +1,4 @@
+# CONFIG_A is not set
+CONFIG_B=y
+CONFIG_C=y
+# CONFIG_D is not set
diff --git a/scripts/kconfig/tests/rand_nested_choice/expected_stdout2 b/scripts/kconfig/tests/rand_nested_choice/expected_stdout2
new file mode 100644
index 0000000000..849ff47e98
--- /dev/null
+++ b/scripts/kconfig/tests/rand_nested_choice/expected_stdout2
@@ -0,0 +1,5 @@
+# CONFIG_A is not set
+CONFIG_B=y
+# CONFIG_C is not set
+CONFIG_D=y
+CONFIG_E=y
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index 94f9c83e32..d999683bb2 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -14,69 +14,21 @@
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->name = xstrdup(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)
{
@@ -88,16 +40,6 @@ struct gstr str_new(void)
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)
{
@@ -114,7 +56,7 @@ void str_append(struct gstr *gs, const char *s)
if (s) {
l = strlen(gs->s) + strlen(s) + 1;
if (l > gs->len) {
- gs->s = realloc(gs->s, l);
+ gs->s = xrealloc(gs->s, l);
gs->len = l;
}
strcat(gs->s, s);
@@ -155,3 +97,34 @@ void *xcalloc(size_t nmemb, size_t size)
fprintf(stderr, "Out of memory.\n");
exit(1);
}
+
+void *xrealloc(void *p, size_t size)
+{
+ p = realloc(p, size);
+ if (p)
+ return p;
+ fprintf(stderr, "Out of memory.\n");
+ exit(1);
+}
+
+char *xstrdup(const char *s)
+{
+ char *p;
+
+ p = strdup(s);
+ if (p)
+ return p;
+ fprintf(stderr, "Out of memory.\n");
+ exit(1);
+}
+
+char *xstrndup(const char *s, size_t n)
+{
+ char *p;
+
+ p = strndup(s, n);
+ if (p)
+ return p;
+ fprintf(stderr, "Out of memory.\n");
+ exit(1);
+}
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
deleted file mode 100644
index b6ac02d604..0000000000
--- a/scripts/kconfig/zconf.gperf
+++ /dev/null
@@ -1,48 +0,0 @@
-%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
-allnoconfig_y, T_OPT_ALLNOCONFIG_Y,TF_OPTION
-%%
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c
index c77a8eff1e..c77a8eff1e 100644
--- a/scripts/kconfig/zconf.hash.c_shipped
+++ b/scripts/kconfig/zconf.hash.c
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
index 6c62d93b4f..25bd2b89fe 100644
--- a/scripts/kconfig/zconf.l
+++ b/scripts/kconfig/zconf.l
@@ -1,13 +1,13 @@
%option nostdinit noyywrap never-interactive full ecs
-%option 8bit nodefault perf-report perf-report
-%option noinput
-%x COMMAND HELP STRING PARAM
+%option 8bit nodefault yylineno
+%x COMMAND HELP STRING PARAM ASSIGN_VAL
%{
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
+#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -35,6 +35,8 @@ struct buffer *current_buf;
static int last_ts, first_ts;
+static char *expand_token(const char *in, size_t n);
+static void append_expanded_string(const char *in);
static void zconf_endhelp(void);
static void zconf_endfile(void);
@@ -52,7 +54,7 @@ static void append_string(const char *str, int size)
if (new_size > text_asize) {
new_size += START_STRSIZE - 1;
new_size &= -START_STRSIZE;
- text = realloc(text, new_size);
+ text = xrealloc(text, new_size);
text_asize = new_size;
}
memcpy(text + text_size, str, size);
@@ -66,9 +68,16 @@ static void alloc_string(const char *str, int size)
memcpy(text, str, size);
text[size] = 0;
}
+
+static void warn_ignored_character(char chr)
+{
+ fprintf(stderr,
+ "%s:%d:warning: ignoring unsupported character '%c'\n",
+ zconf_curname(), zconf_lineno(), chr);
+}
%}
-n [A-Za-z0-9_]
+n [A-Za-z0-9_-]
%%
int str = 0;
@@ -76,7 +85,6 @@ n [A-Za-z0-9_]
[ \t]*#.*\n |
[ \t]*\n {
- current_file->lineno++;
return T_EOL;
}
[ \t]*#.*
@@ -95,25 +103,45 @@ n [A-Za-z0-9_]
<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;
+ current_pos.lineno = yylineno;
if (id && id->flags & TF_COMMAND) {
- zconflval.id = id;
+ BEGIN(PARAM);
+ yylval.id = id;
return id->token;
}
alloc_string(yytext, yyleng);
- zconflval.string = text;
- return T_WORD;
+ yylval.string = text;
+ return T_VARIABLE;
}
- .
+ ({n}|$)+ {
+ /* this token includes at least one '$' */
+ yylval.string = expand_token(yytext, yyleng);
+ if (strlen(yylval.string))
+ return T_VARIABLE;
+ free(yylval.string);
+ }
+ "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; }
+ ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; }
+ "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; }
+ [[:blank:]]+
+ . warn_ignored_character(*yytext);
\n {
BEGIN(INITIAL);
- current_file->lineno++;
return T_EOL;
}
}
+<ASSIGN_VAL>{
+ [^[:blank:]\n]+.* {
+ alloc_string(yytext, yyleng);
+ yylval.string = text;
+ return T_ASSIGN_VAL;
+ }
+ \n { BEGIN(INITIAL); return T_EOL; }
+ .
+}
+
<PARAM>{
"&&" return T_AND;
"||" return T_OR;
@@ -122,43 +150,55 @@ n [A-Za-z0-9_]
"!" return T_NOT;
"=" return T_EQUAL;
"!=" return T_UNEQUAL;
+ "<=" return T_LESS_EQUAL;
+ ">=" return T_GREATER_EQUAL;
+ "<" return T_LESS;
+ ">" return T_GREATER;
\"|\' {
str = yytext[0];
new_string();
BEGIN(STRING);
}
- \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
- --- /* ignore */
- ({n}|[-/.])+ {
+ \n BEGIN(INITIAL); return T_EOL;
+ ({n}|[/.])+ {
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
if (id && id->flags & TF_PARAM) {
- zconflval.id = id;
+ yylval.id = id;
return id->token;
}
alloc_string(yytext, yyleng);
- zconflval.string = text;
+ yylval.string = text;
return T_WORD;
}
+ ({n}|[/.$])+ {
+ /* this token includes at least one '$' */
+ yylval.string = expand_token(yytext, yyleng);
+ if (strlen(yylval.string))
+ return T_WORD;
+ free(yylval.string);
+ }
#.* /* comment */
- \\\n current_file->lineno++;
- .
+ \\\n ;
+ [[:blank:]]+
+ . warn_ignored_character(*yytext);
<<EOF>> {
BEGIN(INITIAL);
}
}
<STRING>{
- [^'"\\\n]+/\n {
+ "$".* append_expanded_string(yytext);
+ [^$'"\\\n]+/\n {
append_string(yytext, yyleng);
- zconflval.string = text;
+ yylval.string = text;
return T_WORD_QUOTE;
}
- [^'"\\\n]+ {
+ [^$'"\\\n]+ {
append_string(yytext, yyleng);
}
\\.?/\n {
append_string(yytext + 1, yyleng - 1);
- zconflval.string = text;
+ yylval.string = text;
return T_WORD_QUOTE;
}
\\.? {
@@ -167,14 +207,15 @@ n [A-Za-z0-9_]
\'|\" {
if (str == yytext[0]) {
BEGIN(PARAM);
- zconflval.string = text;
+ yylval.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++;
+ fprintf(stderr,
+ "%s:%d:warning: multi-line strings not supported\n",
+ zconf_curname(), zconf_lineno());
BEGIN(INITIAL);
return T_EOL;
}
@@ -207,12 +248,10 @@ n [A-Za-z0-9_]
}
}
[ \t]*\n/[^ \t\n] {
- current_file->lineno++;
zconf_endhelp();
return T_HELPTEXT;
}
[ \t]*\n {
- current_file->lineno++;
append_string("\n", 1);
}
[^ \t\n].* {
@@ -241,6 +280,58 @@ n [A-Za-z0-9_]
}
%%
+static char *expand_token(const char *in, size_t n)
+{
+ char *out;
+ int c;
+ char c2;
+ const char *rest, *end;
+
+ new_string();
+ append_string(in, n);
+
+ /* get the whole line because we do not know the end of token. */
+ while ((c = input()) != EOF) {
+ if (c == '\n') {
+ unput(c);
+ break;
+ }
+ c2 = c;
+ append_string(&c2, 1);
+ }
+
+ rest = text;
+ out = expand_one_token(&rest);
+
+ /* push back unused characters to the input stream */
+ end = rest + strlen(rest);
+ while (end > rest)
+ unput(*--end);
+
+ free(text);
+
+ return out;
+}
+
+static void append_expanded_string(const char *str)
+{
+ const char *end;
+ char *res;
+
+ str++;
+
+ res = expand_dollar(&str);
+
+ /* push back unused characters to the input stream */
+ end = str + strlen(str);
+ while (end > str)
+ unput(*--end);
+
+ append_string(res, strlen(res));
+
+ free(res);
+}
+
void zconf_starthelp(void)
{
new_string();
@@ -250,7 +341,7 @@ void zconf_starthelp(void)
static void zconf_endhelp(void)
{
- zconflval.string = text;
+ yylval.string = text;
BEGIN(INITIAL);
}
@@ -283,7 +374,7 @@ void zconf_initscan(const char *name)
{
yyin = zconf_fopen(name);
if (!yyin) {
- printf("can't find file %s\n", name);
+ fprintf(stderr, "can't find file %s\n", name);
exit(1);
}
@@ -291,7 +382,7 @@ void zconf_initscan(const char *name)
memset(current_buf, 0, sizeof(*current_buf));
current_file = file_lookup(name);
- current_file->lineno = 1;
+ yylineno = 1;
}
void zconf_nextfile(const char *name)
@@ -304,35 +395,34 @@ void zconf_nextfile(const char *name)
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);
+ fprintf(stderr, "%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);
+ current_file->lineno = yylineno;
+ file->parent = current_file;
+
+ for (iter = current_file; iter; iter = iter->parent) {
+ if (!strcmp(iter->name, file->name)) {
+ fprintf(stderr,
+ "Recursive inclusion detected.\n"
+ "Inclusion path:\n"
+ " current file : %s\n", file->name);
+ iter = file;
+ do {
iter = iter->parent;
- }
- if (iter)
- printf(" included from: '%s:%d'\n",
- iter->name, iter->lineno+1);
+ fprintf(stderr, " included from: %s:%d\n",
+ iter->name, iter->lineno - 1);
+ } while (strcmp(iter->name, file->name));
exit(1);
}
}
- file->lineno = 1;
- file->parent = current_file;
+
+ yylineno = 1;
current_file = file;
}
@@ -341,6 +431,8 @@ static void zconf_endfile(void)
struct buffer *parent;
current_file = current_file->parent;
+ if (current_file)
+ yylineno = current_file->lineno;
parent = current_buf->parent;
if (parent) {
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 0f683cfa53..22fceb264c 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -20,10 +20,10 @@
int cdebug = PRINTD;
-extern int zconflex(void);
+int yylex(void);
+static void yyerror(const char *err);
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];
@@ -41,6 +41,7 @@ static struct menu *current_menu, *current_entry;
struct expr *expr;
struct menu *menu;
const struct kconf_id *id;
+ enum variable_flavor flavor;
}
%token <id>T_MAINMENU
@@ -62,6 +63,7 @@ static struct menu *current_menu, *current_entry;
%token <id>T_TYPE
%token <id>T_DEFAULT
%token <id>T_SELECT
+%token <id>T_IMPLY
%token <id>T_RANGE
%token <id>T_VISIBLE
%token <id>T_OPTION
@@ -69,23 +71,32 @@ static struct menu *current_menu, *current_entry;
%token <string> T_WORD
%token <string> T_WORD_QUOTE
%token T_UNEQUAL
+%token T_LESS
+%token T_LESS_EQUAL
+%token T_GREATER
+%token T_GREATER_EQUAL
%token T_CLOSE_PAREN
%token T_OPEN_PAREN
%token T_EOL
+%token <string> T_VARIABLE
+%token <flavor> T_ASSIGN
+%token <string> T_ASSIGN_VAL
%left T_OR
%left T_AND
%left T_EQUAL T_UNEQUAL
+%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
%nonassoc T_NOT
%type <string> prompt
+%type <symbol> nonconst_symbol
%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
+%type <string> symbol_option_arg word_opt assign_val
%destructor {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -95,8 +106,8 @@ static struct menu *current_menu, *current_entry;
} if_entry menu_entry choice_entry
%{
-/* Include zconf.hash.c here so it can see the token constants. */
-#include "zconf.hash.c"
+/* Include kconf_id.c here so it can see the token constants. */
+#include "kconf_id.c"
%}
%%
@@ -104,6 +115,13 @@ input: nl start | start;
start: mainmenu_stmt stmt_list | stmt_list;
+/* mainmenu entry */
+
+mainmenu_stmt: T_MAINMENU prompt T_EOL
+{
+ menu_add_prompt(P_MENU, $2, NULL);
+};
+
stmt_list:
/* empty */
| stmt_list common_stmt
@@ -113,13 +131,13 @@ stmt_list:
| 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);
+ zconf_error("unexpected option \"%s\"", $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
+ T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_IMPLY | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
;
common_stmt:
@@ -129,6 +147,7 @@ common_stmt:
| config_stmt
| menuconfig_stmt
| source_stmt
+ | assignment_stmt
;
option_error:
@@ -139,26 +158,23 @@ option_error:
/* config/menuconfig entry */
-config_entry_start: T_CONFIG T_WORD T_EOL
+config_entry_start: T_CONFIG nonconst_symbol 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);
+ $2->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry($2);
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name);
};
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
+menuconfig_entry_start: T_MENUCONFIG nonconst_symbol 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);
+ $2->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry($2);
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name);
};
menuconfig_stmt: menuconfig_entry_start config_option_list
@@ -167,7 +183,6 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
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());
};
@@ -205,12 +220,18 @@ config_option: T_DEFAULT expr if_expr T_EOL
$1->stype);
};
-config_option: T_SELECT T_WORD if_expr T_EOL
+config_option: T_SELECT nonconst_symbol if_expr T_EOL
{
- menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
+ menu_add_symbol(P_SELECT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
};
+config_option: T_IMPLY nonconst_symbol if_expr T_EOL
+{
+ menu_add_symbol(P_IMPLY, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:imply\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);
@@ -225,8 +246,10 @@ symbol_option_list:
| 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)
+ if (id && id->flags & TF_OPTION) {
menu_add_option(id->token, $3);
+ free($3);
+ }
else
zconfprint("warning: ignoring unknown option %s", $2);
free($2);
@@ -242,9 +265,10 @@ symbol_option_arg:
choice: T_CHOICE word_opt T_EOL
{
struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
- sym->flags |= SYMBOL_AUTO;
+ sym->flags |= SYMBOL_NO_WRITE;
menu_add_entry(sym);
menu_add_expr(P_CHOICE, NULL, NULL);
+ free($2);
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
};
@@ -296,10 +320,10 @@ choice_option: T_OPTIONAL T_EOL
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
};
-choice_option: T_DEFAULT T_WORD if_expr T_EOL
+choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
{
if ($1->stype == S_UNKNOWN) {
- menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
+ menu_add_symbol(P_DEFAULT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:default\n",
zconf_curname(), zconf_lineno());
} else
@@ -313,7 +337,7 @@ choice_block:
/* if entry */
-if_entry: T_IF expr nl
+if_entry: T_IF expr T_EOL
{
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
menu_add_entry(NULL);
@@ -339,13 +363,6 @@ if_block:
| 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
@@ -382,6 +399,7 @@ source_stmt: T_SOURCE prompt T_EOL
{
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
zconf_nextfile($2);
+ free($2);
};
/* comment entry */
@@ -394,9 +412,7 @@ comment: T_COMMENT prompt T_EOL
};
comment_stmt: comment depends_list
-{
- menu_end_entry();
-};
+;
/* help option */
@@ -408,6 +424,17 @@ help_start: T_HELP T_EOL
help: help_start T_HELPTEXT
{
+ if (current_entry->help) {
+ free(current_entry->help);
+ zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used",
+ current_entry->sym->name ?: "<choice>");
+ }
+
+ /* Is the help text empty or all whitespace? */
+ if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
+ zconfprint("warning: '%s' defined with blank help text",
+ current_entry->sym->name ?: "<choice>");
+
current_entry->help = $2;
};
@@ -467,6 +494,10 @@ if_expr: /* empty */ { $$ = NULL; }
;
expr: symbol { $$ = expr_alloc_symbol($1); }
+ | symbol T_LESS symbol { $$ = expr_alloc_comp(E_LTH, $1, $3); }
+ | symbol T_LESS_EQUAL symbol { $$ = expr_alloc_comp(E_LEQ, $1, $3); }
+ | symbol T_GREATER symbol { $$ = expr_alloc_comp(E_GTH, $1, $3); }
+ | symbol T_GREATER_EQUAL symbol { $$ = expr_alloc_comp(E_GEQ, $1, $3); }
| 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; }
@@ -475,13 +506,25 @@ expr: symbol { $$ = expr_alloc_symbol($1); }
| expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
;
-symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
+/* For symbol definitions, selects, etc., where quotes are not accepted */
+nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };
+
+symbol: nonconst_symbol
| T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
;
word_opt: /* empty */ { $$ = NULL; }
| T_WORD
+/* assignment statement */
+
+assignment_stmt: T_VARIABLE T_ASSIGN assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
+
+assign_val:
+ /* empty */ { $$ = xstrdup(""); };
+ | T_ASSIGN_VAL
+;
+
%%
void conf_parse(const char *name)
@@ -491,27 +534,31 @@ void conf_parse(const char *name)
zconf_initscan(name);
- sym_init();
_menu_init();
- rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
if (getenv("ZCONF_DEBUG"))
- zconfdebug = 1;
- zconfparse();
- if (zconfnerrs)
+ yydebug = 1;
+ yyparse();
+
+ /* Variables are expanded in the parse phase. We can free them here. */
+ variable_all_del();
+
+ if (yynerrs)
exit(1);
if (!modules_sym)
modules_sym = sym_find( "n" );
- rootmenu.prompt->text = _(rootmenu.prompt->text);
- rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
+ if (!menu_has_prompt(&rootmenu)) {
+ current_entry = &rootmenu;
+ menu_add_prompt(P_MENU, "Main menu", NULL);
+ }
menu_finalize(&rootmenu);
for_all_symbols(i, sym) {
if (sym_check_deps(sym))
- zconfnerrs++;
+ yynerrs++;
}
- if (zconfnerrs)
+ if (yynerrs)
exit(1);
sym_set_change_count(1);
}
@@ -535,17 +582,17 @@ static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtok
{
if (id->token != endtoken) {
zconf_error("unexpected '%s' within %s block",
- kconf_id_strings + id->name, zconf_tokenname(starttoken));
- zconfnerrs++;
+ id->name, zconf_tokenname(starttoken));
+ yynerrs++;
return false;
}
if (current_menu->file != current_file) {
zconf_error("'%s' in different file than '%s'",
- kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ 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++;
+ yynerrs++;
return false;
}
return true;
@@ -566,7 +613,7 @@ static void zconf_error(const char *err, ...)
{
va_list ap;
- zconfnerrs++;
+ yynerrs++;
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
va_start(ap, err);
vfprintf(stderr, err, ap);
@@ -574,7 +621,7 @@ static void zconf_error(const char *err, ...)
fprintf(stderr, "\n");
}
-static void zconferror(const char *err)
+static void yyerror(const char *err)
{
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
}
@@ -607,7 +654,7 @@ static void print_symbol(FILE *out, struct menu *menu)
fprintf(out, "\nconfig %s\n", sym->name);
switch (sym->type) {
case S_BOOLEAN:
- fputs(" boolean\n", out);
+ fputs(" bool\n", out);
break;
case S_TRISTATE:
fputs(" tristate\n", out);
@@ -655,6 +702,11 @@ static void print_symbol(FILE *out, struct menu *menu)
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
+ case P_IMPLY:
+ fputs( " imply ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
case P_RANGE:
fputs( " range ", out);
expr_fprint(prop->expr, out);
@@ -665,6 +717,10 @@ static void print_symbol(FILE *out, struct menu *menu)
print_quoted_string(out, prop->text);
fputc('\n', out);
break;
+ case P_SYMBOL:
+ fputs( " symbol ", out);
+ fprintf(out, "%s\n", prop->sym->name);
+ break;
default:
fprintf(out, " unknown prop %d!\n", prop->type);
break;
@@ -731,3 +787,4 @@ void zconfdump(FILE *out)
#include "expr.c"
#include "symbol.c"
#include "menu.c"
+#include "preprocess.c"