build: scripts/config - update to kconfig-v6.6.16
authorEneas U de Queiroz <cotequeiroz@gmail.com>
Fri, 16 Feb 2024 17:32:07 +0000 (14:32 -0300)
committerRobert Marko <robimarko@gmail.com>
Fri, 1 Mar 2024 18:02:00 +0000 (19:02 +0100)
The main goal here is to keep this close to upstream.

Changes include:
 - allow symbols implied by y to become m
 - make 'imply' obey the direct dependency
 - allow only 'config', 'comment', and 'if' inside 'choice'
 - qconf: make search fully work again on split mode
 - qconf: navigate menus on hyperlinks
 - remove '---help---' support
 - qconf: allow to edit "int", "hex", "string" menus in-place
 - qconf: drop Qt4 support
 - nconf: fix core dump when searching in empty menu
 - nconf: stop endless search loops
 - Create links to main menu items in search
 - fix segmentation fault in menuconfig search
 - nconf: Add search jump feature
 - port qconf to work with Qt6 in addition to Qt5
 - fix possible buffer overflow
 - fix memory leak from range properties

Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
28 files changed:
scripts/config/.gitignore
scripts/config/Kbuild.include [new file with mode: 0644]
scripts/config/Makefile
scripts/config/README
scripts/config/conf.c
scripts/config/confdata.c
scripts/config/expr.h
scripts/config/lexer.l
scripts/config/lexer.lex.c
scripts/config/lkc.h
scripts/config/lkc_proto.h
scripts/config/lxdialog/dialog.h
scripts/config/lxdialog/menubox.c
scripts/config/lxdialog/textbox.c
scripts/config/mconf-cfg.sh
scripts/config/mconf.c
scripts/config/menu.c
scripts/config/nconf-cfg.sh
scripts/config/nconf.c
scripts/config/nconf.gui.c
scripts/config/nconf.h
scripts/config/parser.tab.c
scripts/config/parser.tab.h
scripts/config/preprocess.c
scripts/config/qconf-cfg.sh
scripts/config/qconf.cc
scripts/config/symbol.c
scripts/config/util.c

index 05c55c3c8e58e2411637dc1de1a79d3bafa646a8..1cef9de10fbf7584fc7778961c094b50bb35358c 100644 (file)
@@ -1,16 +1,14 @@
 # SPDX-License-Identifier: GPL-2.0-only
 /conf
 /[gmnq]conf
-/[gmnq]conf-cfg
+/[gmnq]conf-bin
+/[gmnq]conf-cflags
+/[gmnq]conf-libs
 /qconf-moc.cc
 
-# From linux kconfig parent directories
-.*
-
-# OpenWrt-generated files
+#
+# Added by openwrt
+#
 mconf_check
-
-# Temporary files from older versions.  They should be removed after the
-# end of support for OpenWrt 19.07.
-zconf.???.c
-zconf.hash.c
+# The next line should be removed after 23.05 is EOL
+*conf-cfg
diff --git a/scripts/config/Kbuild.include b/scripts/config/Kbuild.include
new file mode 100644 (file)
index 0000000..7778cc9
--- /dev/null
@@ -0,0 +1,279 @@
+# SPDX-License-Identifier: GPL-2.0
+####
+# kbuild: Generic definitions
+
+# Convenient variables
+comma   := ,
+quote   := "
+squote  := '
+empty   :=
+space   := $(empty) $(empty)
+space_escape := _-_SPACE_-_
+pound := \#
+define newline
+
+
+endef
+
+###
+# Comparison macros.
+# Usage: $(call test-lt, $(CONFIG_LLD_VERSION), 150000)
+#
+# Use $(intcmp ...) if supported. (Make >= 4.4)
+# Otherwise, fall back to the 'test' shell command.
+ifeq ($(intcmp 1,0,,,y),y)
+test-ge = $(intcmp $(strip $1)0, $(strip $2)0,,y,y)
+test-gt = $(intcmp $(strip $1)0, $(strip $2)0,,,y)
+else
+test-ge = $(shell test $(strip $1)0 -ge $(strip $2)0 && echo y)
+test-gt = $(shell test $(strip $1)0 -gt $(strip $2)0 && echo y)
+endif
+test-le = $(call test-ge, $2, $1)
+test-lt = $(call test-gt, $2, $1)
+
+###
+# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
+dot-target = $(dir $@).$(notdir $@)
+
+###
+# Name of target with a '.tmp_' as filename prefix. foo/bar.o => foo/.tmp_bar.o
+tmp-target = $(dir $@).tmp_$(notdir $@)
+
+###
+# The temporary file to save gcc -MMD generated dependencies must not
+# contain a comma
+depfile = $(subst $(comma),_,$(dot-target).d)
+
+###
+# filename of target with directory and extension stripped
+basetarget = $(basename $(notdir $@))
+
+###
+# real prerequisites without phony targets
+real-prereqs = $(filter-out $(PHONY), $^)
+
+###
+# Escape single quote for use in echo statements
+escsq = $(subst $(squote),'\$(squote)',$1)
+
+###
+# Quote a string to pass it to C files. foo => '"foo"'
+stringify = $(squote)$(quote)$1$(quote)$(squote)
+
+###
+# The path to Kbuild or Makefile. Kbuild has precedence over Makefile.
+kbuild-dir = $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+kbuild-file = $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile)
+
+###
+# Read a file, replacing newlines with spaces
+#
+# Make 4.2 or later can read a file by using its builtin function.
+ifneq ($(filter-out 3.% 4.0 4.1, $(MAKE_VERSION)),)
+read-file = $(subst $(newline),$(space),$(file < $1))
+else
+read-file = $(shell cat $1 2>/dev/null)
+endif
+
+###
+# Easy method for doing a status message
+       kecho := :
+ quiet_kecho := echo
+silent_kecho := :
+kecho := $($(quiet)kecho)
+
+###
+# filechk is used to check if the content of a generated file is updated.
+# Sample usage:
+#
+# filechk_sample = echo $(KERNELRELEASE)
+# version.h: FORCE
+#      $(call filechk,sample)
+#
+# The rule defined shall write to stdout the content of the new file.
+# The existing file will be compared with the new one.
+# - If no file exist it is created
+# - If the content differ the new file is used
+# - If they are equal no change, and no timestamp update
+define filechk
+       $(check-FORCE)
+       $(Q)set -e;                                             \
+       mkdir -p $(dir $@);                                     \
+       trap "rm -f $(tmp-target)" EXIT;                        \
+       { $(filechk_$(1)); } > $(tmp-target);                   \
+       if [ ! -r $@ ] || ! cmp -s $@ $(tmp-target); then       \
+               $(kecho) '  UPD     $@';                        \
+               mv -f $(tmp-target) $@;                         \
+       fi
+endef
+
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
+# Usage:
+# $(Q)$(MAKE) $(build)=dir
+build := -f $(srctree)/scripts/Makefile.build obj
+
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj=
+# Usage:
+# $(Q)$(MAKE) $(dtbinst)=dir
+dtbinst := -f $(srctree)/scripts/Makefile.dtbinst obj
+
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=
+# Usage:
+# $(Q)$(MAKE) $(clean)=dir
+clean := -f $(srctree)/scripts/Makefile.clean obj
+
+# pring log
+#
+# If quiet is "silent_", print nothing and sink stdout
+# If quiet is "quiet_", print short log
+# If quiet is empty, print short log and whole command
+silent_log_print = exec >/dev/null;
+ quiet_log_print = $(if $(quiet_cmd_$1), echo '  $(call escsq,$(quiet_cmd_$1)$(why))';)
+       log_print = echo '$(pound) $(call escsq,$(or $(quiet_cmd_$1),cmd_$1 $@)$(why))'; \
+                   echo '  $(call escsq,$(cmd_$1))';
+
+# Delete the target on interruption
+#
+# GNU Make automatically deletes the target if it has already been changed by
+# the interrupted recipe. So, you can safely stop the build by Ctrl-C (Make
+# will delete incomplete targets), and resume it later.
+#
+# However, this does not work when the stderr is piped to another program, like
+#  $ make >&2 | tee log
+# Make dies with SIGPIPE before cleaning the targets.
+#
+# To address it, we clean the target in signal traps.
+#
+# Make deletes the target when it catches SIGHUP, SIGINT, SIGQUIT, SIGTERM.
+# So, we cover them, and also SIGPIPE just in case.
+#
+# Of course, this is unneeded for phony targets.
+delete-on-interrupt = \
+       $(if $(filter-out $(PHONY), $@), \
+               $(foreach sig, HUP INT QUIT TERM PIPE, \
+                       trap 'rm -f $@; trap - $(sig); kill -s $(sig) $$$$' $(sig);))
+
+# print and execute commands
+cmd = @$(if $(cmd_$(1)),set -e; $($(quiet)log_print) $(delete-on-interrupt) $(cmd_$(1)),:)
+
+###
+# if_changed      - execute command if any prerequisite is newer than
+#                   target, or command line has changed
+# if_changed_dep  - as if_changed, but uses fixdep to reveal dependencies
+#                   including used config symbols
+# if_changed_rule - as if_changed but execute rule instead
+# See Documentation/kbuild/makefiles.rst for more info
+
+ifneq ($(KBUILD_NOCMDDEP),1)
+# Check if both commands are the same including their order. Result is empty
+# string if equal. User may override this check using make KBUILD_NOCMDDEP=1
+# If the target does not exist, the *.cmd file should not be included so
+# $(savedcmd_$@) gets empty. Then, target will be built even if $(newer-prereqs)
+# happens to become empty.
+cmd-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(savedcmd_$@))), \
+                         $(subst $(space),$(space_escape),$(strip $(cmd_$1))))
+else
+# We still need to detect missing targets.
+cmd-check = $(if $(strip $(savedcmd_$@)),,1)
+endif
+
+# Replace >$< with >$$< to preserve $ when reloading the .cmd file
+# (needed for make)
+# Replace >#< with >$(pound)< to avoid starting a comment in the .cmd file
+# (needed for make)
+# Replace >'< with >'\''< to be able to enclose the whole string in '...'
+# (needed for the shell)
+make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1)))))
+
+# Find any prerequisites that are newer than target or that do not exist.
+# PHONY targets skipped in both cases.
+# If there is no prerequisite other than phony targets, $(newer-prereqs) becomes
+# empty even if the target does not exist. cmd-check saves this corner case.
+newer-prereqs = $(filter-out $(PHONY),$?)
+
+# It is a typical mistake to forget the FORCE prerequisite. Check it here so
+# no more breakage will slip in.
+check-FORCE = $(if $(filter FORCE, $^),,$(warning FORCE prerequisite is missing))
+
+if-changed-cond = $(newer-prereqs)$(cmd-check)$(check-FORCE)
+
+# Execute command if command has changed or prerequisite(s) are updated.
+if_changed = $(if $(if-changed-cond),$(cmd_and_savecmd),@:)
+
+cmd_and_savecmd =                                                            \
+       $(cmd);                                                              \
+       printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd
+
+# Execute the command and also postprocess generated .d dependencies file.
+if_changed_dep = $(if $(if-changed-cond),$(cmd_and_fixdep),@:)
+
+cmd_and_fixdep =                                                             \
+       $(cmd);                                                              \
+       scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).cmd;\
+       rm -f $(depfile)
+
+# Usage: $(call if_changed_rule,foo)
+# Will check if $(cmd_foo) or any of the prerequisites changed,
+# and if so will execute $(rule_foo).
+if_changed_rule = $(if $(if-changed-cond),$(rule_$(1)),@:)
+
+###
+# why - tell why a target got built
+#       enabled by make V=2
+#       Output (listed in the order they are checked):
+#          (1) - due to target is PHONY
+#          (2) - due to target missing
+#          (3) - due to: file1.h file2.h
+#          (4) - due to command line change
+#          (5) - due to missing .cmd file
+#          (6) - due to target not in $(targets)
+# (1) PHONY targets are always build
+# (2) No target, so we better build it
+# (3) Prerequisite is newer than target
+# (4) The command line stored in the file named dir/.target.cmd
+#     differed from actual command line. This happens when compiler
+#     options changes
+# (5) No dir/.target.cmd file (used to store command line)
+# (6) No dir/.target.cmd file and target not listed in $(targets)
+#     This is a good hint that there is a bug in the kbuild file
+ifneq ($(findstring 2, $(KBUILD_VERBOSE)),)
+_why =                                                                        \
+    $(if $(filter $@, $(PHONY)),- due to target is PHONY,                    \
+        $(if $(wildcard $@),                                                 \
+            $(if $(newer-prereqs),- due to: $(newer-prereqs),                \
+                $(if $(cmd-check),                                           \
+                    $(if $(savedcmd_$@),- due to command line change,        \
+                        $(if $(filter $@, $(targets)),                       \
+                            - due to missing .cmd file,                      \
+                            - due to $(notdir $@) not in $$(targets)         \
+                         )                                                   \
+                     )                                                       \
+                 )                                                           \
+             ),                                                              \
+             - due to target missing                                         \
+         )                                                                   \
+     )
+
+why = $(space)$(strip $(_why))
+endif
+
+###############################################################################
+
+# delete partially updated (i.e. corrupted) files on error
+.DELETE_ON_ERROR:
+
+# do not delete intermediate files automatically
+#
+# .NOTINTERMEDIATE is more correct, but only available on newer Make versions.
+# Make 4.4 introduced .NOTINTERMEDIATE, and it appears in .FEATURES, but the
+# global .NOTINTERMEDIATE does not work. We can use it on Make > 4.4.
+# Use .SECONDARY for older Make versions, but "newer-prereq" cannot detect
+# deleted files.
+ifneq ($(and $(filter notintermediate, $(.FEATURES)),$(filter-out 4.4,$(MAKE_VERSION))),)
+.NOTINTERMEDIATE:
+else
+.SECONDARY:
+endif
index 5976a91b9abf8dd529c4c7811cbe12297013f94c..5e7dd9578ecfee04ea9558a451baaa8d85a2599f 100644 (file)
@@ -5,46 +5,21 @@
 .PHONY: clean all
 all: conf mconf
 clean:
-       rm -f *.o lxdialog/*.o *.moc .*.cmd $(clean-files)
+       rm -f $(clean-files) $(hostprogs)
 
-# This clean-files definition is here to ensure that temporary files from the
-# previous version are removed by make config-clean.
-# It should be emptied after the end of support for OpenWrt 19.07.
-clean-files    := zconf.tab.c zconf.lex.c zconf.hash.c .tmp_qtcheck
+clean-files    := *.o lxdialog/*.o *.moc qconf-moc.cc \
+                  *conf-cfg # <- This should be removed after 23.05 is EOL
 
 # ===========================================================================
 # Variables needed by the upstream Makefile
 
-# Avoids displaying 'UPD mconf-cfg' in an otherwise quiet make menuconfig
-kecho:=true
-
+export HOSTPKG_CONFIG=pkg-config
 CONFIG_SHELL:=$(SHELL)
-srctree:=.
-src:=.
+src:=$(CURDIR)
 obj:=.
 Q:=$(if $V,,@)
-cmd = $(cmd_$(1))
-
-# some definitions taken from ../Kbuild.include
-dot-target = $(dir $@).$(notdir $@)
-squote  := '
-escsq = $(subst $(squote),'\$(squote)',$1)
-define filechk
-       $(Q)set -e;                                             \
-       mkdir -p $(dir $@);                                     \
-       trap "rm -f $(dot-target).tmp" EXIT;                    \
-       { $(filechk_$(1)); } > $(dot-target).tmp;               \
-       if [ ! -r $@ ] || ! cmp -s $@ $(dot-target).tmp; then   \
-               $(kecho) '  UPD     $@';                        \
-               mv -f $(dot-target).tmp $@;                     \
-       fi
-endef
-cmd-check = $(if $(strip $(cmd_$@)),,1)
-make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1)))))
-newer-prereqs = $(filter-out $(PHONY),$?)
-if_changed = $(if $(newer-prereqs)$(cmd-check),                        \
-       $(cmd);                                                 \
-       printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
+quiet:=$(if $V,,_silent)
+include Kbuild.include
 
 ### Stripped down upstream Makefile follows:
 # ===========================================================================
@@ -64,11 +39,12 @@ conf-objs   := conf.o $(common-objs)
 hostprogs      += nconf
 nconf-objs     := nconf.o nconf.gui.o $(common-objs)
 
-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)
+HOSTLDLIBS_nconf       = $(call read-file, $(obj)/nconf-libs)
+HOSTCFLAGS_nconf.o     = $(call read-file, $(obj)/nconf-cflags)
+HOSTCFLAGS_nconf.gui.o = $(call read-file, $(obj)/nconf-cflags)
 
-$(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/nconf-cfg
+$(obj)/nconf: | $(obj)/nconf-libs
+$(obj)/nconf.o $(obj)/nconf.gui.o: | $(obj)/nconf-cflags
 
 # mconf: Used for the menuconfig target based on lxdialog
 hostprogs      += mconf
@@ -76,45 +52,44 @@ lxdialog    := $(addprefix lxdialog/, \
                     checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
 mconf-objs     := mconf.o $(lxdialog) $(common-objs)
 
-HOSTLDLIBS_mconf = $(shell . $(obj)/mconf-cfg && echo $$libs)
+HOSTLDLIBS_mconf = $(call read-file, $(obj)/mconf-libs)
 $(foreach f, mconf.o $(lxdialog), \
-  $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/mconf-cfg && echo $$$$cflags)))
+  $(eval HOSTCFLAGS_$f = $$(call read-file, $(obj)/mconf-cflags)))
 
-$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/mconf-cfg
+$(obj)/mconf: | $(obj)/mconf-libs
+$(addprefix $(obj)/, mconf.o $(lxdialog)): | $(obj)/mconf-cflags
 
 # qconf: Used for the xconfig target based on Qt
 hostprogs      += qconf
 qconf-cxxobjs  := qconf.o qconf-moc.o
 qconf-objs     := images.o $(common-objs)
 
-HOSTLDLIBS_qconf       = $(shell . $(obj)/qconf-cfg && echo $$libs)
-HOSTCXXFLAGS_qconf.o   = $(shell . $(obj)/qconf-cfg && echo $$cflags)
-HOSTCXXFLAGS_qconf-moc.o = $(shell . $(obj)/qconf-cfg && echo $$cflags)
-
-$(obj)/qconf.o: $(obj)/qconf-cfg
+HOSTLDLIBS_qconf         = $(call read-file, $(obj)/qconf-libs)
+HOSTCXXFLAGS_qconf.o     = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags)
+HOSTCXXFLAGS_qconf-moc.o = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags)
+$(obj)/qconf: | $(obj)/qconf-libs
+$(obj)/qconf.o $(obj)/qconf-moc.o: | $(obj)/qconf-cflags
 
 quiet_cmd_moc = MOC     $@
-      cmd_moc = $(shell . $(obj)/qconf-cfg && echo $$moc) $< -o $@
+      cmd_moc = $(call read-file, $(obj)/qconf-bin)/moc $< -o $@
 
-$(obj)/qconf-moc.cc: $(src)/qconf.h $(obj)/qconf-cfg FORCE
+$(obj)/qconf-moc.cc: $(src)/qconf.h FORCE | $(obj)/qconf-bin
        $(call if_changed,moc)
 
 targets += qconf-moc.cc
 
 # check if necessary packages are available, and configure build flags
-filechk_conf_cfg = $(CONFIG_SHELL) $<
+cmd_conf_cfg = $< $(addprefix $(obj)/$*conf-, cflags libs bin); touch $(obj)/$*conf-bin
 
-$(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE
-       $(call filechk,conf_cfg)
+$(obj)/%conf-cflags $(obj)/%conf-libs $(obj)/%conf-bin: $(src)/%conf-cfg.sh
+       $(call cmd,conf_cfg)
 
-clean-files += *conf-cfg
+clean-files += *conf-cflags *conf-libs *conf-bin
 
 # ===========================================================================
 # OpenWrt rules and final adjustments that need to be made after reading the
 # full upstream Makefile
 
-clean-files += $(targets) $(hostprogs)
-
 FORCE:
 
 ifdef BUILD_SHIPPED_FILES
@@ -130,25 +105,21 @@ clean-files += $(shipped-files)
        flex -L -o$@ $<
 endif
 
-$(foreach f,$(conf-objs) $(filter-out $(common-objs),$(mconf-objs) \
-                                                    $(qconf-objs) \
-                                                    $(nconf-objs)), \
-  $(eval $(obj)/$f: CFLAGS+=$$(HOSTCFLAGS_$f)))
-
-$(foreach f,$(qconf-cxxobjs), \
-  $(eval $(obj)/$f: CXXFLAGS+=$$(HOSTCXXFLAGS_$f)))
+define link_rule
+$(1): LDLIBS+=$$(HOSTLDLIBS_$(1))
+$(1): $($(1)-objs) $$($(1)-cxxobjs)
+$(if $($(1)-cxxobjs),  $(CXX) $$(LDFLAGS) -o $$@ $$^ $$(LDLIBS))
+all-objs += $($(1)-objs)
+all-cxxobjs += $($(1)-cxxobjs)
+endef
 
-$(obj)/conf: $(addprefix $(obj)/,$(conf-objs))
+all-objs:=
+all-cxxobjs:=
+$(foreach f,$(hostprogs),$(eval $(call link_rule,$f)))
 
-# The *conf-cfg file is used (then filtered out) as the first prerequisite to
-# avoid sourcing it before the script is built, when trying to compute CFLAGS
-# for the actual first prerequisite.  This avoids errors like:
-# '/bin/sh: ./mconf-cfg: No such file or directory'
-$(obj)/mconf: mconf-cfg $(addprefix $(obj)/,$(mconf-objs))
-       $(CC) -o $@ $(filter-out mconf-cfg,$^) $(HOSTLDLIBS_mconf)
 
-$(obj)/nconf: nconf-cfg $(addprefix $(obj)/,$(nconf-objs))
-       $(CC) -o $@ $(filter-out nconf-cfg,$^) $(HOSTLDLIBS_nconf)
+$(foreach f,$(sort $(all-objs)), \
+  $(eval $f: CFLAGS+=$$(HOSTCFLAGS_$f)))
 
-$(obj)/qconf: qconf-cfg $(addprefix $(obj)/,$(qconf-cxxobjs) $(qconf-objs))
-       $(CXX) -o $@ $(filter-out qconf-cfg,$^) $(HOSTLDLIBS_qconf)
+$(foreach f,$(sort $(all-cxxobjs)), \
+  $(eval $f: CXXFLAGS+=$$(HOSTCXXFLAGS_$f)))
index 99a7d535ab25d2029edd3be7b0a34108655fb70a..e1ebf89cbf1dd41f38405cb5bf8ae78d04fce744 100644 (file)
@@ -1,6 +1,7 @@
-These files were taken from the Linux 5.14 Kernel Configuration System and
-modified for the OpenWrt Buildroot:
- - Removed nconf, gconf, tests and kernel configuration targets.
+These files were taken from the Linux Kernel Configuration System v6.6.16, 
+at commit eb3e299184cc4f40d4bd84fda269b3a20ddcff80 (Feb 5, 2024),  and modified
+for the OpenWrt Buildroot:
+ - Removed gconf, tests and kernel configuration targets.
  - Adjusted the Makefile to compile outside the kernel.
  - Always use default file when running make all{no,mod,yes}config.
  - Added a 'reset' command to reset config when the target changes.
@@ -23,4 +24,4 @@ modified for the OpenWrt Buildroot:
    BUILD_SHIPPED_FILES defined
 
 For a full list of changes, see the repository at:
-https://github.com/cotequeiroz/linux/commits/openwrt-5.14/scripts/kconfig
+https://github.com/cotequeiroz/linux/commits/openwrt-v6.6.16/scripts/kconfig
index 978abebe654555ecf1ad4ef7cc81e75f75f963f7..1bd6f4fa8ba6129a76ccb8923f7d18bcb94cc714 100644 (file)
@@ -35,6 +35,7 @@ enum input_mode {
        olddefconfig,
        yes2modconfig,
        mod2yesconfig,
+       mod2noconfig,
        fatalrecursive,
 };
 static enum input_mode input_mode = oldaskconfig;
@@ -164,8 +165,6 @@ enum conf_def_mode {
        def_default,
        def_yes,
        def_mod,
-       def_y2m,
-       def_m2y,
        def_no,
        def_random
 };
@@ -303,12 +302,10 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
        return has_changed;
 }
 
-static void conf_rewrite_mod_or_yes(enum conf_def_mode mode)
+static void conf_rewrite_tristates(tristate old_val, tristate new_val)
 {
        struct symbol *sym;
        int i;
-       tristate old_val = (mode == def_y2m) ? yes : mod;
-       tristate new_val = (mode == def_y2m) ? mod : yes;
 
        for_all_symbols(i, sym) {
                if (sym_get_type(sym) == S_TRISTATE &&
@@ -555,7 +552,7 @@ static int conf_choice(struct menu *menu)
                        print_help(child);
                        continue;
                }
-               sym_set_choice_value(sym, child->sym);
+               sym_set_tristate_value(child->sym, yes);
                for (child = child->list; child; child = child->next) {
                        indent += 2;
                        conf(child);
@@ -647,19 +644,8 @@ static void check_conf(struct menu *menu)
 
                switch (input_mode) {
                case listnewconfig:
-                       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);
-                               }
-                       }
+                       if (sym->name)
+                               print_symbol_for_listconfig(sym);
                        break;
                case helpnewconfig:
                        printf("-----\n");
@@ -697,7 +683,8 @@ static const struct option long_opts[] = {
        {"olddefconfig",  no_argument,       &input_mode_opt, olddefconfig},
        {"yes2modconfig", no_argument,       &input_mode_opt, yes2modconfig},
        {"mod2yesconfig", no_argument,       &input_mode_opt, mod2yesconfig},
-       {"fatalrecursive",no_argument,       NULL, fatalrecursive},
+       {"mod2noconfig",  no_argument,       &input_mode_opt, mod2noconfig},
+       {"fatalrecursive",no_argument,       &input_mode_opt, fatalrecursive},
        {NULL, 0, NULL, 0}
 };
 
@@ -707,8 +694,10 @@ static void conf_usage(const char *progname)
        printf("\n");
        printf("Generic options:\n");
        printf("  -h, --help              Print this message and exit.\n");
+       printf("  -r <file>               Read <file> as input.\n");
        printf("  -s, --silent            Do not print log.\n");
-       printf("      --fatalrecursive    Treat recursive depenendencies as a fatal error\n");
+       printf("  -w <file>               Write config to <file>.\n");
+       printf("  --fatalrecursive        Treat recursive dependency as error.\n");
        printf("\n");
        printf("Mode options:\n");
        printf("  --listnewconfig         List new options\n");
@@ -727,6 +716,7 @@ static void conf_usage(const char *progname)
        printf("  --randconfig            New config with random answer to all options\n");
        printf("  --yes2modconfig         Change answers from yes to mod if possible\n");
        printf("  --mod2yesconfig         Change answers from mod to yes if possible\n");
+       printf("  --mod2noconfig          Change answers from mod to no if possible\n");
        printf("  (If none of the above is given, --oldaskconfig is the default)\n");
 }
 
@@ -740,27 +730,23 @@ int main(int ac, char **av)
 
        tty_stdio = isatty(0) && isatty(1);
 
-       while ((opt = getopt_long(ac, av, "hr:sw:", long_opts, NULL)) != -1) {
+       while ((opt = getopt_long(ac, av, "hr:w:s", long_opts, NULL)) != -1) {
                switch (opt) {
                case 'h':
                        conf_usage(progname);
                        exit(1);
                        break;
-               case 's':
-                       conf_set_message_callback(NULL);
-                       break;
-               case fatalrecursive:
-                       recursive_is_error = 1;
-                       continue;
                case 'r':
                        input_file = optarg;
                        break;
+               case 's':
+                       conf_set_message_callback(NULL);
+                       break;
                case 'w':
                        output_file = optarg;
                        break;
                case 0:
-                       input_mode = input_mode_opt;
-                       switch (input_mode) {
+                       switch (input_mode_opt) {
                        case syncconfig:
                                /*
                                 * syncconfig is invoked during the build stage.
@@ -777,9 +763,13 @@ int main(int ac, char **av)
                        case randconfig:
                                set_randconfig_seed();
                                break;
+                       case fatalrecursive:
+                               recursive_is_error = 1;
+                               continue;
                        default:
                                break;
                        }
+                       input_mode = input_mode_opt;
                default:
                        break;
                }
@@ -812,6 +802,7 @@ int main(int ac, char **av)
        case olddefconfig:
        case yes2modconfig:
        case mod2yesconfig:
+       case mod2noconfig:
        case allnoconfig:
        case allyesconfig:
        case allmodconfig:
@@ -858,10 +849,13 @@ int main(int ac, char **av)
        case savedefconfig:
                break;
        case yes2modconfig:
-               conf_rewrite_mod_or_yes(def_y2m);
+               conf_rewrite_tristates(yes, mod);
                break;
        case mod2yesconfig:
-               conf_rewrite_mod_or_yes(def_m2y);
+               conf_rewrite_tristates(mod, yes);
+               break;
+       case mod2noconfig:
+               conf_rewrite_tristates(mod, no);
                break;
        case oldaskconfig:
                rootEntry = &rootmenu;
index dad0b471c7df31ec1922a770c2222f84ea1ec762..e3f6fdfeb324e828fe2ded7924b1ca4fae1105ad 100644 (file)
@@ -11,6 +11,7 @@
 #include <fcntl.h>
 #include <limits.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -129,41 +130,22 @@ static size_t depfile_prefix_len;
 /* touch depfile for symbol 'name' */
 static int conf_touch_dep(const char *name)
 {
-       int fd, ret;
-       char *d;
+       int fd;
 
        /* check overflow: prefix + name + '\0' must fit in buffer. */
        if (depfile_prefix_len + strlen(name) + 1 > sizeof(depfile_path))
                return -1;
 
-       d = depfile_path + depfile_prefix_len;
-       strcpy(d, name);
+       strcpy(depfile_path + depfile_prefix_len, name);
 
-       /* Assume directory path already exists. */
        fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-       if (fd == -1) {
-               if (errno != ENOENT)
-                       return -1;
-
-               ret = make_parent_dir(depfile_path);
-               if (ret)
-                       return ret;
-
-               /* Try it again. */
-               fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-               if (fd == -1)
-                       return -1;
-       }
+       if (fd == -1)
+               return -1;
        close(fd);
 
        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)));
 
@@ -227,6 +209,20 @@ static const char *conf_get_autoconfig_name(void)
        return name ? name : "include/config/auto.conf";
 }
 
+static const char *conf_get_autoheader_name(void)
+{
+       char *name = getenv("KCONFIG_AUTOHEADER");
+
+       return name ? name : "include/generated/autoconf.h";
+}
+
+static const char *conf_get_rustccfg_name(void)
+{
+       char *name = getenv("KCONFIG_RUSTCCFG");
+
+       return name ? name : "include/generated/rustc_cfg";
+}
+
 static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
 {
        char *p2;
@@ -255,19 +251,21 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                                     p, sym->name);
                return 1;
        case S_STRING:
-               if (*p++ != '"')
-                       break;
-               for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
-                       if (*p2 == '"') {
-                               *p2 = 0;
+               /* No escaping for S_DEF_AUTO (include/config/auto.conf) */
+               if (def != S_DEF_AUTO) {
+                       if (*p++ != '"')
                                break;
+                       for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
+                               if (*p2 == '"') {
+                                       *p2 = 0;
+                                       break;
+                               }
+                               memmove(p2, p2 + 1, strlen(p2));
                        }
-                       memmove(p2, p2 + 1, strlen(p2));
-               }
-               if (!p2) {
-                       if (def != S_DEF_AUTO)
+                       if (!p2) {
                                conf_warning("invalid string found");
-                       return 1;
+                               return 1;
+                       }
                }
                /* fall through */
        case S_INT:
@@ -376,7 +374,11 @@ int conf_read_simple(const char *name, int def)
        char *p, *p2;
        struct symbol *sym;
        int def_flags;
+       const char *warn_unknown;
+       const char *werror;
 
+       warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS");
+       werror = getenv("KCONFIG_WERROR");
        if (name) {
                in = zconf_fopen(name);
        } else {
@@ -448,6 +450,10 @@ load:
                        if (def == S_DEF_USER) {
                                sym = sym_find(line + 2 + strlen(CONFIG_));
                                if (!sym) {
+                                       if (warn_unknown)
+                                               conf_warning("unknown symbol: %s",
+                                                            line + 2 + strlen(CONFIG_));
+
                                        conf_set_changed(true);
                                        continue;
                                }
@@ -479,7 +485,7 @@ load:
 
                        sym = sym_find(line + strlen(CONFIG_));
                        if (!sym) {
-                               if (def == S_DEF_AUTO)
+                               if (def == S_DEF_AUTO) {
                                        /*
                                         * Reading from include/config/auto.conf
                                         * If CONFIG_FOO previously existed in
@@ -487,8 +493,13 @@ load:
                                         * include/config/FOO must be touched.
                                         */
                                        conf_touch_dep(line + strlen(CONFIG_));
-                               else
+                               } else {
+                                       if (warn_unknown)
+                                               conf_warning("unknown symbol: %s",
+                                                            line + strlen(CONFIG_));
+
                                        conf_set_changed(true);
+                               }
                                continue;
                        }
 
@@ -524,6 +535,10 @@ load:
        }
        free(line);
        fclose(in);
+
+       if (conf_warnings && werror)
+               exit(1);
+
        return 0;
 }
 
@@ -597,169 +612,226 @@ int conf_read(const char *name)
        return 0;
 }
 
-/*
- * Kconfig configuration printer
- *
- * This printer is used when generating the resulting configuration after
- * kconfig invocation and `defconfig' files. Unset symbol might be omitted by
- * passing a non-NULL argument to the printer.
- *
- */
-static void
-kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+struct comment_style {
+       const char *decoration;
+       const char *prefix;
+       const char *postfix;
+};
+
+static const struct comment_style comment_style_pound = {
+       .decoration = "#",
+       .prefix = "#",
+       .postfix = "#",
+};
+
+static const struct comment_style comment_style_c = {
+       .decoration = " *",
+       .prefix = "/*",
+       .postfix = " */",
+};
+
+static void conf_write_heading(FILE *fp, const struct comment_style *cs)
 {
+       if (!cs)
+               return;
 
-       switch (sym->type) {
-       case S_BOOLEAN:
-       case S_TRISTATE:
-               if (*value == 'n') {
-                       bool skip_unset = (arg != NULL);
+       fprintf(fp, "%s\n", cs->prefix);
 
-                       if (!skip_unset)
-                               fprintf(fp, "# %s%s is not set\n",
-                                   CONFIG_, sym->name);
-                       return;
-               }
-               break;
-       default:
-               break;
-       }
+       fprintf(fp, "%s Automatically generated file; DO NOT EDIT.\n",
+               cs->decoration);
+
+       fprintf(fp, "%s %s\n", cs->decoration, rootmenu.prompt->text);
 
-       fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
+       fprintf(fp, "%s\n", cs->postfix);
 }
 
-static void
-kconfig_print_comment(FILE *fp, const char *value, void *arg)
+/* The returned pointer must be freed on the caller side */
+static char *escape_string_value(const char *in)
 {
-       const char *p = value;
-       size_t l;
+       const char *p;
+       char *out;
+       size_t len;
 
-       for (;;) {
-               l = strcspn(p, "\n");
-               fprintf(fp, "#");
-               if (l) {
-                       fprintf(fp, " ");
-                       xfwrite(p, l, 1, fp);
-                       p += l;
-               }
-               fprintf(fp, "\n");
-               if (*p++ == '\0')
+       len = strlen(in) + strlen("\"\"") + 1;
+
+       p = in;
+       while (1) {
+               p += strcspn(p, "\"\\");
+
+               if (p[0] == '\0')
                        break;
+
+               len++;
+               p++;
+       }
+
+       out = xmalloc(len);
+       out[0] = '\0';
+
+       strcat(out, "\"");
+
+       p = in;
+       while (1) {
+               len = strcspn(p, "\"\\");
+               strncat(out, p, len);
+               p += len;
+
+               if (p[0] == '\0')
+                       break;
+
+               strcat(out, "\\");
+               strncat(out, p++, 1);
        }
+
+       strcat(out, "\"");
+
+       return out;
 }
 
-static struct conf_printer kconfig_printer_cb =
+enum output_n { OUTPUT_N, OUTPUT_N_AS_UNSET, OUTPUT_N_NONE };
+
+static void __print_symbol(FILE *fp, struct symbol *sym, enum output_n output_n,
+                          bool escape_string)
 {
-       .print_symbol = kconfig_print_symbol,
-       .print_comment = kconfig_print_comment,
-};
+       const char *val;
+       char *escaped = NULL;
 
-/*
- * Header printer
- *
- * This printer is used when generating the `include/generated/autoconf.h' file.
- */
-static void
-header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+       if (sym->type == S_UNKNOWN)
+               return;
+
+       val = sym_get_string_value(sym);
+
+       if ((sym->type == S_BOOLEAN || sym->type == S_TRISTATE) &&
+           output_n != OUTPUT_N && *val == 'n') {
+               if (output_n == OUTPUT_N_AS_UNSET)
+                       fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name);
+               return;
+       }
+
+       if (sym->type == S_STRING && escape_string) {
+               escaped = escape_string_value(val);
+               val = escaped;
+       }
+
+       fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, val);
+
+       free(escaped);
+}
+
+static void print_symbol_for_dotconfig(FILE *fp, struct symbol *sym)
 {
+       __print_symbol(fp, sym, OUTPUT_N_AS_UNSET, true);
+}
+
+static void print_symbol_for_autoconf(FILE *fp, struct symbol *sym)
+{
+       __print_symbol(fp, sym, OUTPUT_N_NONE, false);
+}
+
+void print_symbol_for_listconfig(struct symbol *sym)
+{
+       __print_symbol(stdout, sym, OUTPUT_N, true);
+}
+
+static void print_symbol_for_c(FILE *fp, struct symbol *sym)
+{
+       const char *val;
+       const char *sym_suffix = "";
+       const char *val_prefix = "";
+       char *escaped = NULL;
+
+       if (sym->type == S_UNKNOWN)
+               return;
+
+       val = sym_get_string_value(sym);
 
        switch (sym->type) {
        case S_BOOLEAN:
-       case S_TRISTATE: {
-               const char *suffix = "";
-
-               switch (*value) {
+       case S_TRISTATE:
+               switch (*val) {
                case 'n':
-                       break;
+                       return;
                case 'm':
-                       suffix = "_MODULE";
+                       sym_suffix = "_MODULE";
                        /* fall through */
                default:
-                       fprintf(fp, "#define %s%s%s 1\n",
-                           CONFIG_, sym->name, suffix);
+                       val = "1";
                }
                break;
-       }
-       case S_HEX: {
-               const char *prefix = "";
-
-               if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
-                       prefix = "0x";
-               fprintf(fp, "#define %s%s %s%s\n",
-                   CONFIG_, sym->name, prefix, value);
+       case S_HEX:
+               if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
+                       val_prefix = "0x";
                break;
-       }
        case S_STRING:
-       case S_INT:
-               fprintf(fp, "#define %s%s %s\n",
-                   CONFIG_, sym->name, value);
-               break;
+               escaped = escape_string_value(val);
+               val = escaped;
        default:
                break;
        }
 
-}
-
-static void
-header_print_comment(FILE *fp, const char *value, void *arg)
-{
-       const char *p = value;
-       size_t l;
+       fprintf(fp, "#define %s%s%s %s%s\n", CONFIG_, sym->name, sym_suffix,
+               val_prefix, val);
 
-       fprintf(fp, "/*\n");
-       for (;;) {
-               l = strcspn(p, "\n");
-               fprintf(fp, " *");
-               if (l) {
-                       fprintf(fp, " ");
-                       xfwrite(p, l, 1, fp);
-                       p += l;
-               }
-               fprintf(fp, "\n");
-               if (*p++ == '\0')
-                       break;
-       }
-       fprintf(fp, " */\n");
+       free(escaped);
 }
 
-static struct conf_printer header_printer_cb =
+static void print_symbol_for_rustccfg(FILE *fp, struct symbol *sym)
 {
-       .print_symbol = header_print_symbol,
-       .print_comment = header_print_comment,
-};
+       const char *val;
+       const char *val_prefix = "";
+       char *val_prefixed = NULL;
+       size_t val_prefixed_len;
+       char *escaped = NULL;
 
-static void conf_write_symbol(FILE *fp, struct symbol *sym,
-                             struct conf_printer *printer, void *printer_arg)
-{
-       const char *str;
+       if (sym->type == S_UNKNOWN)
+               return;
+
+       val = sym_get_string_value(sym);
 
        switch (sym->type) {
-       case S_UNKNOWN:
+       case S_BOOLEAN:
+       case S_TRISTATE:
+               /*
+                * We do not care about disabled ones, i.e. no need for
+                * what otherwise are "comments" in other printers.
+                */
+               if (*val == 'n')
+                       return;
+
+               /*
+                * To have similar functionality to the C macro `IS_ENABLED()`
+                * we provide an empty `--cfg CONFIG_X` here in both `y`
+                * and `m` cases.
+                *
+                * Then, the common `fprintf()` below will also give us
+                * a `--cfg CONFIG_X="y"` or `--cfg CONFIG_X="m"`, which can
+                * be used as the equivalent of `IS_BUILTIN()`/`IS_MODULE()`.
+                */
+               fprintf(fp, "--cfg=%s%s\n", CONFIG_, sym->name);
                break;
-       case S_STRING:
-               str = sym_get_string_value(sym);
-               str = sym_escape_string_value(str);
-               printer->print_symbol(fp, sym, str, printer_arg);
-               free((void *)str);
+       case S_HEX:
+               if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
+                       val_prefix = "0x";
                break;
        default:
-               str = sym_get_string_value(sym);
-               printer->print_symbol(fp, sym, str, printer_arg);
+               break;
        }
-}
 
-static void
-conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
-{
-       char buf[256];
+       if (strlen(val_prefix) > 0) {
+               val_prefixed_len = strlen(val) + strlen(val_prefix) + 1;
+               val_prefixed = xmalloc(val_prefixed_len);
+               snprintf(val_prefixed, val_prefixed_len, "%s%s", val_prefix, val);
+               val = val_prefixed;
+       }
+
+       /* All values get escaped: the `--cfg` option only takes strings */
+       escaped = escape_string_value(val);
+       val = escaped;
 
-       snprintf(buf, sizeof(buf),
-           "\n"
-           "Automatically generated file; DO NOT EDIT.\n"
-           "%s\n",
-           rootmenu.prompt->text);
+       fprintf(fp, "--cfg=%s%s=%s\n", CONFIG_, sym->name, val);
 
-       printer->print_comment(fp, buf, printer_arg);
+       free(escaped);
+       free(val_prefixed);
 }
 
 /*
@@ -818,7 +890,7 @@ int conf_write_defconfig(const char *filename)
                                                goto next_menu;
                                }
                        }
-                       conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
+                       print_symbol_for_dotconfig(out, sym);
                }
 next_menu:
                if (menu->list != NULL) {
@@ -878,7 +950,7 @@ int conf_write(const char *name)
        if (!out)
                return 1;
 
-       conf_write_heading(out, &kconfig_printer_cb, NULL);
+       conf_write_heading(out, &comment_style_pound);
 
        if (!conf_get_changed())
                sym_clear_all_valid();
@@ -905,7 +977,7 @@ int conf_write(const char *name)
                                need_newline = false;
                        }
                        sym->flags |= SYMBOL_WRITTEN;
-                       conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
+                       print_symbol_for_dotconfig(out, sym);
                }
 
 next:
@@ -913,19 +985,20 @@ next:
                        menu = menu->list;
                        continue;
                }
-               if (menu->next)
+
+end_check:
+               if (!menu->sym && menu_is_visible(menu) && menu != &rootmenu &&
+                   menu->prompt->type == P_MENU) {
+                       fprintf(out, "# end of %s\n", menu_get_prompt(menu));
+                       need_newline = true;
+               }
+
+               if (menu->next) {
                        menu = menu->next;
-               else while ((menu = menu->parent)) {
-                       if (!menu->sym && menu_is_visible(menu) &&
-                           menu != &rootmenu) {
-                               str = menu_get_prompt(menu);
-                               fprintf(out, "# end of %s\n", str);
-                               need_newline = true;
-                       }
-                       if (menu->next) {
-                               menu = menu->next;
-                               break;
-                       }
+               } else {
+                       menu = menu->parent;
+                       if (menu)
+                               goto end_check;
                }
        }
        fclose(out);
@@ -955,45 +1028,69 @@ next:
 }
 
 /* write a dependency file as used by kbuild to track dependencies */
-static int conf_write_dep(const char *name)
+static int conf_write_autoconf_cmd(const char *autoconf_name)
 {
+       char name[PATH_MAX], tmp[PATH_MAX];
        struct file *file;
        FILE *out;
+       int ret;
 
-       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);
+       ret = snprintf(name, sizeof(name), "%s.cmd", autoconf_name);
+       if (ret >= sizeof(name)) /* check truncation */
+               return -1;
+
+       if (make_parent_dir(name))
+               return -1;
+
+       ret = snprintf(tmp, sizeof(tmp), "%s.cmd.tmp", autoconf_name);
+       if (ret >= sizeof(tmp)) /* check truncation */
+               return -1;
+
+       out = fopen(tmp, "w");
+       if (!out) {
+               perror("fopen");
+               return -1;
        }
-       fprintf(out, "\n%s: \\\n"
-                    "\t$(deps_config)\n\n", conf_get_autoconfig_name());
 
-       env_write_dep(out, conf_get_autoconfig_name());
+       fprintf(out, "deps_config := \\\n");
+       for (file = file_list; file; file = file->next)
+               fprintf(out, "\t%s \\\n", file->name);
+
+       fprintf(out, "\n%s: $(deps_config)\n\n", autoconf_name);
+
+       env_write_dep(out, autoconf_name);
 
        fprintf(out, "\n$(deps_config): ;\n");
+
+       fflush(out);
+       ret = ferror(out); /* error check for all fprintf() calls */
        fclose(out);
+       if (ret)
+               return -1;
+
+       if (rename(tmp, name)) {
+               perror("rename");
+               return -1;
+       }
 
-       if (make_parent_dir(name))
-               return 1;
-       rename("..config.tmp", name);
        return 0;
 }
 
 static int conf_touch_deps(void)
 {
-       const char *name;
+       const char *name, *tmp;
        struct symbol *sym;
        int res, i;
 
-       strcpy(depfile_path, "include/config/");
-       depfile_prefix_len = strlen(depfile_path);
-
        name = conf_get_autoconfig_name();
+       tmp = strrchr(name, '/');
+       depfile_prefix_len = tmp ? tmp - name + 1 : 0;
+       if (depfile_prefix_len + 1 > sizeof(depfile_path))
+               return -1;
+
+       strncpy(depfile_path, name, depfile_prefix_len);
+       depfile_path[depfile_prefix_len] = 0;
+
        conf_read_simple(name, S_DEF_AUTO);
        sym_calc_value(modules_sym);
 
@@ -1056,13 +1153,54 @@ static int conf_touch_deps(void)
        return 0;
 }
 
+static int __conf_write_autoconf(const char *filename,
+                                void (*print_symbol)(FILE *, struct symbol *),
+                                const struct comment_style *comment_style)
+{
+       char tmp[PATH_MAX];
+       FILE *file;
+       struct symbol *sym;
+       int ret, i;
+
+       if (make_parent_dir(filename))
+               return -1;
+
+       ret = snprintf(tmp, sizeof(tmp), "%s.tmp", filename);
+       if (ret >= sizeof(tmp)) /* check truncation */
+               return -1;
+
+       file = fopen(tmp, "w");
+       if (!file) {
+               perror("fopen");
+               return -1;
+       }
+
+       conf_write_heading(file, comment_style);
+
+       for_all_symbols(i, sym)
+               if ((sym->flags & SYMBOL_WRITE) && sym->name)
+                       print_symbol(file, sym);
+
+       fflush(file);
+       /* check possible errors in conf_write_heading() and print_symbol() */
+       ret = ferror(file);
+       fclose(file);
+       if (ret)
+               return -1;
+
+       if (rename(tmp, filename)) {
+               perror("rename");
+               return -1;
+       }
+
+       return 0;
+}
+
 int conf_write_autoconf(int overwrite)
 {
        struct symbol *sym;
-       const char *name;
        const char *autoconf_name = conf_get_autoconfig_name();
-       FILE *out, *out_h;
-       int i;
+       int ret, i;
 
 #ifndef OPENWRT_DOES_NOT_WANT_THIS
        return 0;
@@ -1070,52 +1208,38 @@ int conf_write_autoconf(int overwrite)
        if (!overwrite && is_present(autoconf_name))
                return 0;
 
-       conf_write_dep("include/config/auto.conf.cmd");
+       ret = conf_write_autoconf_cmd(autoconf_name);
+       if (ret)
+               return -1;
 
        if (conf_touch_deps())
                return 1;
 
-       out = fopen(".tmpconfig", "w");
-       if (!out)
-               return 1;
-
-       out_h = fopen(".tmpconfig.h", "w");
-       if (!out_h) {
-               fclose(out);
-               return 1;
-       }
-
-       conf_write_heading(out, &kconfig_printer_cb, NULL);
-       conf_write_heading(out_h, &header_printer_cb, NULL);
-
-       for_all_symbols(i, sym) {
+       for_all_symbols(i, sym)
                sym_calc_value(sym);
-               if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
-                       continue;
 
-               /* write symbols to auto.conf and autoconf.h */
-               conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
-               conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
-       }
-       fclose(out);
-       fclose(out_h);
+       ret = __conf_write_autoconf(conf_get_autoheader_name(),
+                                   print_symbol_for_c,
+                                   &comment_style_c);
+       if (ret)
+               return ret;
 
-       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;
+       ret = __conf_write_autoconf(conf_get_rustccfg_name(),
+                                   print_symbol_for_rustccfg,
+                                   NULL);
+       if (ret)
+               return ret;
 
-       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.
+        * Create include/config/auto.conf. This must be the last step because
+        * Kbuild has a dependency on auto.conf and this marks the successful
+        * completion of the previous steps.
         */
-       if (rename(".tmpconfig", autoconf_name))
-               return 1;
+       ret = __conf_write_autoconf(conf_get_autoconfig_name(),
+                                   print_symbol_for_autoconf,
+                                   &comment_style_pound);
+       if (ret)
+               return ret;
 
        return 0;
 }
@@ -1125,10 +1249,12 @@ static void (*conf_changed_callback)(void);
 
 void conf_set_changed(bool val)
 {
-       if (conf_changed_callback && conf_changed != val)
-               conf_changed_callback();
+       bool changed = conf_changed != val;
 
        conf_changed = val;
+
+       if (conf_changed_callback && changed)
+               conf_changed_callback();
 }
 
 bool conf_get_changed(void)
index c2fa804fe114027e21537cc07b0649887b44a917..005e27f130e16c0a3837dae4778919bf5b74fb8b 100644 (file)
@@ -276,7 +276,6 @@ struct jump_key {
        struct list_head entries;
        size_t offset;
        struct menu *target;
-       int index;
 };
 
 extern struct file *file_list;
index 0df51ec468a7ab2f260f7e8bdb94f89b4c2d6012..e73b262539eb1a0b899496f6769ac3a74a8c96c7 100644 (file)
@@ -86,8 +86,7 @@ static void warn_ignored_character(char chr)
 n      [A-Za-z0-9_-]
 
 %%
-       int str = 0;
-       int ts, i;
+       char open_quote = 0;
 
 #.*                    /* ignore comment */
 [ \t]*                 /* whitespaces */
@@ -137,7 +136,7 @@ n   [A-Za-z0-9_-]
 ":="                   return T_COLON_EQUAL;
 "+="                   return T_PLUS_EQUAL;
 \"|\'                  {
-                               str = yytext[0];
+                               open_quote = yytext[0];
                                new_string();
                                BEGIN(STRING);
                        }
@@ -174,7 +173,7 @@ n   [A-Za-z0-9_-]
                append_string(yytext + 1, yyleng - 1);
        }
        \'|\"   {
-               if (str == yytext[0]) {
+               if (open_quote == yytext[0]) {
                        BEGIN(INITIAL);
                        yylval.string = text;
                        return T_WORD_QUOTE;
@@ -199,6 +198,8 @@ n   [A-Za-z0-9_-]
 
 <HELP>{
        [ \t]+  {
+               int ts, i;
+
                ts = 0;
                for (i = 0; i < yyleng; i++) {
                        if (yytext[i] == '\t')
index 826c06e4e7bdd0766339e8841425f1353e6422df..c57119fa235caa746644a1b8cc5e4457709bb1db 100644 (file)
@@ -14,6 +14,7 @@
 /* First, we deal with  platform-specific or compiler-specific issues. */
 
 /* begin standard C headers. */
+
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
@@ -30,8 +31,8 @@
 
 #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
+/* C++ systems might need __STDC_LIMIT_MACROS defined before including
+ * <stdint.h>, if you want the limit (max/min) macros for int types.
  */
 #ifndef __STDC_LIMIT_MACROS
 #define __STDC_LIMIT_MACROS 1
@@ -2538,8 +2539,7 @@ YY_DECL
 
        {
 
-       int str = 0;
-       int ts, i;
+       char open_quote = 0;
 
        while ( /*CONSTCOND*/1 )                /* loops until end-of-file is reached */
                {
@@ -2772,7 +2772,7 @@ return T_PLUS_EQUAL;
 case 48:
 YY_RULE_SETUP
 {
-                               str = yytext[0];
+                               open_quote = yytext[0];
                                new_string();
                                BEGIN(STRING);
                        }
@@ -2837,7 +2837,7 @@ YY_RULE_SETUP
 case 58:
 YY_RULE_SETUP
 {
-               if (str == yytext[0]) {
+               if (open_quote == yytext[0]) {
                        BEGIN(INITIAL);
                        yylval.string = text;
                        return T_WORD_QUOTE;
@@ -2869,6 +2869,8 @@ case YY_STATE_EOF(STRING):
 case 60:
 YY_RULE_SETUP
 {
+               int ts, i;
+
                ts = 0;
                for (i = 0; i < yyleng; i++) {
                        if (yytext[i] == '\t')
index a7b18b227635b748fab58ada9ce202065649ed29..1c8717de78e2c5cbb85520f4d0710d3aeba695b5 100644 (file)
@@ -77,7 +77,7 @@ struct gstr str_new(void);
 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);
+char *str_get(struct gstr *gs);
 
 /* menu.c */
 void _menu_init(void);
@@ -100,10 +100,10 @@ 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);
+int get_jump_key_char(void);
 struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
 void menu_get_ext_help(struct menu *menu, struct gstr *help);
 
@@ -126,11 +126,6 @@ static inline struct symbol *sym_get_choice_value(struct symbol *sym)
        return (struct symbol *)sym->curr.val;
 }
 
-static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
-{
-       return sym_set_tristate_value(chval, yes);
-}
-
 static inline bool sym_is_choice(struct symbol *sym)
 {
        return sym->flags & SYMBOL_CHOICE ? true : false;
index ebedd230b32cc19d2029f6cb365d6a7cbd413b4a..4babf6435a1980f35a2ce38179ad34d340dad73c 100644 (file)
@@ -19,7 +19,7 @@ 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);
+void print_symbol_for_listconfig(struct symbol *sym);
 struct symbol ** sym_re_search(const char *pattern);
 const char * sym_type_name(enum symbol_type type);
 void sym_calc_value(struct symbol *sym);
index 3930d93a4adf0de5961686e907050122bd5d79fb..3128bd6d7664d779cd452e729b5a4b6d41fd47ef 100644 (file)
 #endif
 #include <ncurses.h>
 
-/*
- * Colors in ncurses 1.9.9e do not work properly since foreground and
- * background colors are OR'd rather than separately masked.  This version
- * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
- * with standard curses.  The simplest fix (to make this work with standard
- * curses) uses the wbkgdset() function, not used in the original hack.
- * Turn it off if we're building with 1.9.9e, since it just confuses things.
- */
-#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
-#define OLD_NCURSES 1
-#undef  wbkgdset
-#define wbkgdset(w,p)          /*nothing */
-#else
-#define OLD_NCURSES 0
-#endif
-
 #define TR(params) _tracef params
 
 #define KEY_ESC 27
@@ -212,27 +196,12 @@ int first_alpha(const char *string, const char *exempt);
 int dialog_yesno(const char *title, const char *prompt, int height, int width);
 int dialog_msgbox(const char *title, const char *prompt, int height,
                  int width, int pause);
-
-
-typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
-                              *_data);
-int dialog_textbox(const char *title, char *tbuf, int initial_height,
-                  int initial_width, int *keys, int *_vscroll, int *_hscroll,
-                  update_text_fn update_text, void *data);
+int dialog_textbox(const char *title, const char *tbuf, int initial_height,
+                  int initial_width, int *_vscroll, int *_hscroll,
+                  int (*extra_key_cb)(int, size_t, size_t, void *), void *data);
 int dialog_menu(const char *title, const char *prompt,
                const void *selected, int *s_scroll);
 int dialog_checklist(const char *title, const char *prompt, int height,
                     int width, int list_height);
 int dialog_inputbox(const char *title, const char *prompt, int height,
                    int width, const char *init);
-
-/*
- * This is the base for fictitious keys, which activate
- * the buttons.
- *
- * Mouse-generated keys are the following:
- *   -- the first 32 are used as numbers, in addition to '0'-'9'
- *   -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
- *   -- uppercase chars are used to invoke the button (M_EVENT + 'O')
- */
-#define M_EVENT (KEY_MAX+1)
index 428774556674e609d4696369100e2858c7f5e8d5..bcdf3bbac99a8ac0295ab1dd9c3e093c63f3d95d 100644 (file)
@@ -63,15 +63,7 @@ static void do_print_item(WINDOW * win, const char *item, int line_y,
        /* Clear 'residue' of last item */
        wattrset(win, dlg.menubox.atr);
        wmove(win, line_y, 0);
-#if OLD_NCURSES
-       {
-               int i;
-               for (i = 0; i < menu_width; i++)
-                       waddch(win, ' ');
-       }
-#else
        wclrtoeol(win);
-#endif
        wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
        mvwaddstr(win, line_y, item_x, menu_item);
        if (hotkey) {
index b5987735b06cd5e438786a43b7a6866b6c303cae..e02acb7493100d9978a840b66c716cb9aa8bcc49 100644 (file)
 
 #include "dialog.h"
 
-static void back_lines(int n);
-static void print_page(WINDOW *win, int height, int width, update_text_fn
-                      update_text, void *data);
-static void print_line(WINDOW *win, int row, int width);
-static char *get_line(void);
-static void print_position(WINDOW * win);
-
 static int hscroll;
 static int begin_reached, end_reached, page_length;
-static char *buf;
-static char *page;
+static const char *buf, *page;
+static size_t start, end;
+
+/*
+ * Go back 'n' lines in text. Called by dialog_textbox().
+ * 'page' will be updated to point to the desired line in 'buf'.
+ */
+static void back_lines(int n)
+{
+       int i;
+
+       begin_reached = 0;
+       /* Go back 'n' lines */
+       for (i = 0; i < n; i++) {
+               if (*page == '\0') {
+                       if (end_reached) {
+                               end_reached = 0;
+                               continue;
+                       }
+               }
+               if (page == buf) {
+                       begin_reached = 1;
+                       return;
+               }
+               page--;
+               do {
+                       if (page == buf) {
+                               begin_reached = 1;
+                               return;
+                       }
+                       page--;
+               } while (*page != '\n');
+               page++;
+       }
+}
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static char *get_line(void)
+{
+       int i = 0;
+       static char line[MAX_LEN + 1];
+
+       end_reached = 0;
+       while (*page != '\n') {
+               if (*page == '\0') {
+                       end_reached = 1;
+                       break;
+               } else if (i < MAX_LEN)
+                       line[i++] = *(page++);
+               else {
+                       /* Truncate lines longer than MAX_LEN characters */
+                       if (i == MAX_LEN)
+                               line[i++] = '\0';
+                       page++;
+               }
+       }
+       if (i <= MAX_LEN)
+               line[i] = '\0';
+       if (!end_reached)
+               page++;         /* move past '\n' */
+
+       return line;
+}
+
+/*
+ * Print a new line of text.
+ */
+static void print_line(WINDOW *win, int row, int width)
+{
+       char *line;
+
+       line = get_line();
+       line += MIN(strlen(line), hscroll);     /* Scroll horizontally */
+       wmove(win, row, 0);     /* move cursor to correct line */
+       waddch(win, ' ');
+       waddnstr(win, line, MIN(strlen(line), width - 2));
+
+       /* Clear 'residue' of previous line */
+       wclrtoeol(win);
+}
+
+/*
+ * Print a new page of text.
+ */
+static void print_page(WINDOW *win, int height, int width)
+{
+       int i, passed_end = 0;
+
+       page_length = 0;
+       for (i = 0; i < height; i++) {
+               print_line(win, i, width);
+               if (!passed_end)
+                       page_length++;
+               if (end_reached && !passed_end)
+                       passed_end = 1;
+       }
+       wnoutrefresh(win);
+}
+
+/*
+ * Print current position
+ */
+static void print_position(WINDOW *win)
+{
+       int percent;
+
+       wattrset(win, dlg.position_indicator.atr);
+       wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
+       percent = (page - buf) * 100 / strlen(buf);
+       wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
+       wprintw(win, "(%3d%%)", percent);
+}
 
 /*
  * refresh window content
  */
 static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
-                            int cur_y, int cur_x, update_text_fn update_text,
-                            void *data)
+                            int cur_y, int cur_x)
 {
-       print_page(box, boxh, boxw, update_text, data);
+       start = page - buf;
+
+       print_page(box, boxh, boxw);
        print_position(dialog);
        wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
        wrefresh(dialog);
-}
 
+       end = page - buf;
+}
 
 /*
  * Display text from a file in a dialog box.
  *
  * keys is a null-terminated array
- * update_text() may not add or remove any '\n' or '\0' in tbuf
  */
-int dialog_textbox(const char *title, char *tbuf, int initial_height,
-                  int initial_width, int *keys, int *_vscroll, int *_hscroll,
-                  update_text_fn update_text, void *data)
+int dialog_textbox(const char *title, const char *tbuf, int initial_height,
+                  int initial_width, int *_vscroll, int *_hscroll,
+                  int (*extra_key_cb)(int, size_t, size_t, void *), void *data)
 {
        int i, x, y, cur_x, cur_y, key = 0;
        int height, width, boxh, boxw;
@@ -122,8 +230,7 @@ do_resize:
 
        /* Print first page of text */
        attr_clear(box, boxh, boxw, dlg.dialog.atr);
-       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
-                        data);
+       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
 
        while (!done) {
                key = wgetch(dialog);
@@ -142,8 +249,7 @@ do_resize:
                                begin_reached = 1;
                                page = buf;
                                refresh_text_box(dialog, box, boxh, boxw,
-                                                cur_y, cur_x, update_text,
-                                                data);
+                                                cur_y, cur_x);
                        }
                        break;
                case 'G':       /* Last page */
@@ -153,8 +259,7 @@ do_resize:
                        /* point to last char in buf */
                        page = buf + strlen(buf);
                        back_lines(boxh);
-                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
-                                        cur_x, update_text, data);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
                        break;
                case 'K':       /* Previous line */
                case 'k':
@@ -163,8 +268,7 @@ do_resize:
                                break;
 
                        back_lines(page_length + 1);
-                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
-                                        cur_x, update_text, data);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
                        break;
                case 'B':       /* Previous page */
                case 'b':
@@ -173,8 +277,7 @@ do_resize:
                        if (begin_reached)
                                break;
                        back_lines(page_length + boxh);
-                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
-                                        cur_x, update_text, data);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
                        break;
                case 'J':       /* Next line */
                case 'j':
@@ -183,8 +286,7 @@ do_resize:
                                break;
 
                        back_lines(page_length - 1);
-                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
-                                        cur_x, update_text, data);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
                        break;
                case KEY_NPAGE: /* Next page */
                case ' ':
@@ -193,8 +295,7 @@ do_resize:
                                break;
 
                        begin_reached = 0;
-                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
-                                        cur_x, update_text, data);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
                        break;
                case '0':       /* Beginning of line */
                case 'H':       /* Scroll left */
@@ -209,8 +310,7 @@ do_resize:
                                hscroll--;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
-                                        cur_x, update_text, data);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
                        break;
                case 'L':       /* Scroll right */
                case 'l':
@@ -220,8 +320,7 @@ do_resize:
                        hscroll++;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
-                                        cur_x, update_text, data);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
                        break;
                case KEY_ESC:
                        if (on_key_esc(dialog) == KEY_ESC)
@@ -234,11 +333,9 @@ do_resize:
                        on_key_resize();
                        goto do_resize;
                default:
-                       for (i = 0; keys[i]; i++) {
-                               if (key == keys[i]) {
-                                       done = true;
-                                       break;
-                               }
+                       if (extra_key_cb && extra_key_cb(key, start, end, data)) {
+                               done = true;
+                               break;
                        }
                }
        }
@@ -259,137 +356,3 @@ do_resize:
                *_hscroll = hscroll;
        return key;
 }
-
-/*
- * Go back 'n' lines in text. Called by dialog_textbox().
- * 'page' will be updated to point to the desired line in 'buf'.
- */
-static void back_lines(int n)
-{
-       int i;
-
-       begin_reached = 0;
-       /* Go back 'n' lines */
-       for (i = 0; i < n; i++) {
-               if (*page == '\0') {
-                       if (end_reached) {
-                               end_reached = 0;
-                               continue;
-                       }
-               }
-               if (page == buf) {
-                       begin_reached = 1;
-                       return;
-               }
-               page--;
-               do {
-                       if (page == buf) {
-                               begin_reached = 1;
-                               return;
-                       }
-                       page--;
-               } while (*page != '\n');
-               page++;
-       }
-}
-
-/*
- * Print a new page of text.
- */
-static void print_page(WINDOW *win, int height, int width, update_text_fn
-                      update_text, void *data)
-{
-       int i, passed_end = 0;
-
-       if (update_text) {
-               char *end;
-
-               for (i = 0; i < height; i++)
-                       get_line();
-               end = page;
-               back_lines(height);
-               update_text(buf, page - buf, end - buf, data);
-       }
-
-       page_length = 0;
-       for (i = 0; i < height; i++) {
-               print_line(win, i, width);
-               if (!passed_end)
-                       page_length++;
-               if (end_reached && !passed_end)
-                       passed_end = 1;
-       }
-       wnoutrefresh(win);
-}
-
-/*
- * Print a new line of text.
- */
-static void print_line(WINDOW * win, int row, int width)
-{
-       char *line;
-
-       line = get_line();
-       line += MIN(strlen(line), hscroll);     /* Scroll horizontally */
-       wmove(win, row, 0);     /* move cursor to correct line */
-       waddch(win, ' ');
-       waddnstr(win, line, MIN(strlen(line), width - 2));
-
-       /* Clear 'residue' of previous line */
-#if OLD_NCURSES
-       {
-               int x = getcurx(win);
-               int i;
-               for (i = 0; i < width - x; i++)
-                       waddch(win, ' ');
-       }
-#else
-       wclrtoeol(win);
-#endif
-}
-
-/*
- * Return current line of text. Called by dialog_textbox() and print_line().
- * 'page' should point to start of current line before calling, and will be
- * updated to point to start of next line.
- */
-static char *get_line(void)
-{
-       int i = 0;
-       static char line[MAX_LEN + 1];
-
-       end_reached = 0;
-       while (*page != '\n') {
-               if (*page == '\0') {
-                       end_reached = 1;
-                       break;
-               } else if (i < MAX_LEN)
-                       line[i++] = *(page++);
-               else {
-                       /* Truncate lines longer than MAX_LEN characters */
-                       if (i == MAX_LEN)
-                               line[i++] = '\0';
-                       page++;
-               }
-       }
-       if (i <= MAX_LEN)
-               line[i] = '\0';
-       if (!end_reached)
-               page++;         /* move past '\n' */
-
-       return line;
-}
-
-/*
- * Print current position
- */
-static void print_position(WINDOW * win)
-{
-       int percent;
-
-       wattrset(win, dlg.position_indicator.atr);
-       wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
-       percent = (page - buf) * 100 / strlen(buf);
-       wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
-       wprintw(win, "(%3d%%)", percent);
-}
index 35723692880e6bab170f0d9561dd8e8903c4276f..4e48cc1d57b8d79a380c3c813355f8d396585b84 100755 (executable)
@@ -1,19 +1,22 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0-only
 
+cflags=$1
+libs=$2
+
 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)\"
+if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then
+       if ${HOSTPKG_CONFIG} --exists $PKG; then
+               ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
+               ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
                exit 0
        fi
 
-       if pkg-config --exists $PKG2; then
-               echo cflags=\"$(pkg-config --cflags $PKG2)\"
-               echo libs=\"$(pkg-config --libs $PKG2)\"
+       if ${HOSTPKG_CONFIG} --exists ${PKG2}; then
+               ${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags}
+               ${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs}
                exit 0
        fi
 fi
@@ -22,22 +25,22 @@ fi
 # (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\"
+       echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags}
+       echo -lncursesw > ${libs}
        exit 0
 fi
 
 if [ -f /usr/include/ncurses/ncurses.h ]; then
-       echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
-       echo libs=\"-lncurses\"
+       echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags}
+       echo -lncurses > ${libs}
        exit 0
 fi
 
 # As a final fallback before giving up, check if $HOSTCC knows of a default
 # ncurses installation (e.g. from a vendor-specific sysroot).
 if echo '#include <ncurses.h>' | ${HOSTCC} -E - >/dev/null 2>&1; then
-       echo cflags=\"-D_GNU_SOURCE\"
-       echo libs=\"-lncurses\"
+       echo -D_GNU_SOURCE > ${cflags}
+       echo -lncurses > ${libs}
        exit 0
 fi
 
@@ -46,7 +49,7 @@ 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 "*"
-echo >&2 "* You may also need to install pkg-config to find the"
+echo >&2 "* You may also need to install ${HOSTPKG_CONFIG} to find the"
 echo >&2 "* ncurses installed in a non-default location."
 echo >&2 "*"
 exit 1
index 81d232b66562bf69b6ac8cb4113b15be26dec3fb..d357cf11003906ee89dfad441357aee94f898a8e 100644 (file)
@@ -22,8 +22,6 @@
 #include "lkc.h"
 #include "lxdialog/dialog.h"
 
-#define JUMP_NB                        9
-
 static const char mconf_readme[] =
 "OpenWrt config is based on Kernel kconfig\n"
 "so ipkg packages are referred here as modules.\n"
@@ -164,6 +162,12 @@ static const char mconf_readme[] =
 "(especially with a larger number of unrolled categories) than the\n"
 "default mode.\n"
 "\n"
+
+"Search\n"
+"-------\n"
+"Pressing the forward-slash (/) anywhere brings up a search dialog box.\n"
+"\n"
+
 "Different color themes available\n"
 "--------------------------------\n"
 "It is possible to select different color themes using the variable\n"
@@ -285,18 +289,9 @@ static int single_menu_mode;
 static int show_all_options;
 static int save_and_exit;
 static int silent;
+static int jump_key_char;
 
 static void conf(struct menu *menu, struct menu *active_menu);
-static void conf_choice(struct menu *menu);
-static void conf_string(struct menu *menu);
-static void conf_load(void);
-static void conf_save(void);
-static int show_textbox_ext(const char *title, char *text, int r, int c,
-                           int *keys, int *vscroll, int *hscroll,
-                           update_text_fn update_text, void *data);
-static void show_textbox(const char *title, const char *text, int r, int c);
-static void show_helptext(const char *title, const char *text);
-static void show_help(struct menu *menu);
 
 static char filename[PATH_MAX+1];
 static void set_config_filename(const char *config_filename)
@@ -355,37 +350,87 @@ static void reset_subtitle(void)
        set_dialog_subtitles(subtitles);
 }
 
+static int show_textbox_ext(const char *title, const char *text, int r, int c,
+                           int *vscroll, int *hscroll,
+                           int (*extra_key_cb)(int, size_t, size_t, void *),
+                           void *data)
+{
+       dialog_clear();
+       return dialog_textbox(title, text, r, c, vscroll, hscroll,
+                             extra_key_cb, data);
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+       show_textbox_ext(title, text, r, c, NULL, NULL, NULL, NULL);
+}
+
+static void show_helptext(const char *title, const char *text)
+{
+       show_textbox(title, text, 0, 0);
+}
+
+static void show_help(struct menu *menu)
+{
+       struct gstr help = str_new();
+
+       help.max_width = getmaxx(stdscr) - 10;
+       menu_get_ext_help(menu, &help);
+
+       show_helptext(menu_get_prompt(menu), str_get(&help));
+       str_free(&help);
+}
+
 struct search_data {
        struct list_head *head;
-       struct menu **targets;
-       int *keys;
+       struct menu *target;
 };
 
-static void update_text(char *buf, size_t start, size_t end, void *_data)
+static int next_jump_key(int key)
+{
+       if (key < '1' || key > '9')
+               return '1';
+
+       key++;
+
+       if (key > '9')
+               key = '1';
+
+       return key;
+}
+
+static int handle_search_keys(int key, size_t start, size_t end, void *_data)
 {
        struct search_data *data = _data;
        struct jump_key *pos;
-       int k = 0;
+       int index = 0;
+
+       if (key < '1' || key > '9')
+               return 0;
 
        list_for_each_entry(pos, data->head, entries) {
-               if (pos->offset >= start && pos->offset < end) {
-                       char header[4];
+               index = next_jump_key(index);
 
-                       if (k < JUMP_NB) {
-                               int key = '0' + (pos->index % JUMP_NB) + 1;
+               if (pos->offset < start)
+                       continue;
 
-                               sprintf(header, "(%c)", key);
-                               data->keys[k] = key;
-                               data->targets[k] = pos->target;
-                               k++;
-                       } else {
-                               sprintf(header, "   ");
-                       }
+               if (pos->offset >= end)
+                       break;
 
-                       memcpy(buf + pos->offset, header, sizeof(header) - 1);
+               if (key == index) {
+                       data->target = pos->target;
+                       return 1;
                }
        }
-       data->keys[k] = 0;
+
+       return 0;
+}
+
+int get_jump_key_char(void)
+{
+       jump_key_char = next_jump_key(jump_key_char);
+
+       return jump_key_char;
 }
 
 static void search_conf(void)
@@ -432,27 +477,23 @@ again:
        sym_arr = sym_re_search(dialog_input);
        do {
                LIST_HEAD(head);
-               struct menu *targets[JUMP_NB];
-               int keys[JUMP_NB + 1], i;
                struct search_data data = {
                        .head = &head,
-                       .targets = targets,
-                       .keys = keys,
                };
                struct jump_key *pos, *tmp;
 
+               jump_key_char = 0;
                res = get_relations_str(sym_arr, &head);
                set_subtitle();
-               dres = show_textbox_ext("Search Results", (char *)
-                                       str_get(&res), 0, 0, keys, &vscroll,
-                                       &hscroll, &update_text, (void *)
-                                       &data);
+               dres = show_textbox_ext("Search Results", str_get(&res), 0, 0,
+                                       &vscroll, &hscroll,
+                                       handle_search_keys, &data);
                again = false;
-               for (i = 0; i < JUMP_NB && keys[i]; i++)
-                       if (dres == keys[i]) {
-                               conf(targets[i]->parent, targets[i]);
-                               again = true;
-                       }
+               if (dres >= '1' && dres <= '9') {
+                       assert(data.target != NULL);
+                       conf(data.target->parent, data.target);
+                       again = true;
+               }
                str_free(&res);
                list_for_each_entry_safe(pos, tmp, &head, entries)
                        free(pos);
@@ -641,158 +682,6 @@ conf_childs:
        indent -= doint;
 }
 
-static void conf(struct menu *menu, struct menu *active_menu)
-{
-       struct menu *submenu;
-       const char *prompt = menu_get_prompt(menu);
-       struct subtitle_part stpart;
-       struct symbol *sym;
-       int res;
-       int s_scroll = 0;
-
-       if (menu != &rootmenu)
-               stpart.text = menu_get_prompt(menu);
-       else
-               stpart.text = NULL;
-       list_add_tail(&stpart.entries, &trail);
-
-       while (1) {
-               item_reset();
-               current_menu = menu;
-               build_conf(menu);
-               if (!child_count)
-                       break;
-               set_subtitle();
-               dialog_clear();
-               res = dialog_menu(prompt ? prompt : "Main Menu",
-                                 menu_instructions,
-                                 active_menu, &s_scroll);
-               if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
-                       break;
-               if (item_count() != 0) {
-                       if (!item_activate_selected())
-                               continue;
-                       if (!item_tag())
-                               continue;
-               }
-               submenu = item_data();
-               active_menu = item_data();
-               if (submenu)
-                       sym = submenu->sym;
-               else
-                       sym = NULL;
-
-               switch (res) {
-               case 0:
-                       switch (item_tag()) {
-                       case 'm':
-                               if (single_menu_mode)
-                                       submenu->data = (void *) (long) !submenu->data;
-                               else
-                                       conf(submenu, NULL);
-                               break;
-                       case 't':
-                               if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
-                                       conf_choice(submenu);
-                               else if (submenu->prompt->type == P_MENU)
-                                       conf(submenu, NULL);
-                               break;
-                       case 's':
-                               conf_string(submenu);
-                               break;
-                       }
-                       break;
-               case 2:
-                       if (sym)
-                               show_help(submenu);
-                       else {
-                               reset_subtitle();
-                               show_helptext("README", mconf_readme);
-                       }
-                       break;
-               case 3:
-                       reset_subtitle();
-                       conf_save();
-                       break;
-               case 4:
-                       reset_subtitle();
-                       conf_load();
-                       break;
-               case 5:
-                       if (item_is_tag('t')) {
-                               if (sym_set_tristate_value(sym, yes))
-                                       break;
-                               if (sym_set_tristate_value(sym, mod))
-                                       show_textbox(NULL, setmod_text, 6, 74);
-                       }
-                       break;
-               case 6:
-                       if (item_is_tag('t'))
-                               sym_set_tristate_value(sym, no);
-                       break;
-               case 7:
-                       if (item_is_tag('t'))
-                               sym_set_tristate_value(sym, mod);
-                       break;
-               case 8:
-                       if (item_is_tag('t'))
-                               sym_toggle_tristate_value(sym);
-                       else if (item_is_tag('m'))
-                               conf(submenu, NULL);
-                       break;
-               case 9:
-                       search_conf();
-                       break;
-               case 10:
-                       show_all_options = !show_all_options;
-                       break;
-               }
-       }
-
-       list_del(trail.prev);
-}
-
-static int show_textbox_ext(const char *title, char *text, int r, int c, int
-                           *keys, int *vscroll, int *hscroll, update_text_fn
-                           update_text, void *data)
-{
-       dialog_clear();
-       return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
-                             update_text, data);
-}
-
-static void show_textbox(const char *title, const char *text, int r, int c)
-{
-       show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
-                        NULL, NULL);
-}
-
-static void show_helptext(const char *title, const char *text)
-{
-       show_textbox(title, text, 0, 0);
-}
-
-static void conf_message_callback(const char *s)
-{
-       if (save_and_exit) {
-               if (!silent)
-                       printf("%s", s);
-       } else {
-               show_textbox(NULL, s, 6, 60);
-       }
-}
-
-static void show_help(struct menu *menu)
-{
-       struct gstr help = str_new();
-
-       help.max_width = getmaxx(stdscr) - 10;
-       menu_get_ext_help(menu, &help);
-
-       show_helptext(menu_get_prompt(menu), str_get(&help));
-       str_free(&help);
-}
-
 static void conf_choice(struct menu *menu)
 {
        const char *prompt = menu_get_prompt(menu);
@@ -958,6 +847,127 @@ static void conf_save(void)
        }
 }
 
+static void conf(struct menu *menu, struct menu *active_menu)
+{
+       struct menu *submenu;
+       const char *prompt = menu_get_prompt(menu);
+       struct subtitle_part stpart;
+       struct symbol *sym;
+       int res;
+       int s_scroll = 0;
+
+       if (menu != &rootmenu)
+               stpart.text = menu_get_prompt(menu);
+       else
+               stpart.text = NULL;
+       list_add_tail(&stpart.entries, &trail);
+
+       while (1) {
+               item_reset();
+               current_menu = menu;
+               build_conf(menu);
+               if (!child_count)
+                       break;
+               set_subtitle();
+               dialog_clear();
+               res = dialog_menu(prompt ? prompt : "Main Menu",
+                                 menu_instructions,
+                                 active_menu, &s_scroll);
+               if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
+                       break;
+               if (item_count() != 0) {
+                       if (!item_activate_selected())
+                               continue;
+                       if (!item_tag())
+                               continue;
+               }
+               submenu = item_data();
+               active_menu = item_data();
+               if (submenu)
+                       sym = submenu->sym;
+               else
+                       sym = NULL;
+
+               switch (res) {
+               case 0:
+                       switch (item_tag()) {
+                       case 'm':
+                               if (single_menu_mode)
+                                       submenu->data = (void *) (long) !submenu->data;
+                               else
+                                       conf(submenu, NULL);
+                               break;
+                       case 't':
+                               if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
+                                       conf_choice(submenu);
+                               else if (submenu->prompt->type == P_MENU)
+                                       conf(submenu, NULL);
+                               break;
+                       case 's':
+                               conf_string(submenu);
+                               break;
+                       }
+                       break;
+               case 2:
+                       if (sym)
+                               show_help(submenu);
+                       else {
+                               reset_subtitle();
+                               show_helptext("README", mconf_readme);
+                       }
+                       break;
+               case 3:
+                       reset_subtitle();
+                       conf_save();
+                       break;
+               case 4:
+                       reset_subtitle();
+                       conf_load();
+                       break;
+               case 5:
+                       if (item_is_tag('t')) {
+                               if (sym_set_tristate_value(sym, yes))
+                                       break;
+                               if (sym_set_tristate_value(sym, mod))
+                                       show_textbox(NULL, setmod_text, 6, 74);
+                       }
+                       break;
+               case 6:
+                       if (item_is_tag('t'))
+                               sym_set_tristate_value(sym, no);
+                       break;
+               case 7:
+                       if (item_is_tag('t'))
+                               sym_set_tristate_value(sym, mod);
+                       break;
+               case 8:
+                       if (item_is_tag('t'))
+                               sym_toggle_tristate_value(sym);
+                       else if (item_is_tag('m'))
+                               conf(submenu, NULL);
+                       break;
+               case 9:
+                       search_conf();
+                       break;
+               case 10:
+                       show_all_options = !show_all_options;
+                       break;
+               }
+       }
+
+       list_del(trail.prev);
+}
+
+static void conf_message_callback(const char *s)
+{
+       if (save_and_exit) {
+               if (!silent)
+                       printf("%s", s);
+       } else {
+               show_textbox(NULL, s, 6, 60);
+       }
+}
+
 static int handle_exit(void)
 {
        int res;
index 22fd26a9f7147e79578efa8ad3b1872ae6f792f8..d41a61a73a490d29ee96c864e70c40be7d48712b 100644 (file)
@@ -661,11 +661,6 @@ const char *menu_get_prompt(struct menu *menu)
        return NULL;
 }
 
-struct menu *menu_get_root_menu(struct menu *menu)
-{
-       return &rootmenu;
-}
-
 struct menu *menu_get_parent_menu(struct menu *menu)
 {
        enum prop_type type;
@@ -706,6 +701,11 @@ static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
        }
 }
 
+int __attribute__((weak)) get_jump_key_char(void)
+{
+       return -1;
+}
+
 static void get_prompt_str(struct gstr *r, struct property *prop,
                           struct list_head *head)
 {
@@ -727,52 +727,41 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
        if (!expr_eq(prop->menu->dep, prop->visible.expr))
                get_dep_str(r, prop->visible.expr, "  Visible if: ");
 
-       menu = prop->menu->parent;
+       menu = prop->menu;
        for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
-               bool accessible = menu_is_visible(menu);
-
                submenu[i++] = menu;
-               if (location == NULL && accessible)
+               if (location == NULL && menu_is_visible(menu))
                        location = menu;
        }
        if (head && location) {
                jump = xmalloc(sizeof(struct jump_key));
+               jump->target = location;
+               list_add_tail(&jump->entries, head);
+       }
 
-               if (menu_is_visible(prop->menu)) {
-                       /*
-                        * There is not enough room to put the hint at the
-                        * beginning of the "Prompt" line. Put the hint on the
-                        * last "Location" line even when it would belong on
-                        * the former.
-                        */
-                       jump->target = prop->menu;
-               } else
-                       jump->target = location;
+       str_printf(r, "  Location:\n");
+       for (j = 0; --i >= 0; j++) {
+               int jk = -1;
+               int indent = 2 * j + 4;
 
-               if (list_empty(head))
-                       jump->index = 0;
-               else
-                       jump->index = list_entry(head->prev, struct jump_key,
-                                                entries)->index + 1;
+               menu = submenu[i];
+               if (jump && menu == location) {
+                       jump->offset = strlen(r->s);
+                       jk = get_jump_key_char();
+               }
 
-               list_add_tail(&jump->entries, head);
-       }
+               if (jk >= 0) {
+                       str_printf(r, "(%c)", jk);
+                       indent -= 3;
+               }
 
-       if (i > 0) {
-               str_printf(r, "  Location:\n");
-               for (j = 4; --i >= 0; j += 2) {
-                       menu = submenu[i];
-                       if (jump && menu == location)
-                               jump->offset = strlen(r->s);
-                       str_printf(r, "%*c-> %s", j, ' ',
-                                  menu_get_prompt(menu));
-                       if (menu->sym) {
-                               str_printf(r, " (%s [=%s])", menu->sym->name ?
-                                       menu->sym->name : "<choice>",
-                                       sym_get_string_value(menu->sym));
-                       }
-                       str_append(r, "\n");
+               str_printf(r, "%*c-> %s", indent, ' ', menu_get_prompt(menu));
+               if (menu->sym) {
+                       str_printf(r, " (%s [=%s])", menu->sym->name ?
+                               menu->sym->name : "<choice>",
+                               sym_get_string_value(menu->sym));
                }
+               str_append(r, "\n");
        }
 }
 
index a22730928397e3fa8f96d5df2a305a965965d304..9d4096074941e659c2ea99b67f3f14e014b94880 100755 (executable)
@@ -1,19 +1,22 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0-only
 
+cflags=$1
+libs=$2
+
 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)\"
+if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then
+       if ${HOSTPKG_CONFIG} --exists $PKG; then
+               ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
+               ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
                exit 0
        fi
 
-       if pkg-config --exists $PKG2; then
-               echo cflags=\"$(pkg-config --cflags $PKG2)\"
-               echo libs=\"$(pkg-config --libs $PKG2)\"
+       if ${HOSTPKG_CONFIG} --exists $PKG2; then
+               ${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags}
+               ${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs}
                exit 0
        fi
 fi
@@ -22,20 +25,20 @@ fi
 # (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\"
+       echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags}
+       echo -lncursesw -lmenuw -lpanelw > ${libs}
        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\"
+       echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags}
+       echo -lncurses -lmenu -lpanel > ${libs}
        exit 0
 fi
 
 if [ -f /usr/include/ncurses.h ]; then
-       echo cflags=\"-D_GNU_SOURCE\"
-       echo libs=\"-lncurses -lmenu -lpanel\"
+       echo -D_GNU_SOURCE > ${cflags}
+       echo -lncurses -lmenu -lpanel > ${libs}
        exit 0
 fi
 
@@ -44,7 +47,7 @@ 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 "*"
-echo >&2 "* You may also need to install pkg-config to find the"
+echo >&2 "* You may also need to install ${HOSTPKG_CONFIG} to find the"
 echo >&2 "* ncurses installed in a non-default location."
 echo >&2 "*"
 exit 1
index b75cabe017cabdc701753fa1f6707496d79e6d2d..ece86726efd6cea1c85ee2ad492020b55eff65e1 100644 (file)
@@ -55,8 +55,8 @@ static const char nconf_global_help[] =
 "\n"
 "Menu navigation keys\n"
 "----------------------------------------------------------------------\n"
-"Linewise up                 <Up>\n"
-"Linewise down               <Down>\n"
+"Linewise up                 <Up>    <k>\n"
+"Linewise down               <Down>  <j>\n"
 "Pagewise up                 <Page Up>\n"
 "Pagewise down               <Page Down>\n"
 "First entry                 <Home>\n"
@@ -223,7 +223,7 @@ search_help[] =
 "Location:\n"
 "  -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
 "    -> PCI support (PCI [ = y])\n"
-"      -> PCI access mode (<choice> [ = y])\n"
+"(1)   -> PCI access mode (<choice> [ = y])\n"
 "Selects: LIBCRC32\n"
 "Selected by: BAR\n"
 "-----------------------------------------------------------------\n"
@@ -234,9 +234,13 @@ search_help[] =
 "o  The 'Depends on:' line lists symbols that need to be defined for\n"
 "   this symbol to be visible and selectable in the menu.\n"
 "o  The 'Location:' lines tell, where in the menu structure this symbol\n"
-"   is located.  A location followed by a [ = y] indicates that this is\n"
-"   a selectable menu item, and the current value is displayed inside\n"
-"   brackets.\n"
+"   is located.\n"
+"     A location followed by a [ = y] indicates that this is\n"
+"     a selectable menu item, and the current value is displayed inside\n"
+"     brackets.\n"
+"     Press the key in the (#) prefix to jump directly to that\n"
+"     location. You will be returned to the current search results\n"
+"     after exiting this new menu.\n"
 "o  The 'Selects:' line tells, what symbol will be automatically selected\n"
 "   if this symbol is selected (y or m).\n"
 "o  The 'Selected by' line tells what symbol has selected this symbol.\n"
@@ -278,7 +282,9 @@ static const char *current_instructions = menu_instructions;
 
 static char *dialog_input_result;
 static int dialog_input_result_len;
+static int jump_key_char;
 
+static void selected_conf(struct menu *menu, struct menu *active_menu);
 static void conf(struct menu *menu);
 static void conf_choice(struct menu *menu);
 static void conf_string(struct menu *menu);
@@ -688,6 +694,57 @@ static int do_exit(void)
        return 0;
 }
 
+struct search_data {
+       struct list_head *head;
+       struct menu *target;
+};
+
+static int next_jump_key(int key)
+{
+       if (key < '1' || key > '9')
+               return '1';
+
+       key++;
+
+       if (key > '9')
+               key = '1';
+
+       return key;
+}
+
+static int handle_search_keys(int key, size_t start, size_t end, void *_data)
+{
+       struct search_data *data = _data;
+       struct jump_key *pos;
+       int index = 0;
+
+       if (key < '1' || key > '9')
+               return 0;
+
+       list_for_each_entry(pos, data->head, entries) {
+               index = next_jump_key(index);
+
+               if (pos->offset < start)
+                       continue;
+
+               if (pos->offset >= end)
+                       break;
+
+               if (key == index) {
+                       data->target = pos->target;
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+int get_jump_key_char(void)
+{
+       jump_key_char = next_jump_key(jump_key_char);
+
+       return jump_key_char;
+}
 
 static void search_conf(void)
 {
@@ -695,7 +752,8 @@ static void search_conf(void)
        struct gstr res;
        struct gstr title;
        char *dialog_input;
-       int dres;
+       int dres, vscroll = 0, hscroll = 0;
+       bool again;
 
        title = str_new();
        str_printf( &title, "Enter (sub)string or regexp to search for "
@@ -724,11 +782,28 @@ again:
                dialog_input += strlen(CONFIG_);
 
        sym_arr = sym_re_search(dialog_input);
-       res = get_relations_str(sym_arr, NULL);
+
+       do {
+               LIST_HEAD(head);
+               struct search_data data = {
+                       .head = &head,
+                       .target = NULL,
+               };
+               jump_key_char = 0;
+               res = get_relations_str(sym_arr, &head);
+               dres = show_scroll_win_ext(main_window,
+                               "Search Results", str_get(&res),
+                               &vscroll, &hscroll,
+                               handle_search_keys, &data);
+               again = false;
+               if (dres >= '1' && dres <= '9') {
+                       assert(data.target != NULL);
+                       selected_conf(data.target->parent, data.target);
+                       again = true;
+               }
+               str_free(&res);
+       } while (again);
        free(sym_arr);
-       show_scroll_win(main_window,
-                       "Search Results", str_get(&res));
-       str_free(&res);
        str_free(&title);
 }
 
@@ -1065,10 +1140,15 @@ static int do_match(int key, struct match_state *state, int *ans)
 }
 
 static void conf(struct menu *menu)
+{
+       selected_conf(menu, NULL);
+}
+
+static void selected_conf(struct menu *menu, struct menu *active_menu)
 {
        struct menu *submenu = NULL;
        struct symbol *sym;
-       int res;
+       int i, res;
        int current_index = 0;
        int last_top_row = 0;
        struct match_state match_state = {
@@ -1084,6 +1164,19 @@ static void conf(struct menu *menu)
                if (!child_count)
                        break;
 
+               if (active_menu != NULL) {
+                       for (i = 0; i < items_num; i++) {
+                               struct mitem *mcur;
+
+                               mcur = (struct mitem *) item_userptr(curses_menu_items[i]);
+                               if ((struct menu *) mcur->usrptr == active_menu) {
+                                       current_index = i;
+                                       break;
+                               }
+                       }
+                       active_menu = NULL;
+               }
+
                show_menu(menu_get_prompt(menu), menu_instructions,
                          current_index, &last_top_row);
                keypad((menu_win(curses_menu)), TRUE);
@@ -1108,9 +1201,11 @@ static void conf(struct menu *menu)
                                break;
                        switch (res) {
                        case KEY_DOWN:
+                       case 'j':
                                menu_driver(curses_menu, REQ_DOWN_ITEM);
                                break;
                        case KEY_UP:
+                       case 'k':
                                menu_driver(curses_menu, REQ_UP_ITEM);
                                break;
                        case KEY_NPAGE:
@@ -1291,9 +1386,11 @@ static void conf_choice(struct menu *menu)
                                break;
                        switch (res) {
                        case KEY_DOWN:
+                       case 'j':
                                menu_driver(curses_menu, REQ_DOWN_ITEM);
                                break;
                        case KEY_UP:
+                       case 'k':
                                menu_driver(curses_menu, REQ_UP_ITEM);
                                break;
                        case KEY_NPAGE:
index c72d61a7725e5a7134ec19538e286414ab7515f2..48ba1c1a07f5aefc5d82d1f94148ef7b06ca7182 100644 (file)
@@ -497,10 +497,17 @@ void refresh_all_windows(WINDOW *main_window)
        refresh();
 }
 
-/* layman's scrollable window... */
 void show_scroll_win(WINDOW *main_window,
                const char *title,
                const char *text)
+{
+       (void)show_scroll_win_ext(main_window, title, (char *)text, NULL, NULL, NULL, NULL);
+}
+
+/* layman's scrollable window... */
+int show_scroll_win_ext(WINDOW *main_window, const char *title, char *text,
+                       int *vscroll, int *hscroll,
+                       extra_key_cb_fn extra_key_cb, void *data)
 {
        int res;
        int total_lines = get_line_no(text);
@@ -514,6 +521,12 @@ void show_scroll_win(WINDOW *main_window,
        WINDOW *win;
        WINDOW *pad;
        PANEL *panel;
+       bool done = false;
+
+       if (hscroll)
+               start_x = *hscroll;
+       if (vscroll)
+               start_y = *vscroll;
 
        getmaxyx(stdscr, lines, columns);
 
@@ -549,8 +562,7 @@ void show_scroll_win(WINDOW *main_window,
        panel = new_panel(win);
 
        /* handle scrolling */
-       do {
-
+       while (!done) {
                copywin(pad, win, start_y, start_x, 2, 2, text_lines,
                                text_cols, 0);
                print_in_middle(win,
@@ -593,8 +605,18 @@ void show_scroll_win(WINDOW *main_window,
                case 'l':
                        start_x++;
                        break;
+               default:
+                       if (extra_key_cb) {
+                               size_t start = (get_line(text, start_y) - text);
+                               size_t end = (get_line(text, start_y + text_lines) - text);
+
+                               if (extra_key_cb(res, start, end, data)) {
+                                       done = true;
+                                       break;
+                               }
+                       }
                }
-               if (res == 10 || res == 27 || res == 'q' ||
+               if (res == 0 || res == 10 || res == 27 || res == 'q' ||
                        res == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||
                        res == KEY_F(F_EXIT))
                        break;
@@ -606,9 +628,14 @@ void show_scroll_win(WINDOW *main_window,
                        start_x = 0;
                if (start_x >= total_cols-text_cols)
                        start_x = total_cols-text_cols;
-       } while (res);
+       }
 
+       if (hscroll)
+               *hscroll = start_x;
+       if (vscroll)
+               *vscroll = start_y;
        del_panel(panel);
        delwin(win);
        refresh_all_windows(main_window);
+       return res;
 }
index 6e127c63d5773a5e3659effbba4c689354687357..174b035fdef105ba91363713a6eeb9e4cd8b7cc3 100644 (file)
@@ -67,6 +67,8 @@ typedef enum {
 
 void set_colors(void);
 
+typedef int (*extra_key_cb_fn)(int, size_t, size_t, void *);
+
 /* this changes the windows attributes !!! */
 void print_in_middle(WINDOW *win, int y, int width, const char *str, int attrs);
 int get_line_length(const char *line);
@@ -78,6 +80,9 @@ int dialog_inputbox(WINDOW *main_window,
                const char *title, const char *prompt,
                const char *init, char **resultp, int *result_len);
 void refresh_all_windows(WINDOW *main_window);
+int show_scroll_win_ext(WINDOW *main_window, const char *title, char *text,
+                       int *vscroll, int *hscroll,
+                       extra_key_cb_fn extra_key_cb, void *data);
 void show_scroll_win(WINDOW *main_window,
                const char *title,
                const char *text);
index 18137050a9c2a3d0cd7add324bfb6eab3208cbe4..93fdc257a603bb358c8de052f9795755610b923d 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.7.6.  */
+/* A Bison parser, made by GNU Bison 3.8.2.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
    USER NAME SPACE" below.  */
 
 /* Identify Bison output, and Bison version.  */
-#define YYBISON 30706
+#define YYBISON 30802
 
 /* Bison version string.  */
-#define YYBISON_VERSION "3.7.6"
+#define YYBISON_VERSION "3.8.2"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -379,12 +379,18 @@ typedef int yy_state_fast_t;
 # define YY_USE(E) /* empty */
 #endif
 
-#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
 /* Suppress an incorrect diagnostic about yylval being uninitialized.  */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                            \
+#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
+# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
+#  define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                           \
+    _Pragma ("GCC diagnostic push")                                     \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
+# else
+#  define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                           \
     _Pragma ("GCC diagnostic push")                                     \
     _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")              \
     _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# endif
 # define YY_IGNORE_MAYBE_UNINITIALIZED_END      \
     _Pragma ("GCC diagnostic pop")
 #else
@@ -603,7 +609,7 @@ static const yytype_int8 yytranslate[] =
 };
 
 #if YYDEBUG
-  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+/* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_int16 yyrline[] =
 {
        0,   110,   110,   110,   114,   119,   121,   122,   123,   124,
@@ -661,20 +667,6 @@ yysymbol_name (yysymbol_kind_t yysymbol)
 }
 #endif
 
-#ifdef YYPRINT
-/* YYTOKNUM[NUM] -- (External) token number corresponding to the
-   (internal) symbol number NUM (which must be that of a token).  */
-static const yytype_int16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
-     305
-};
-#endif
-
 #define YYPACT_NINF (-105)
 
 #define yypact_value_is_default(Yyn) \
@@ -685,8 +677,8 @@ static const yytype_int16 yytoknum[] =
 #define yytable_value_is_error(Yyn) \
   0
 
-  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-     STATE-NUM.  */
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
 static const yytype_int16 yypact[] =
 {
       -5,    17,    37,  -105,    57,     8,  -105,    91,    39,    15,
@@ -710,9 +702,9 @@ static const yytype_int16 yypact[] =
     -105,   136,  -105,  -105,  -105,  -105,  -105
 };
 
-  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
-     Performed when YYTABLE does not specify something else to do.  Zero
-     means the default is an error.  */
+/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+   Performed when YYTABLE does not specify something else to do.  Zero
+   means the default is an error.  */
 static const yytype_int8 yydefact[] =
 {
        5,     0,     0,     5,     0,     0,     1,     0,     0,     0,
@@ -736,7 +728,7 @@ static const yytype_int8 yydefact[] =
       30,     0,    32,    31,    48,    44,    34
 };
 
-  /* YYPGOTO[NTERM-NUM].  */
+/* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
     -105,  -105,  -105,     3,    38,  -105,   -55,  -105,  -105,   138,
@@ -746,7 +738,7 @@ static const yytype_int16 yypgoto[] =
      -46,    -8,   -65,  -105,  -105,  -105,  -105
 };
 
-  /* YYDEFGOTO[NTERM-NUM].  */
+/* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_uint8 yydefgoto[] =
 {
        0,     2,     3,     4,    57,    17,    18,    19,    20,    54,
@@ -756,9 +748,9 @@ static const yytype_uint8 yydefgoto[] =
       48,    49,    50,    41,    32,    39,    64
 };
 
-  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
-     positive, shift that token.  If negative, reduce the rule whose
-     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule whose
+   number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_int16 yytable[] =
 {
       68,    69,   116,   118,    44,   120,     7,    52,   134,   135,
@@ -807,8 +799,8 @@ static const yytype_int16 yycheck[] =
       34,    -1,    -1,    -1,    38
 };
 
-  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-     symbol of state STATE-NUM.  */
+/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
+   state STATE-NUM.  */
 static const yytype_int8 yystos[] =
 {
        0,    24,    52,    53,    54,     5,     0,    54,     1,     4,
@@ -832,7 +824,7 @@ static const yytype_int8 yystos[] =
       40,    90,    40,    40,    40,    40,    40
 };
 
-  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM.  */
 static const yytype_int8 yyr1[] =
 {
        0,    51,    52,    52,    53,    54,    54,    54,    54,    54,
@@ -848,7 +840,7 @@ static const yytype_int8 yyr1[] =
       94,    95,    96,    96,    96,    97,    97
 };
 
-  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM.  */
 static const yytype_int8 yyr2[] =
 {
        0,     2,     2,     1,     3,     0,     2,     2,     2,     2,
@@ -873,6 +865,7 @@ enum { YYENOMEM = -2 };
 #define YYACCEPT        goto yyacceptlab
 #define YYABORT         goto yyabortlab
 #define YYERROR         goto yyerrorlab
+#define YYNOMEM         goto yyexhaustedlab
 
 
 #define YYRECOVERING()  (!!yyerrstatus)
@@ -913,10 +906,7 @@ do {                                            \
     YYFPRINTF Args;                             \
 } while (0)
 
-/* This macro is provided for backward compatibility. */
-# ifndef YY_LOCATION_PRINT
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
+
 
 
 # define YY_SYMBOL_PRINT(Title, Kind, Value, Location)                    \
@@ -943,10 +933,6 @@ yy_symbol_value_print (FILE *yyo,
   YY_USE (yyoutput);
   if (!yyvaluep)
     return;
-# ifdef YYPRINT
-  if (yykind < YYNTOKENS)
-    YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
-# endif
   YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   YY_USE (yykind);
   YY_IGNORE_MAYBE_UNINITIALIZED_END
@@ -1162,6 +1148,7 @@ yyparse (void)
   YYDPRINTF ((stderr, "Starting parse\n"));
 
   yychar = YYEMPTY; /* Cause a token to be read.  */
+
   goto yysetstate;
 
 
@@ -1187,7 +1174,7 @@ yysetstate:
 
   if (yyss + yystacksize - 1 <= yyssp)
 #if !defined yyoverflow && !defined YYSTACK_RELOCATE
-    goto yyexhaustedlab;
+    YYNOMEM;
 #else
     {
       /* Get the current used size of the three stacks, in elements.  */
@@ -1215,7 +1202,7 @@ yysetstate:
 # else /* defined YYSTACK_RELOCATE */
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-        goto yyexhaustedlab;
+        YYNOMEM;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
         yystacksize = YYMAXDEPTH;
@@ -1226,7 +1213,7 @@ yysetstate:
           YY_CAST (union yyalloc *,
                    YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
         if (! yyptr)
-          goto yyexhaustedlab;
+          YYNOMEM;
         YYSTACK_RELOCATE (yyss_alloc, yyss);
         YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
@@ -1248,6 +1235,7 @@ yysetstate:
     }
 #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
 
+
   if (yystate == YYFINAL)
     YYACCEPT;
 
@@ -1832,6 +1820,7 @@ yyerrorlab:
      label yyerrorlab therefore never appears in user code.  */
   if (0)
     YYERROR;
+  ++yynerrs;
 
   /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
@@ -1892,7 +1881,7 @@ yyerrlab1:
 `-------------------------------------*/
 yyacceptlab:
   yyresult = 0;
-  goto yyreturn;
+  goto yyreturnlab;
 
 
 /*-----------------------------------.
@@ -1900,24 +1889,22 @@ yyacceptlab:
 `-----------------------------------*/
 yyabortlab:
   yyresult = 1;
-  goto yyreturn;
+  goto yyreturnlab;
 
 
-#if !defined yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
+/*-----------------------------------------------------------.
+| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here.  |
+`-----------------------------------------------------------*/
 yyexhaustedlab:
   yyerror (YY_("memory exhausted"));
   yyresult = 2;
-  goto yyreturn;
-#endif
+  goto yyreturnlab;
 
 
-/*-------------------------------------------------------.
-| yyreturn -- parsing is finished, clean up and return.  |
-`-------------------------------------------------------*/
-yyreturn:
+/*----------------------------------------------------------.
+| yyreturnlab -- parsing is finished, clean up and return.  |
+`----------------------------------------------------------*/
+yyreturnlab:
   if (yychar != YYEMPTY)
     {
       /* Make sure we have latest lookahead translation.  See comments at
index aac457ce39a8994380165649ca543815f866ab5a..fa3eb3491bd16ec4e40446b303f1a4144c348c35 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.7.6.  */
+/* A Bison parser, made by GNU Bison 3.8.2.  */
 
 /* Bison interface for Yacc-like parsers in C
 
@@ -128,6 +128,8 @@ typedef union YYSTYPE YYSTYPE;
 
 extern YYSTYPE yylval;
 
+
 int yyparse (void);
 
+
 #endif /* !YY_YY_PARSER_TAB_H_INCLUDED  */
index 3c7a35a724703ad43cd503f3c9adca4ea2c2f96d..3c544b775ae0aad04799c6f135d2e92f6f6ad3b4 100644 (file)
@@ -141,7 +141,7 @@ static char *do_lineno(int argc, char *argv[])
 static char *do_shell(int argc, char *argv[])
 {
        FILE *p;
-       char buf[256];
+       char buf[4096];
        char *cmd;
        size_t nread;
        int i;
@@ -396,6 +396,9 @@ static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
 
                p++;
        }
+
+       if (new_argc >= FUNCTION_MAX_ARGS)
+               pperror("too many function arguments");
        new_argv[new_argc++] = prev;
 
        /*
index 609bb818e8fec250fdb060c7551974c5020851b5..203ddf4203406ae057c3a0793c15e0fe1674c4fa 100755 (executable)
@@ -1,24 +1,40 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0-only
 
-PKG="Qt5Core Qt5Gui Qt5Widgets"
+cflags=$1
+libs=$2
+bin=$3
 
-if [ -z "$(command -v pkg-config)" ]; then
+PKG5="Qt5Core Qt5Gui Qt5Widgets"
+PKG6="Qt6Core Qt6Gui Qt6Widgets"
+
+if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then
        echo >&2 "*"
-       echo >&2 "* 'make xconfig' requires 'pkg-config'. Please install it."
+       echo >&2 "* 'make xconfig' requires '${HOSTPKG_CONFIG}'. Please install it."
        echo >&2 "*"
        exit 1
 fi
 
-if pkg-config --exists $PKG; then
-       echo cflags=\"-std=c++11 -fPIC $(pkg-config --cflags $PKG)\"
-       echo libs=\"$(pkg-config --libs $PKG)\"
-       echo moc=\"$(pkg-config --variable=host_bins Qt5Core)/moc\"
+if ${HOSTPKG_CONFIG} --exists $PKG6; then
+       ${HOSTPKG_CONFIG} --cflags ${PKG6} > ${cflags}
+       # Qt6 requires C++17.
+       echo -std=c++17 >> ${cflags}
+       ${HOSTPKG_CONFIG} --libs ${PKG6} > ${libs}
+       ${HOSTPKG_CONFIG} --variable=libexecdir Qt6Core > ${bin}
+       exit 0
+fi
+
+if ${HOSTPKG_CONFIG} --exists $PKG5; then
+       ${HOSTPKG_CONFIG} --cflags ${PKG5} > ${cflags}
+       ${HOSTPKG_CONFIG} --libs ${PKG5} > ${libs}
+       ${HOSTPKG_CONFIG} --variable=host_bins Qt5Core > ${bin}
        exit 0
 fi
 
 echo >&2 "*"
-echo >&2 "* Could not find Qt5 via pkg-config."
-echo >&2 "* Please install Qt5 and make sure it's in PKG_CONFIG_PATH"
+echo >&2 "* Could not find Qt6 or Qt5 via ${HOSTPKG_CONFIG}."
+echo >&2 "* Please install Qt6 or Qt5 and make sure it's in PKG_CONFIG_PATH"
+echo >&2 "* You need $PKG6 for Qt6"
+echo >&2 "* You need $PKG5 for Qt5"
 echo >&2 "*"
 exit 1
index ed7b3e3e20e9b5ec19514aa1e745a562de847bac..abf0d0b392b943aef9bb7ddf152e14f6639a55cd 100644 (file)
@@ -5,10 +5,10 @@
  */
 
 #include <QAction>
+#include <QActionGroup>
 #include <QApplication>
 #include <QCloseEvent>
 #include <QDebug>
-#include <QDesktopWidget>
 #include <QFileDialog>
 #include <QLabel>
 #include <QLayout>
@@ -16,6 +16,8 @@
 #include <QMenu>
 #include <QMenuBar>
 #include <QMessageBox>
+#include <QRegularExpression>
+#include <QScreen>
 #include <QToolBar>
 
 #include <stdlib.h>
@@ -1126,7 +1128,7 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
 
 QString ConfigInfoView::print_filter(const QString &str)
 {
-       QRegExp re("[<>&\"\\n]");
+       QRegularExpression re("[<>&\"\\n]");
        QString res = str;
        for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
                switch (res[i].toLatin1()) {
@@ -1322,15 +1324,15 @@ ConfigMainWindow::ConfigMainWindow(void)
        int width, height;
        char title[256];
 
-       QDesktopWidget *d = configApp->desktop();
        snprintf(title, sizeof(title), "%s%s",
                rootmenu.prompt->text,
                ""
                );
        setWindowTitle(title);
 
-       width = configSettings->value("/window width", d->width() - 64).toInt();
-       height = configSettings->value("/window height", d->height() - 64).toInt();
+       QRect g = configApp->primaryScreen()->geometry();
+       width = configSettings->value("/window width", g.width() - 64).toInt();
+       height = configSettings->value("/window height", g.height() - 64).toInt();
        resize(width, height);
        x = configSettings->value("/window x");
        y = configSettings->value("/window y");
@@ -1379,17 +1381,17 @@ ConfigMainWindow::ConfigMainWindow(void)
                this, &ConfigMainWindow::goBack);
 
        QAction *quitAction = new QAction("&Quit", this);
-       quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
+       quitAction->setShortcut(Qt::CTRL | Qt::Key_Q);
        connect(quitAction, &QAction::triggered,
                this, &ConfigMainWindow::close);
 
        QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
-       loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
+       loadAction->setShortcut(Qt::CTRL | Qt::Key_L);
        connect(loadAction, &QAction::triggered,
                this, &ConfigMainWindow::loadConfig);
 
        saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
-       saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
+       saveAction->setShortcut(Qt::CTRL | Qt::Key_S);
        connect(saveAction, &QAction::triggered,
                this, &ConfigMainWindow::saveConfig);
 
@@ -1403,7 +1405,7 @@ ConfigMainWindow::ConfigMainWindow(void)
        connect(saveAsAction, &QAction::triggered,
                this, &ConfigMainWindow::saveConfigAs);
        QAction *searchAction = new QAction("&Find", this);
-       searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
+       searchAction->setShortcut(Qt::CTRL | Qt::Key_F);
        connect(searchAction, &QAction::triggered,
                this, &ConfigMainWindow::searchConfig);
        singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
@@ -1750,11 +1752,21 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
                e->accept();
                return;
        }
-       QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
-                       QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
-       mb.setButtonText(QMessageBox::Yes, "&Save Changes");
-       mb.setButtonText(QMessageBox::No, "&Discard Changes");
-       mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
+
+       QMessageBox mb(QMessageBox::Icon::Warning, "qconf",
+                      "Save configuration?");
+
+       QPushButton *yb = mb.addButton(QMessageBox::Yes);
+       QPushButton *db = mb.addButton(QMessageBox::No);
+       QPushButton *cb = mb.addButton(QMessageBox::Cancel);
+
+       yb->setText("&Save Changes");
+       db->setText("&Discard Changes");
+       cb->setText("Cancel Exit");
+
+       mb.setDefaultButton(yb);
+       mb.setEscapeButton(cb);
+
        switch (mb.exec()) {
        case QMessageBox::Yes:
                if (saveConfig())
index d97b56ab0ece7a0af72eb8019f3127bb1c3c19b7..6ef44adc057e417063036b50a17eac094d134748 100644 (file)
@@ -123,9 +123,9 @@ static long long sym_get_range_val(struct symbol *sym, int base)
 static void sym_validate_range(struct symbol *sym)
 {
        struct property *prop;
+       struct symbol *range_sym;
        int base;
        long long val, val2;
-       char str[64];
 
        switch (sym->type) {
        case S_INT:
@@ -141,17 +141,15 @@ static void sym_validate_range(struct symbol *sym)
        if (!prop)
                return;
        val = strtoll(sym->curr.val, NULL, base);
-       val2 = sym_get_range_val(prop->expr->left.sym, base);
+       range_sym = prop->expr->left.sym;
+       val2 = sym_get_range_val(range_sym, base);
        if (val >= val2) {
-               val2 = sym_get_range_val(prop->expr->right.sym, base);
+               range_sym = prop->expr->right.sym;
+               val2 = sym_get_range_val(range_sym, base);
                if (val <= val2)
                        return;
        }
-       if (sym->type == S_INT)
-               sprintf(str, "%lld", val2);
-       else
-               sprintf(str, "0x%llx", val2);
-       sym->curr.val = xstrdup(str);
+       sym->curr.val = range_sym->curr.val;
 }
 
 static void sym_set_changed(struct symbol *sym)
@@ -851,49 +849,6 @@ struct symbol *sym_find(const char *name)
        return symbol;
 }
 
-const char *sym_escape_string_value(const char *in)
-{
-       const char *p;
-       size_t reslen;
-       char *res;
-       size_t l;
-
-       reslen = strlen(in) + strlen("\"\"") + 1;
-
-       p = in;
-       for (;;) {
-               l = strcspn(p, "\"\\");
-               p += l;
-
-               if (p[0] == '\0')
-                       break;
-
-               reslen++;
-               p++;
-       }
-
-       res = xmalloc(reslen);
-       res[0] = '\0';
-
-       strcat(res, "\"");
-
-       p = in;
-       for (;;) {
-               l = strcspn(p, "\"\\");
-               strncat(res, p, l);
-               p += l;
-
-               if (p[0] == '\0')
-                       break;
-
-               strcat(res, "\\");
-               strncat(res, p++, 1);
-       }
-
-       strcat(res, "\"");
-       return res;
-}
-
 struct sym_match {
        struct symbol   *sym;
        off_t           so, eo;
index 0bc415cd737e544c035a3fe910d954b58aa5ab8e..53e079e2e8af1a5b4b4536c92ef214de089575c8 100644 (file)
@@ -74,7 +74,7 @@ void str_printf(struct gstr *gs, const char *fmt, ...)
 }
 
 /* Retrieve value of growable string */
-const char *str_get(struct gstr *gs)
+char *str_get(struct gstr *gs)
 {
        return gs->s;
 }