mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-24 07:46:48 +00:00
build: scripts/config - update to kconfig-v6.6.16
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>
This commit is contained in:
parent
ff6df9ac9f
commit
65a3eb28d5
18
scripts/config/.gitignore
vendored
18
scripts/config/.gitignore
vendored
@ -1,16 +1,14 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
/conf
|
/conf
|
||||||
/[gmnq]conf
|
/[gmnq]conf
|
||||||
/[gmnq]conf-cfg
|
/[gmnq]conf-bin
|
||||||
|
/[gmnq]conf-cflags
|
||||||
|
/[gmnq]conf-libs
|
||||||
/qconf-moc.cc
|
/qconf-moc.cc
|
||||||
|
|
||||||
# From linux kconfig parent directories
|
#
|
||||||
.*
|
# Added by openwrt
|
||||||
|
#
|
||||||
# OpenWrt-generated files
|
|
||||||
mconf_check
|
mconf_check
|
||||||
|
# The next line should be removed after 23.05 is EOL
|
||||||
# Temporary files from older versions. They should be removed after the
|
*conf-cfg
|
||||||
# end of support for OpenWrt 19.07.
|
|
||||||
zconf.???.c
|
|
||||||
zconf.hash.c
|
|
||||||
|
279
scripts/config/Kbuild.include
Normal file
279
scripts/config/Kbuild.include
Normal file
@ -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
|
@ -5,46 +5,21 @@
|
|||||||
.PHONY: clean all
|
.PHONY: clean all
|
||||||
all: conf mconf
|
all: conf mconf
|
||||||
clean:
|
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
|
clean-files := *.o lxdialog/*.o *.moc qconf-moc.cc \
|
||||||
# previous version are removed by make config-clean.
|
*conf-cfg # <- This should be removed after 23.05 is EOL
|
||||||
# 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
|
|
||||||
|
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# Variables needed by the upstream Makefile
|
# Variables needed by the upstream Makefile
|
||||||
|
|
||||||
# Avoids displaying 'UPD mconf-cfg' in an otherwise quiet make menuconfig
|
export HOSTPKG_CONFIG=pkg-config
|
||||||
kecho:=true
|
|
||||||
|
|
||||||
CONFIG_SHELL:=$(SHELL)
|
CONFIG_SHELL:=$(SHELL)
|
||||||
srctree:=.
|
src:=$(CURDIR)
|
||||||
src:=.
|
|
||||||
obj:=.
|
obj:=.
|
||||||
Q:=$(if $V,,@)
|
Q:=$(if $V,,@)
|
||||||
cmd = $(cmd_$(1))
|
quiet:=$(if $V,,_silent)
|
||||||
|
include Kbuild.include
|
||||||
# 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, @:)
|
|
||||||
|
|
||||||
### Stripped down upstream Makefile follows:
|
### Stripped down upstream Makefile follows:
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
@ -64,11 +39,12 @@ conf-objs := conf.o $(common-objs)
|
|||||||
hostprogs += nconf
|
hostprogs += nconf
|
||||||
nconf-objs := nconf.o nconf.gui.o $(common-objs)
|
nconf-objs := nconf.o nconf.gui.o $(common-objs)
|
||||||
|
|
||||||
HOSTLDLIBS_nconf = $(shell . $(obj)/nconf-cfg && echo $$libs)
|
HOSTLDLIBS_nconf = $(call read-file, $(obj)/nconf-libs)
|
||||||
HOSTCFLAGS_nconf.o = $(shell . $(obj)/nconf-cfg && echo $$cflags)
|
HOSTCFLAGS_nconf.o = $(call read-file, $(obj)/nconf-cflags)
|
||||||
HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/nconf-cfg && echo $$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
|
# mconf: Used for the menuconfig target based on lxdialog
|
||||||
hostprogs += mconf
|
hostprogs += mconf
|
||||||
@ -76,45 +52,44 @@ lxdialog := $(addprefix lxdialog/, \
|
|||||||
checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
|
checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
|
||||||
mconf-objs := mconf.o $(lxdialog) $(common-objs)
|
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), \
|
$(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
|
# qconf: Used for the xconfig target based on Qt
|
||||||
hostprogs += qconf
|
hostprogs += qconf
|
||||||
qconf-cxxobjs := qconf.o qconf-moc.o
|
qconf-cxxobjs := qconf.o qconf-moc.o
|
||||||
qconf-objs := images.o $(common-objs)
|
qconf-objs := images.o $(common-objs)
|
||||||
|
|
||||||
HOSTLDLIBS_qconf = $(shell . $(obj)/qconf-cfg && echo $$libs)
|
HOSTLDLIBS_qconf = $(call read-file, $(obj)/qconf-libs)
|
||||||
HOSTCXXFLAGS_qconf.o = $(shell . $(obj)/qconf-cfg && echo $$cflags)
|
HOSTCXXFLAGS_qconf.o = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags)
|
||||||
HOSTCXXFLAGS_qconf-moc.o = $(shell . $(obj)/qconf-cfg && echo $$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-cfg
|
$(obj)/qconf.o $(obj)/qconf-moc.o: | $(obj)/qconf-cflags
|
||||||
|
|
||||||
quiet_cmd_moc = MOC $@
|
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)
|
$(call if_changed,moc)
|
||||||
|
|
||||||
targets += qconf-moc.cc
|
targets += qconf-moc.cc
|
||||||
|
|
||||||
# check if necessary packages are available, and configure build flags
|
# 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
|
$(obj)/%conf-cflags $(obj)/%conf-libs $(obj)/%conf-bin: $(src)/%conf-cfg.sh
|
||||||
$(call filechk,conf_cfg)
|
$(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
|
# OpenWrt rules and final adjustments that need to be made after reading the
|
||||||
# full upstream Makefile
|
# full upstream Makefile
|
||||||
|
|
||||||
clean-files += $(targets) $(hostprogs)
|
|
||||||
|
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
||||||
ifdef BUILD_SHIPPED_FILES
|
ifdef BUILD_SHIPPED_FILES
|
||||||
@ -130,25 +105,21 @@ clean-files += $(shipped-files)
|
|||||||
flex -L -o$@ $<
|
flex -L -o$@ $<
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(foreach f,$(conf-objs) $(filter-out $(common-objs),$(mconf-objs) \
|
define link_rule
|
||||||
$(qconf-objs) \
|
$(1): LDLIBS+=$$(HOSTLDLIBS_$(1))
|
||||||
$(nconf-objs)), \
|
$(1): $($(1)-objs) $$($(1)-cxxobjs)
|
||||||
$(eval $(obj)/$f: CFLAGS+=$$(HOSTCFLAGS_$f)))
|
$(if $($(1)-cxxobjs), $(CXX) $$(LDFLAGS) -o $$@ $$^ $$(LDLIBS))
|
||||||
|
all-objs += $($(1)-objs)
|
||||||
|
all-cxxobjs += $($(1)-cxxobjs)
|
||||||
|
endef
|
||||||
|
|
||||||
$(foreach f,$(qconf-cxxobjs), \
|
all-objs:=
|
||||||
$(eval $(obj)/$f: CXXFLAGS+=$$(HOSTCXXFLAGS_$f)))
|
all-cxxobjs:=
|
||||||
|
$(foreach f,$(hostprogs),$(eval $(call link_rule,$f)))
|
||||||
|
|
||||||
$(obj)/conf: $(addprefix $(obj)/,$(conf-objs))
|
|
||||||
|
|
||||||
# The *conf-cfg file is used (then filtered out) as the first prerequisite to
|
$(foreach f,$(sort $(all-objs)), \
|
||||||
# avoid sourcing it before the script is built, when trying to compute CFLAGS
|
$(eval $f: CFLAGS+=$$(HOSTCFLAGS_$f)))
|
||||||
# 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))
|
$(foreach f,$(sort $(all-cxxobjs)), \
|
||||||
$(CC) -o $@ $(filter-out nconf-cfg,$^) $(HOSTLDLIBS_nconf)
|
$(eval $f: CXXFLAGS+=$$(HOSTCXXFLAGS_$f)))
|
||||||
|
|
||||||
$(obj)/qconf: qconf-cfg $(addprefix $(obj)/,$(qconf-cxxobjs) $(qconf-objs))
|
|
||||||
$(CXX) -o $@ $(filter-out qconf-cfg,$^) $(HOSTLDLIBS_qconf)
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
These files were taken from the Linux 5.14 Kernel Configuration System and
|
These files were taken from the Linux Kernel Configuration System v6.6.16,
|
||||||
modified for the OpenWrt Buildroot:
|
at commit eb3e299184cc4f40d4bd84fda269b3a20ddcff80 (Feb 5, 2024), and modified
|
||||||
- Removed nconf, gconf, tests and kernel configuration targets.
|
for the OpenWrt Buildroot:
|
||||||
|
- Removed gconf, tests and kernel configuration targets.
|
||||||
- Adjusted the Makefile to compile outside the kernel.
|
- Adjusted the Makefile to compile outside the kernel.
|
||||||
- Always use default file when running make all{no,mod,yes}config.
|
- Always use default file when running make all{no,mod,yes}config.
|
||||||
- Added a 'reset' command to reset config when the target changes.
|
- Added a 'reset' command to reset config when the target changes.
|
||||||
@ -23,4 +24,4 @@ modified for the OpenWrt Buildroot:
|
|||||||
BUILD_SHIPPED_FILES defined
|
BUILD_SHIPPED_FILES defined
|
||||||
|
|
||||||
For a full list of changes, see the repository at:
|
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
|
||||||
|
@ -35,6 +35,7 @@ enum input_mode {
|
|||||||
olddefconfig,
|
olddefconfig,
|
||||||
yes2modconfig,
|
yes2modconfig,
|
||||||
mod2yesconfig,
|
mod2yesconfig,
|
||||||
|
mod2noconfig,
|
||||||
fatalrecursive,
|
fatalrecursive,
|
||||||
};
|
};
|
||||||
static enum input_mode input_mode = oldaskconfig;
|
static enum input_mode input_mode = oldaskconfig;
|
||||||
@ -164,8 +165,6 @@ enum conf_def_mode {
|
|||||||
def_default,
|
def_default,
|
||||||
def_yes,
|
def_yes,
|
||||||
def_mod,
|
def_mod,
|
||||||
def_y2m,
|
|
||||||
def_m2y,
|
|
||||||
def_no,
|
def_no,
|
||||||
def_random
|
def_random
|
||||||
};
|
};
|
||||||
@ -303,12 +302,10 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
|
|||||||
return has_changed;
|
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;
|
struct symbol *sym;
|
||||||
int i;
|
int i;
|
||||||
tristate old_val = (mode == def_y2m) ? yes : mod;
|
|
||||||
tristate new_val = (mode == def_y2m) ? mod : yes;
|
|
||||||
|
|
||||||
for_all_symbols(i, sym) {
|
for_all_symbols(i, sym) {
|
||||||
if (sym_get_type(sym) == S_TRISTATE &&
|
if (sym_get_type(sym) == S_TRISTATE &&
|
||||||
@ -555,7 +552,7 @@ static int conf_choice(struct menu *menu)
|
|||||||
print_help(child);
|
print_help(child);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sym_set_choice_value(sym, child->sym);
|
sym_set_tristate_value(child->sym, yes);
|
||||||
for (child = child->list; child; child = child->next) {
|
for (child = child->list; child; child = child->next) {
|
||||||
indent += 2;
|
indent += 2;
|
||||||
conf(child);
|
conf(child);
|
||||||
@ -647,19 +644,8 @@ static void check_conf(struct menu *menu)
|
|||||||
|
|
||||||
switch (input_mode) {
|
switch (input_mode) {
|
||||||
case listnewconfig:
|
case listnewconfig:
|
||||||
if (sym->name) {
|
if (sym->name)
|
||||||
const char *str;
|
print_symbol_for_listconfig(sym);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case helpnewconfig:
|
case helpnewconfig:
|
||||||
printf("-----\n");
|
printf("-----\n");
|
||||||
@ -697,7 +683,8 @@ static const struct option long_opts[] = {
|
|||||||
{"olddefconfig", no_argument, &input_mode_opt, olddefconfig},
|
{"olddefconfig", no_argument, &input_mode_opt, olddefconfig},
|
||||||
{"yes2modconfig", no_argument, &input_mode_opt, yes2modconfig},
|
{"yes2modconfig", no_argument, &input_mode_opt, yes2modconfig},
|
||||||
{"mod2yesconfig", no_argument, &input_mode_opt, mod2yesconfig},
|
{"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}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -707,8 +694,10 @@ static void conf_usage(const char *progname)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Generic options:\n");
|
printf("Generic options:\n");
|
||||||
printf(" -h, --help Print this message and exit.\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(" -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("\n");
|
||||||
printf("Mode options:\n");
|
printf("Mode options:\n");
|
||||||
printf(" --listnewconfig List new 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(" --randconfig New config with random answer to all options\n");
|
||||||
printf(" --yes2modconfig Change answers from yes to mod if possible\n");
|
printf(" --yes2modconfig Change answers from yes to mod if possible\n");
|
||||||
printf(" --mod2yesconfig Change answers from mod to yes 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");
|
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);
|
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) {
|
switch (opt) {
|
||||||
case 'h':
|
case 'h':
|
||||||
conf_usage(progname);
|
conf_usage(progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
case 's':
|
|
||||||
conf_set_message_callback(NULL);
|
|
||||||
break;
|
|
||||||
case fatalrecursive:
|
|
||||||
recursive_is_error = 1;
|
|
||||||
continue;
|
|
||||||
case 'r':
|
case 'r':
|
||||||
input_file = optarg;
|
input_file = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
conf_set_message_callback(NULL);
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
output_file = optarg;
|
output_file = optarg;
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
input_mode = input_mode_opt;
|
switch (input_mode_opt) {
|
||||||
switch (input_mode) {
|
|
||||||
case syncconfig:
|
case syncconfig:
|
||||||
/*
|
/*
|
||||||
* syncconfig is invoked during the build stage.
|
* syncconfig is invoked during the build stage.
|
||||||
@ -777,9 +763,13 @@ int main(int ac, char **av)
|
|||||||
case randconfig:
|
case randconfig:
|
||||||
set_randconfig_seed();
|
set_randconfig_seed();
|
||||||
break;
|
break;
|
||||||
|
case fatalrecursive:
|
||||||
|
recursive_is_error = 1;
|
||||||
|
continue;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
input_mode = input_mode_opt;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -812,6 +802,7 @@ int main(int ac, char **av)
|
|||||||
case olddefconfig:
|
case olddefconfig:
|
||||||
case yes2modconfig:
|
case yes2modconfig:
|
||||||
case mod2yesconfig:
|
case mod2yesconfig:
|
||||||
|
case mod2noconfig:
|
||||||
case allnoconfig:
|
case allnoconfig:
|
||||||
case allyesconfig:
|
case allyesconfig:
|
||||||
case allmodconfig:
|
case allmodconfig:
|
||||||
@ -858,10 +849,13 @@ int main(int ac, char **av)
|
|||||||
case savedefconfig:
|
case savedefconfig:
|
||||||
break;
|
break;
|
||||||
case yes2modconfig:
|
case yes2modconfig:
|
||||||
conf_rewrite_mod_or_yes(def_y2m);
|
conf_rewrite_tristates(yes, mod);
|
||||||
break;
|
break;
|
||||||
case mod2yesconfig:
|
case mod2yesconfig:
|
||||||
conf_rewrite_mod_or_yes(def_m2y);
|
conf_rewrite_tristates(mod, yes);
|
||||||
|
break;
|
||||||
|
case mod2noconfig:
|
||||||
|
conf_rewrite_tristates(mod, no);
|
||||||
break;
|
break;
|
||||||
case oldaskconfig:
|
case oldaskconfig:
|
||||||
rootEntry = &rootmenu;
|
rootEntry = &rootmenu;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -129,41 +130,22 @@ static size_t depfile_prefix_len;
|
|||||||
/* touch depfile for symbol 'name' */
|
/* touch depfile for symbol 'name' */
|
||||||
static int conf_touch_dep(const char *name)
|
static int conf_touch_dep(const char *name)
|
||||||
{
|
{
|
||||||
int fd, ret;
|
int fd;
|
||||||
char *d;
|
|
||||||
|
|
||||||
/* check overflow: prefix + name + '\0' must fit in buffer. */
|
/* check overflow: prefix + name + '\0' must fit in buffer. */
|
||||||
if (depfile_prefix_len + strlen(name) + 1 > sizeof(depfile_path))
|
if (depfile_prefix_len + strlen(name) + 1 > sizeof(depfile_path))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
d = depfile_path + depfile_prefix_len;
|
strcpy(depfile_path + depfile_prefix_len, name);
|
||||||
strcpy(d, 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);
|
fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return 0;
|
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, ...)
|
static void conf_warning(const char *fmt, ...)
|
||||||
__attribute__ ((format (printf, 1, 2)));
|
__attribute__ ((format (printf, 1, 2)));
|
||||||
|
|
||||||
@ -227,6 +209,20 @@ static const char *conf_get_autoconfig_name(void)
|
|||||||
return name ? name : "include/config/auto.conf";
|
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)
|
static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
||||||
{
|
{
|
||||||
char *p2;
|
char *p2;
|
||||||
@ -255,6 +251,8 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|||||||
p, sym->name);
|
p, sym->name);
|
||||||
return 1;
|
return 1;
|
||||||
case S_STRING:
|
case S_STRING:
|
||||||
|
/* No escaping for S_DEF_AUTO (include/config/auto.conf) */
|
||||||
|
if (def != S_DEF_AUTO) {
|
||||||
if (*p++ != '"')
|
if (*p++ != '"')
|
||||||
break;
|
break;
|
||||||
for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
|
for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
|
||||||
@ -265,10 +263,10 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|||||||
memmove(p2, p2 + 1, strlen(p2));
|
memmove(p2, p2 + 1, strlen(p2));
|
||||||
}
|
}
|
||||||
if (!p2) {
|
if (!p2) {
|
||||||
if (def != S_DEF_AUTO)
|
|
||||||
conf_warning("invalid string found");
|
conf_warning("invalid string found");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case S_INT:
|
case S_INT:
|
||||||
case S_HEX:
|
case S_HEX:
|
||||||
@ -376,7 +374,11 @@ int conf_read_simple(const char *name, int def)
|
|||||||
char *p, *p2;
|
char *p, *p2;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
int def_flags;
|
int def_flags;
|
||||||
|
const char *warn_unknown;
|
||||||
|
const char *werror;
|
||||||
|
|
||||||
|
warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS");
|
||||||
|
werror = getenv("KCONFIG_WERROR");
|
||||||
if (name) {
|
if (name) {
|
||||||
in = zconf_fopen(name);
|
in = zconf_fopen(name);
|
||||||
} else {
|
} else {
|
||||||
@ -448,6 +450,10 @@ load:
|
|||||||
if (def == S_DEF_USER) {
|
if (def == S_DEF_USER) {
|
||||||
sym = sym_find(line + 2 + strlen(CONFIG_));
|
sym = sym_find(line + 2 + strlen(CONFIG_));
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
|
if (warn_unknown)
|
||||||
|
conf_warning("unknown symbol: %s",
|
||||||
|
line + 2 + strlen(CONFIG_));
|
||||||
|
|
||||||
conf_set_changed(true);
|
conf_set_changed(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -479,7 +485,7 @@ load:
|
|||||||
|
|
||||||
sym = sym_find(line + strlen(CONFIG_));
|
sym = sym_find(line + strlen(CONFIG_));
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
if (def == S_DEF_AUTO)
|
if (def == S_DEF_AUTO) {
|
||||||
/*
|
/*
|
||||||
* Reading from include/config/auto.conf
|
* Reading from include/config/auto.conf
|
||||||
* If CONFIG_FOO previously existed in
|
* If CONFIG_FOO previously existed in
|
||||||
@ -487,8 +493,13 @@ load:
|
|||||||
* include/config/FOO must be touched.
|
* include/config/FOO must be touched.
|
||||||
*/
|
*/
|
||||||
conf_touch_dep(line + strlen(CONFIG_));
|
conf_touch_dep(line + strlen(CONFIG_));
|
||||||
else
|
} else {
|
||||||
|
if (warn_unknown)
|
||||||
|
conf_warning("unknown symbol: %s",
|
||||||
|
line + strlen(CONFIG_));
|
||||||
|
|
||||||
conf_set_changed(true);
|
conf_set_changed(true);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,6 +535,10 @@ load:
|
|||||||
}
|
}
|
||||||
free(line);
|
free(line);
|
||||||
fclose(in);
|
fclose(in);
|
||||||
|
|
||||||
|
if (conf_warnings && werror)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,169 +612,226 @@ int conf_read(const char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
struct comment_style {
|
||||||
* Kconfig configuration printer
|
const char *decoration;
|
||||||
*
|
const char *prefix;
|
||||||
* This printer is used when generating the resulting configuration after
|
const char *postfix;
|
||||||
* kconfig invocation and `defconfig' files. Unset symbol might be omitted by
|
};
|
||||||
* passing a non-NULL argument to the printer.
|
|
||||||
*
|
static const struct comment_style comment_style_pound = {
|
||||||
*/
|
.decoration = "#",
|
||||||
static void
|
.prefix = "#",
|
||||||
kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
|
.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;
|
||||||
|
|
||||||
|
fprintf(fp, "%s\n", cs->prefix);
|
||||||
|
|
||||||
|
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\n", cs->postfix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The returned pointer must be freed on the caller side */
|
||||||
|
static char *escape_string_value(const char *in)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
char *out;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
const char *val;
|
||||||
|
char *escaped = NULL;
|
||||||
|
|
||||||
|
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) {
|
switch (sym->type) {
|
||||||
case S_BOOLEAN:
|
case S_BOOLEAN:
|
||||||
case S_TRISTATE:
|
case S_TRISTATE:
|
||||||
if (*value == 'n') {
|
switch (*val) {
|
||||||
bool skip_unset = (arg != NULL);
|
case 'n':
|
||||||
|
|
||||||
if (!skip_unset)
|
|
||||||
fprintf(fp, "# %s%s is not set\n",
|
|
||||||
CONFIG_, sym->name);
|
|
||||||
return;
|
return;
|
||||||
|
case 'm':
|
||||||
|
sym_suffix = "_MODULE";
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
val = "1";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case S_HEX:
|
||||||
|
if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
|
||||||
|
val_prefix = "0x";
|
||||||
|
break;
|
||||||
|
case S_STRING:
|
||||||
|
escaped = escape_string_value(val);
|
||||||
|
val = escaped;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
|
fprintf(fp, "#define %s%s%s %s%s\n", CONFIG_, sym->name, sym_suffix,
|
||||||
|
val_prefix, val);
|
||||||
|
|
||||||
|
free(escaped);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void print_symbol_for_rustccfg(FILE *fp, struct symbol *sym)
|
||||||
kconfig_print_comment(FILE *fp, const char *value, void *arg)
|
|
||||||
{
|
{
|
||||||
const char *p = value;
|
const char *val;
|
||||||
size_t l;
|
const char *val_prefix = "";
|
||||||
|
char *val_prefixed = NULL;
|
||||||
|
size_t val_prefixed_len;
|
||||||
|
char *escaped = NULL;
|
||||||
|
|
||||||
for (;;) {
|
if (sym->type == S_UNKNOWN)
|
||||||
l = strcspn(p, "\n");
|
return;
|
||||||
fprintf(fp, "#");
|
|
||||||
if (l) {
|
|
||||||
fprintf(fp, " ");
|
|
||||||
xfwrite(p, l, 1, fp);
|
|
||||||
p += l;
|
|
||||||
}
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
if (*p++ == '\0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct conf_printer kconfig_printer_cb =
|
val = sym_get_string_value(sym);
|
||||||
{
|
|
||||||
.print_symbol = kconfig_print_symbol,
|
|
||||||
.print_comment = kconfig_print_comment,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Header printer
|
|
||||||
*
|
|
||||||
* This printer is used when generating the `include/generated/autoconf.h' file.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (sym->type) {
|
switch (sym->type) {
|
||||||
case S_BOOLEAN:
|
case S_BOOLEAN:
|
||||||
case S_TRISTATE: {
|
case S_TRISTATE:
|
||||||
const char *suffix = "";
|
/*
|
||||||
|
* We do not care about disabled ones, i.e. no need for
|
||||||
|
* what otherwise are "comments" in other printers.
|
||||||
|
*/
|
||||||
|
if (*val == 'n')
|
||||||
|
return;
|
||||||
|
|
||||||
switch (*value) {
|
/*
|
||||||
case 'n':
|
* 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;
|
break;
|
||||||
case 'm':
|
case S_HEX:
|
||||||
suffix = "_MODULE";
|
if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
|
||||||
/* fall through */
|
val_prefix = "0x";
|
||||||
default:
|
|
||||||
fprintf(fp, "#define %s%s%s 1\n",
|
|
||||||
CONFIG_, sym->name, suffix);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case S_HEX: {
|
|
||||||
const char *prefix = "";
|
|
||||||
|
|
||||||
if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
|
|
||||||
prefix = "0x";
|
|
||||||
fprintf(fp, "#define %s%s %s%s\n",
|
|
||||||
CONFIG_, sym->name, prefix, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case S_STRING:
|
|
||||||
case S_INT:
|
|
||||||
fprintf(fp, "#define %s%s %s\n",
|
|
||||||
CONFIG_, sym->name, value);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* All values get escaped: the `--cfg` option only takes strings */
|
||||||
header_print_comment(FILE *fp, const char *value, void *arg)
|
escaped = escape_string_value(val);
|
||||||
{
|
val = escaped;
|
||||||
const char *p = value;
|
|
||||||
size_t l;
|
|
||||||
|
|
||||||
fprintf(fp, "/*\n");
|
fprintf(fp, "--cfg=%s%s=%s\n", CONFIG_, sym->name, val);
|
||||||
for (;;) {
|
|
||||||
l = strcspn(p, "\n");
|
|
||||||
fprintf(fp, " *");
|
|
||||||
if (l) {
|
|
||||||
fprintf(fp, " ");
|
|
||||||
xfwrite(p, l, 1, fp);
|
|
||||||
p += l;
|
|
||||||
}
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
if (*p++ == '\0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fprintf(fp, " */\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct conf_printer header_printer_cb =
|
free(escaped);
|
||||||
{
|
free(val_prefixed);
|
||||||
.print_symbol = header_print_symbol,
|
|
||||||
.print_comment = header_print_comment,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void conf_write_symbol(FILE *fp, struct symbol *sym,
|
|
||||||
struct conf_printer *printer, void *printer_arg)
|
|
||||||
{
|
|
||||||
const char *str;
|
|
||||||
|
|
||||||
switch (sym->type) {
|
|
||||||
case S_UNKNOWN:
|
|
||||||
break;
|
|
||||||
case S_STRING:
|
|
||||||
str = sym_get_string_value(sym);
|
|
||||||
str = sym_escape_string_value(str);
|
|
||||||
printer->print_symbol(fp, sym, str, printer_arg);
|
|
||||||
free((void *)str);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
str = sym_get_string_value(sym);
|
|
||||||
printer->print_symbol(fp, sym, str, printer_arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
|
||||||
"\n"
|
|
||||||
"Automatically generated file; DO NOT EDIT.\n"
|
|
||||||
"%s\n",
|
|
||||||
rootmenu.prompt->text);
|
|
||||||
|
|
||||||
printer->print_comment(fp, buf, printer_arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -818,7 +890,7 @@ int conf_write_defconfig(const char *filename)
|
|||||||
goto next_menu;
|
goto next_menu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
|
print_symbol_for_dotconfig(out, sym);
|
||||||
}
|
}
|
||||||
next_menu:
|
next_menu:
|
||||||
if (menu->list != NULL) {
|
if (menu->list != NULL) {
|
||||||
@ -878,7 +950,7 @@ int conf_write(const char *name)
|
|||||||
if (!out)
|
if (!out)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
conf_write_heading(out, &kconfig_printer_cb, NULL);
|
conf_write_heading(out, &comment_style_pound);
|
||||||
|
|
||||||
if (!conf_get_changed())
|
if (!conf_get_changed())
|
||||||
sym_clear_all_valid();
|
sym_clear_all_valid();
|
||||||
@ -905,7 +977,7 @@ int conf_write(const char *name)
|
|||||||
need_newline = false;
|
need_newline = false;
|
||||||
}
|
}
|
||||||
sym->flags |= SYMBOL_WRITTEN;
|
sym->flags |= SYMBOL_WRITTEN;
|
||||||
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
|
print_symbol_for_dotconfig(out, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
next:
|
next:
|
||||||
@ -913,19 +985,20 @@ next:
|
|||||||
menu = menu->list;
|
menu = menu->list;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (menu->next)
|
|
||||||
menu = menu->next;
|
end_check:
|
||||||
else while ((menu = menu->parent)) {
|
if (!menu->sym && menu_is_visible(menu) && menu != &rootmenu &&
|
||||||
if (!menu->sym && menu_is_visible(menu) &&
|
menu->prompt->type == P_MENU) {
|
||||||
menu != &rootmenu) {
|
fprintf(out, "# end of %s\n", menu_get_prompt(menu));
|
||||||
str = menu_get_prompt(menu);
|
|
||||||
fprintf(out, "# end of %s\n", str);
|
|
||||||
need_newline = true;
|
need_newline = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menu->next) {
|
if (menu->next) {
|
||||||
menu = menu->next;
|
menu = menu->next;
|
||||||
break;
|
} else {
|
||||||
}
|
menu = menu->parent;
|
||||||
|
if (menu)
|
||||||
|
goto end_check;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(out);
|
fclose(out);
|
||||||
@ -955,45 +1028,69 @@ next:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* write a dependency file as used by kbuild to track dependencies */
|
/* 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;
|
struct file *file;
|
||||||
FILE *out;
|
FILE *out;
|
||||||
|
int ret;
|
||||||
|
|
||||||
out = fopen("..config.tmp", "w");
|
ret = snprintf(name, sizeof(name), "%s.cmd", autoconf_name);
|
||||||
if (!out)
|
if (ret >= sizeof(name)) /* check truncation */
|
||||||
return 1;
|
return -1;
|
||||||
fprintf(out, "deps_config := \\\n");
|
|
||||||
for (file = file_list; file; file = file->next) {
|
|
||||||
if (file->next)
|
|
||||||
fprintf(out, "\t%s \\\n", file->name);
|
|
||||||
else
|
|
||||||
fprintf(out, "\t%s\n", file->name);
|
|
||||||
}
|
|
||||||
fprintf(out, "\n%s: \\\n"
|
|
||||||
"\t$(deps_config)\n\n", conf_get_autoconfig_name());
|
|
||||||
|
|
||||||
env_write_dep(out, conf_get_autoconfig_name());
|
|
||||||
|
|
||||||
fprintf(out, "\n$(deps_config): ;\n");
|
|
||||||
fclose(out);
|
|
||||||
|
|
||||||
if (make_parent_dir(name))
|
if (make_parent_dir(name))
|
||||||
return 1;
|
return -1;
|
||||||
rename("..config.tmp", name);
|
|
||||||
|
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, "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;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int conf_touch_deps(void)
|
static int conf_touch_deps(void)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name, *tmp;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
int res, i;
|
int res, i;
|
||||||
|
|
||||||
strcpy(depfile_path, "include/config/");
|
|
||||||
depfile_prefix_len = strlen(depfile_path);
|
|
||||||
|
|
||||||
name = conf_get_autoconfig_name();
|
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);
|
conf_read_simple(name, S_DEF_AUTO);
|
||||||
sym_calc_value(modules_sym);
|
sym_calc_value(modules_sym);
|
||||||
|
|
||||||
@ -1056,13 +1153,54 @@ static int conf_touch_deps(void)
|
|||||||
return 0;
|
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)
|
int conf_write_autoconf(int overwrite)
|
||||||
{
|
{
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
const char *name;
|
|
||||||
const char *autoconf_name = conf_get_autoconfig_name();
|
const char *autoconf_name = conf_get_autoconfig_name();
|
||||||
FILE *out, *out_h;
|
int ret, i;
|
||||||
int i;
|
|
||||||
|
|
||||||
#ifndef OPENWRT_DOES_NOT_WANT_THIS
|
#ifndef OPENWRT_DOES_NOT_WANT_THIS
|
||||||
return 0;
|
return 0;
|
||||||
@ -1070,52 +1208,38 @@ int conf_write_autoconf(int overwrite)
|
|||||||
if (!overwrite && is_present(autoconf_name))
|
if (!overwrite && is_present(autoconf_name))
|
||||||
return 0;
|
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())
|
if (conf_touch_deps())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
out = fopen(".tmpconfig", "w");
|
for_all_symbols(i, sym)
|
||||||
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) {
|
|
||||||
sym_calc_value(sym);
|
sym_calc_value(sym);
|
||||||
if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* write symbols to auto.conf and autoconf.h */
|
ret = __conf_write_autoconf(conf_get_autoheader_name(),
|
||||||
conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
|
print_symbol_for_c,
|
||||||
conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
|
&comment_style_c);
|
||||||
}
|
if (ret)
|
||||||
fclose(out);
|
return ret;
|
||||||
fclose(out_h);
|
|
||||||
|
|
||||||
name = getenv("KCONFIG_AUTOHEADER");
|
ret = __conf_write_autoconf(conf_get_rustccfg_name(),
|
||||||
if (!name)
|
print_symbol_for_rustccfg,
|
||||||
name = "include/generated/autoconf.h";
|
NULL);
|
||||||
if (make_parent_dir(name))
|
if (ret)
|
||||||
return 1;
|
return ret;
|
||||||
if (rename(".tmpconfig.h", name))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (make_parent_dir(autoconf_name))
|
|
||||||
return 1;
|
|
||||||
/*
|
/*
|
||||||
* This must be the last step, kbuild has a dependency on auto.conf
|
* Create include/config/auto.conf. This must be the last step because
|
||||||
* and this marks the successful completion of the previous steps.
|
* Kbuild has a dependency on auto.conf and this marks the successful
|
||||||
|
* completion of the previous steps.
|
||||||
*/
|
*/
|
||||||
if (rename(".tmpconfig", autoconf_name))
|
ret = __conf_write_autoconf(conf_get_autoconfig_name(),
|
||||||
return 1;
|
print_symbol_for_autoconf,
|
||||||
|
&comment_style_pound);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1125,10 +1249,12 @@ static void (*conf_changed_callback)(void);
|
|||||||
|
|
||||||
void conf_set_changed(bool val)
|
void conf_set_changed(bool val)
|
||||||
{
|
{
|
||||||
if (conf_changed_callback && conf_changed != val)
|
bool changed = conf_changed != val;
|
||||||
conf_changed_callback();
|
|
||||||
|
|
||||||
conf_changed = val;
|
conf_changed = val;
|
||||||
|
|
||||||
|
if (conf_changed_callback && changed)
|
||||||
|
conf_changed_callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool conf_get_changed(void)
|
bool conf_get_changed(void)
|
||||||
|
@ -276,7 +276,6 @@ struct jump_key {
|
|||||||
struct list_head entries;
|
struct list_head entries;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
struct menu *target;
|
struct menu *target;
|
||||||
int index;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct file *file_list;
|
extern struct file *file_list;
|
||||||
|
@ -86,8 +86,7 @@ static void warn_ignored_character(char chr)
|
|||||||
n [A-Za-z0-9_-]
|
n [A-Za-z0-9_-]
|
||||||
|
|
||||||
%%
|
%%
|
||||||
int str = 0;
|
char open_quote = 0;
|
||||||
int ts, i;
|
|
||||||
|
|
||||||
#.* /* ignore comment */
|
#.* /* ignore comment */
|
||||||
[ \t]* /* whitespaces */
|
[ \t]* /* whitespaces */
|
||||||
@ -137,7 +136,7 @@ n [A-Za-z0-9_-]
|
|||||||
":=" return T_COLON_EQUAL;
|
":=" return T_COLON_EQUAL;
|
||||||
"+=" return T_PLUS_EQUAL;
|
"+=" return T_PLUS_EQUAL;
|
||||||
\"|\' {
|
\"|\' {
|
||||||
str = yytext[0];
|
open_quote = yytext[0];
|
||||||
new_string();
|
new_string();
|
||||||
BEGIN(STRING);
|
BEGIN(STRING);
|
||||||
}
|
}
|
||||||
@ -174,7 +173,7 @@ n [A-Za-z0-9_-]
|
|||||||
append_string(yytext + 1, yyleng - 1);
|
append_string(yytext + 1, yyleng - 1);
|
||||||
}
|
}
|
||||||
\'|\" {
|
\'|\" {
|
||||||
if (str == yytext[0]) {
|
if (open_quote == yytext[0]) {
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
yylval.string = text;
|
yylval.string = text;
|
||||||
return T_WORD_QUOTE;
|
return T_WORD_QUOTE;
|
||||||
@ -199,6 +198,8 @@ n [A-Za-z0-9_-]
|
|||||||
|
|
||||||
<HELP>{
|
<HELP>{
|
||||||
[ \t]+ {
|
[ \t]+ {
|
||||||
|
int ts, i;
|
||||||
|
|
||||||
ts = 0;
|
ts = 0;
|
||||||
for (i = 0; i < yyleng; i++) {
|
for (i = 0; i < yyleng; i++) {
|
||||||
if (yytext[i] == '\t')
|
if (yytext[i] == '\t')
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
/* First, we deal with platform-specific or compiler-specific issues. */
|
/* First, we deal with platform-specific or compiler-specific issues. */
|
||||||
|
|
||||||
/* begin standard C headers. */
|
/* begin standard C headers. */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -30,8 +31,8 @@
|
|||||||
|
|
||||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||||
|
|
||||||
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
|
/* C++ systems might need __STDC_LIMIT_MACROS defined before including
|
||||||
* if you want the limit (max/min) macros for int types.
|
* <stdint.h>, if you want the limit (max/min) macros for int types.
|
||||||
*/
|
*/
|
||||||
#ifndef __STDC_LIMIT_MACROS
|
#ifndef __STDC_LIMIT_MACROS
|
||||||
#define __STDC_LIMIT_MACROS 1
|
#define __STDC_LIMIT_MACROS 1
|
||||||
@ -2538,8 +2539,7 @@ YY_DECL
|
|||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
int str = 0;
|
char open_quote = 0;
|
||||||
int ts, i;
|
|
||||||
|
|
||||||
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
|
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
|
||||||
{
|
{
|
||||||
@ -2772,7 +2772,7 @@ return T_PLUS_EQUAL;
|
|||||||
case 48:
|
case 48:
|
||||||
YY_RULE_SETUP
|
YY_RULE_SETUP
|
||||||
{
|
{
|
||||||
str = yytext[0];
|
open_quote = yytext[0];
|
||||||
new_string();
|
new_string();
|
||||||
BEGIN(STRING);
|
BEGIN(STRING);
|
||||||
}
|
}
|
||||||
@ -2837,7 +2837,7 @@ YY_RULE_SETUP
|
|||||||
case 58:
|
case 58:
|
||||||
YY_RULE_SETUP
|
YY_RULE_SETUP
|
||||||
{
|
{
|
||||||
if (str == yytext[0]) {
|
if (open_quote == yytext[0]) {
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
yylval.string = text;
|
yylval.string = text;
|
||||||
return T_WORD_QUOTE;
|
return T_WORD_QUOTE;
|
||||||
@ -2869,6 +2869,8 @@ case YY_STATE_EOF(STRING):
|
|||||||
case 60:
|
case 60:
|
||||||
YY_RULE_SETUP
|
YY_RULE_SETUP
|
||||||
{
|
{
|
||||||
|
int ts, i;
|
||||||
|
|
||||||
ts = 0;
|
ts = 0;
|
||||||
for (i = 0; i < yyleng; i++) {
|
for (i = 0; i < yyleng; i++) {
|
||||||
if (yytext[i] == '\t')
|
if (yytext[i] == '\t')
|
||||||
|
@ -77,7 +77,7 @@ struct gstr str_new(void);
|
|||||||
void str_free(struct gstr *gs);
|
void str_free(struct gstr *gs);
|
||||||
void str_append(struct gstr *gs, const char *s);
|
void str_append(struct gstr *gs, const char *s);
|
||||||
void str_printf(struct gstr *gs, const char *fmt, ...);
|
void str_printf(struct gstr *gs, const char *fmt, ...);
|
||||||
const char *str_get(struct gstr *gs);
|
char *str_get(struct gstr *gs);
|
||||||
|
|
||||||
/* menu.c */
|
/* menu.c */
|
||||||
void _menu_init(void);
|
void _menu_init(void);
|
||||||
@ -100,10 +100,10 @@ bool menu_is_empty(struct menu *menu);
|
|||||||
bool menu_is_visible(struct menu *menu);
|
bool menu_is_visible(struct menu *menu);
|
||||||
bool menu_has_prompt(struct menu *menu);
|
bool menu_has_prompt(struct menu *menu);
|
||||||
const char *menu_get_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);
|
struct menu *menu_get_parent_menu(struct menu *menu);
|
||||||
bool menu_has_help(struct menu *menu);
|
bool menu_has_help(struct menu *menu);
|
||||||
const char *menu_get_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);
|
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
|
||||||
void menu_get_ext_help(struct menu *menu, struct gstr *help);
|
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;
|
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)
|
static inline bool sym_is_choice(struct symbol *sym)
|
||||||
{
|
{
|
||||||
return sym->flags & SYMBOL_CHOICE ? true : false;
|
return sym->flags & SYMBOL_CHOICE ? true : false;
|
||||||
|
@ -19,7 +19,7 @@ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
|
|||||||
|
|
||||||
struct symbol * sym_lookup(const char *name, int flags);
|
struct symbol * sym_lookup(const char *name, int flags);
|
||||||
struct symbol * sym_find(const char *name);
|
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);
|
struct symbol ** sym_re_search(const char *pattern);
|
||||||
const char * sym_type_name(enum symbol_type type);
|
const char * sym_type_name(enum symbol_type type);
|
||||||
void sym_calc_value(struct symbol *sym);
|
void sym_calc_value(struct symbol *sym);
|
||||||
|
@ -18,22 +18,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <ncurses.h>
|
#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 TR(params) _tracef params
|
||||||
|
|
||||||
#define KEY_ESC 27
|
#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_yesno(const char *title, const char *prompt, int height, int width);
|
||||||
int dialog_msgbox(const char *title, const char *prompt, int height,
|
int dialog_msgbox(const char *title, const char *prompt, int height,
|
||||||
int width, int pause);
|
int width, int pause);
|
||||||
|
int dialog_textbox(const char *title, const char *tbuf, int initial_height,
|
||||||
|
int initial_width, int *_vscroll, int *_hscroll,
|
||||||
typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
|
int (*extra_key_cb)(int, size_t, size_t, void *), void *data);
|
||||||
*_data);
|
|
||||||
int dialog_textbox(const char *title, char *tbuf, int initial_height,
|
|
||||||
int initial_width, int *keys, int *_vscroll, int *_hscroll,
|
|
||||||
update_text_fn update_text, void *data);
|
|
||||||
int dialog_menu(const char *title, const char *prompt,
|
int dialog_menu(const char *title, const char *prompt,
|
||||||
const void *selected, int *s_scroll);
|
const void *selected, int *s_scroll);
|
||||||
int dialog_checklist(const char *title, const char *prompt, int height,
|
int dialog_checklist(const char *title, const char *prompt, int height,
|
||||||
int width, int list_height);
|
int width, int list_height);
|
||||||
int dialog_inputbox(const char *title, const char *prompt, int height,
|
int dialog_inputbox(const char *title, const char *prompt, int height,
|
||||||
int width, const char *init);
|
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)
|
|
||||||
|
@ -63,15 +63,7 @@ static void do_print_item(WINDOW * win, const char *item, int line_y,
|
|||||||
/* Clear 'residue' of last item */
|
/* Clear 'residue' of last item */
|
||||||
wattrset(win, dlg.menubox.atr);
|
wattrset(win, dlg.menubox.atr);
|
||||||
wmove(win, line_y, 0);
|
wmove(win, line_y, 0);
|
||||||
#if OLD_NCURSES
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < menu_width; i++)
|
|
||||||
waddch(win, ' ');
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
wclrtoeol(win);
|
wclrtoeol(win);
|
||||||
#endif
|
|
||||||
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
|
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
|
||||||
mvwaddstr(win, line_y, item_x, menu_item);
|
mvwaddstr(win, line_y, item_x, menu_item);
|
||||||
if (hotkey) {
|
if (hotkey) {
|
||||||
|
@ -8,41 +8,149 @@
|
|||||||
|
|
||||||
#include "dialog.h"
|
#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 hscroll;
|
||||||
static int begin_reached, end_reached, page_length;
|
static int begin_reached, end_reached, page_length;
|
||||||
static char *buf;
|
static const char *buf, *page;
|
||||||
static char *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
|
* refresh window content
|
||||||
*/
|
*/
|
||||||
static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
|
static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
|
||||||
int cur_y, int cur_x, update_text_fn update_text,
|
int cur_y, int cur_x)
|
||||||
void *data)
|
|
||||||
{
|
{
|
||||||
print_page(box, boxh, boxw, update_text, data);
|
start = page - buf;
|
||||||
|
|
||||||
|
print_page(box, boxh, boxw);
|
||||||
print_position(dialog);
|
print_position(dialog);
|
||||||
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
|
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
|
||||||
wrefresh(dialog);
|
wrefresh(dialog);
|
||||||
}
|
|
||||||
|
|
||||||
|
end = page - buf;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Display text from a file in a dialog box.
|
* Display text from a file in a dialog box.
|
||||||
*
|
*
|
||||||
* keys is a null-terminated array
|
* 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 dialog_textbox(const char *title, const char *tbuf, int initial_height,
|
||||||
int initial_width, int *keys, int *_vscroll, int *_hscroll,
|
int initial_width, int *_vscroll, int *_hscroll,
|
||||||
update_text_fn update_text, void *data)
|
int (*extra_key_cb)(int, size_t, size_t, void *), void *data)
|
||||||
{
|
{
|
||||||
int i, x, y, cur_x, cur_y, key = 0;
|
int i, x, y, cur_x, cur_y, key = 0;
|
||||||
int height, width, boxh, boxw;
|
int height, width, boxh, boxw;
|
||||||
@ -122,8 +230,7 @@ do_resize:
|
|||||||
|
|
||||||
/* Print first page of text */
|
/* Print first page of text */
|
||||||
attr_clear(box, boxh, boxw, dlg.dialog.atr);
|
attr_clear(box, boxh, boxw, dlg.dialog.atr);
|
||||||
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
|
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
|
||||||
data);
|
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
key = wgetch(dialog);
|
key = wgetch(dialog);
|
||||||
@ -142,8 +249,7 @@ do_resize:
|
|||||||
begin_reached = 1;
|
begin_reached = 1;
|
||||||
page = buf;
|
page = buf;
|
||||||
refresh_text_box(dialog, box, boxh, boxw,
|
refresh_text_box(dialog, box, boxh, boxw,
|
||||||
cur_y, cur_x, update_text,
|
cur_y, cur_x);
|
||||||
data);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'G': /* Last page */
|
case 'G': /* Last page */
|
||||||
@ -153,8 +259,7 @@ do_resize:
|
|||||||
/* point to last char in buf */
|
/* point to last char in buf */
|
||||||
page = buf + strlen(buf);
|
page = buf + strlen(buf);
|
||||||
back_lines(boxh);
|
back_lines(boxh);
|
||||||
refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
|
||||||
cur_x, update_text, data);
|
|
||||||
break;
|
break;
|
||||||
case 'K': /* Previous line */
|
case 'K': /* Previous line */
|
||||||
case 'k':
|
case 'k':
|
||||||
@ -163,8 +268,7 @@ do_resize:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
back_lines(page_length + 1);
|
back_lines(page_length + 1);
|
||||||
refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
|
||||||
cur_x, update_text, data);
|
|
||||||
break;
|
break;
|
||||||
case 'B': /* Previous page */
|
case 'B': /* Previous page */
|
||||||
case 'b':
|
case 'b':
|
||||||
@ -173,8 +277,7 @@ do_resize:
|
|||||||
if (begin_reached)
|
if (begin_reached)
|
||||||
break;
|
break;
|
||||||
back_lines(page_length + boxh);
|
back_lines(page_length + boxh);
|
||||||
refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
|
||||||
cur_x, update_text, data);
|
|
||||||
break;
|
break;
|
||||||
case 'J': /* Next line */
|
case 'J': /* Next line */
|
||||||
case 'j':
|
case 'j':
|
||||||
@ -183,8 +286,7 @@ do_resize:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
back_lines(page_length - 1);
|
back_lines(page_length - 1);
|
||||||
refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
|
||||||
cur_x, update_text, data);
|
|
||||||
break;
|
break;
|
||||||
case KEY_NPAGE: /* Next page */
|
case KEY_NPAGE: /* Next page */
|
||||||
case ' ':
|
case ' ':
|
||||||
@ -193,8 +295,7 @@ do_resize:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
begin_reached = 0;
|
begin_reached = 0;
|
||||||
refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
|
||||||
cur_x, update_text, data);
|
|
||||||
break;
|
break;
|
||||||
case '0': /* Beginning of line */
|
case '0': /* Beginning of line */
|
||||||
case 'H': /* Scroll left */
|
case 'H': /* Scroll left */
|
||||||
@ -209,8 +310,7 @@ do_resize:
|
|||||||
hscroll--;
|
hscroll--;
|
||||||
/* Reprint current page to scroll horizontally */
|
/* Reprint current page to scroll horizontally */
|
||||||
back_lines(page_length);
|
back_lines(page_length);
|
||||||
refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
|
||||||
cur_x, update_text, data);
|
|
||||||
break;
|
break;
|
||||||
case 'L': /* Scroll right */
|
case 'L': /* Scroll right */
|
||||||
case 'l':
|
case 'l':
|
||||||
@ -220,8 +320,7 @@ do_resize:
|
|||||||
hscroll++;
|
hscroll++;
|
||||||
/* Reprint current page to scroll horizontally */
|
/* Reprint current page to scroll horizontally */
|
||||||
back_lines(page_length);
|
back_lines(page_length);
|
||||||
refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
|
||||||
cur_x, update_text, data);
|
|
||||||
break;
|
break;
|
||||||
case KEY_ESC:
|
case KEY_ESC:
|
||||||
if (on_key_esc(dialog) == KEY_ESC)
|
if (on_key_esc(dialog) == KEY_ESC)
|
||||||
@ -234,14 +333,12 @@ do_resize:
|
|||||||
on_key_resize();
|
on_key_resize();
|
||||||
goto do_resize;
|
goto do_resize;
|
||||||
default:
|
default:
|
||||||
for (i = 0; keys[i]; i++) {
|
if (extra_key_cb && extra_key_cb(key, start, end, data)) {
|
||||||
if (key == keys[i]) {
|
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
delwin(box);
|
delwin(box);
|
||||||
delwin(dialog);
|
delwin(dialog);
|
||||||
if (_vscroll) {
|
if (_vscroll) {
|
||||||
@ -259,137 +356,3 @@ do_resize:
|
|||||||
*_hscroll = hscroll;
|
*_hscroll = hscroll;
|
||||||
return key;
|
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);
|
|
||||||
}
|
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
cflags=$1
|
||||||
|
libs=$2
|
||||||
|
|
||||||
PKG="ncursesw"
|
PKG="ncursesw"
|
||||||
PKG2="ncurses"
|
PKG2="ncurses"
|
||||||
|
|
||||||
if [ -n "$(command -v pkg-config)" ]; then
|
if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then
|
||||||
if pkg-config --exists $PKG; then
|
if ${HOSTPKG_CONFIG} --exists $PKG; then
|
||||||
echo cflags=\"$(pkg-config --cflags $PKG)\"
|
${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
|
||||||
echo libs=\"$(pkg-config --libs $PKG)\"
|
${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if pkg-config --exists $PKG2; then
|
if ${HOSTPKG_CONFIG} --exists ${PKG2}; then
|
||||||
echo cflags=\"$(pkg-config --cflags $PKG2)\"
|
${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags}
|
||||||
echo libs=\"$(pkg-config --libs $PKG2)\"
|
${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -22,22 +25,22 @@ fi
|
|||||||
# (Even if it is installed, some distributions such as openSUSE cannot
|
# (Even if it is installed, some distributions such as openSUSE cannot
|
||||||
# find ncurses by pkg-config.)
|
# find ncurses by pkg-config.)
|
||||||
if [ -f /usr/include/ncursesw/ncurses.h ]; then
|
if [ -f /usr/include/ncursesw/ncurses.h ]; then
|
||||||
echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
|
echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags}
|
||||||
echo libs=\"-lncursesw\"
|
echo -lncursesw > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f /usr/include/ncurses/ncurses.h ]; then
|
if [ -f /usr/include/ncurses/ncurses.h ]; then
|
||||||
echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
|
echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags}
|
||||||
echo libs=\"-lncurses\"
|
echo -lncurses > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# As a final fallback before giving up, check if $HOSTCC knows of a default
|
# As a final fallback before giving up, check if $HOSTCC knows of a default
|
||||||
# ncurses installation (e.g. from a vendor-specific sysroot).
|
# ncurses installation (e.g. from a vendor-specific sysroot).
|
||||||
if echo '#include <ncurses.h>' | ${HOSTCC} -E - >/dev/null 2>&1; then
|
if echo '#include <ncurses.h>' | ${HOSTCC} -E - >/dev/null 2>&1; then
|
||||||
echo cflags=\"-D_GNU_SOURCE\"
|
echo -D_GNU_SOURCE > ${cflags}
|
||||||
echo libs=\"-lncurses\"
|
echo -lncurses > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -46,7 +49,7 @@ echo >&2 "* Unable to find the ncurses package."
|
|||||||
echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
|
echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
|
||||||
echo >&2 "* depending on your distribution)."
|
echo >&2 "* depending on your distribution)."
|
||||||
echo >&2 "*"
|
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 "* ncurses installed in a non-default location."
|
||||||
echo >&2 "*"
|
echo >&2 "*"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -22,8 +22,6 @@
|
|||||||
#include "lkc.h"
|
#include "lkc.h"
|
||||||
#include "lxdialog/dialog.h"
|
#include "lxdialog/dialog.h"
|
||||||
|
|
||||||
#define JUMP_NB 9
|
|
||||||
|
|
||||||
static const char mconf_readme[] =
|
static const char mconf_readme[] =
|
||||||
"OpenWrt config is based on Kernel kconfig\n"
|
"OpenWrt config is based on Kernel kconfig\n"
|
||||||
"so ipkg packages are referred here as modules.\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"
|
"(especially with a larger number of unrolled categories) than the\n"
|
||||||
"default mode.\n"
|
"default mode.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
|
"Search\n"
|
||||||
|
"-------\n"
|
||||||
|
"Pressing the forward-slash (/) anywhere brings up a search dialog box.\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
"Different color themes available\n"
|
"Different color themes available\n"
|
||||||
"--------------------------------\n"
|
"--------------------------------\n"
|
||||||
"It is possible to select different color themes using the variable\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 show_all_options;
|
||||||
static int save_and_exit;
|
static int save_and_exit;
|
||||||
static int silent;
|
static int silent;
|
||||||
|
static int jump_key_char;
|
||||||
|
|
||||||
static void conf(struct menu *menu, struct menu *active_menu);
|
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 char filename[PATH_MAX+1];
|
||||||
static void set_config_filename(const char *config_filename)
|
static void set_config_filename(const char *config_filename)
|
||||||
@ -355,37 +350,87 @@ static void reset_subtitle(void)
|
|||||||
set_dialog_subtitles(subtitles);
|
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 search_data {
|
||||||
struct list_head *head;
|
struct list_head *head;
|
||||||
struct menu **targets;
|
struct menu *target;
|
||||||
int *keys;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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 search_data *data = _data;
|
||||||
struct jump_key *pos;
|
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) {
|
list_for_each_entry(pos, data->head, entries) {
|
||||||
if (pos->offset >= start && pos->offset < end) {
|
index = next_jump_key(index);
|
||||||
char header[4];
|
|
||||||
|
|
||||||
if (k < JUMP_NB) {
|
if (pos->offset < start)
|
||||||
int key = '0' + (pos->index % JUMP_NB) + 1;
|
continue;
|
||||||
|
|
||||||
sprintf(header, "(%c)", key);
|
if (pos->offset >= end)
|
||||||
data->keys[k] = key;
|
break;
|
||||||
data->targets[k] = pos->target;
|
|
||||||
k++;
|
|
||||||
} else {
|
|
||||||
sprintf(header, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
static void search_conf(void)
|
||||||
@ -432,25 +477,21 @@ again:
|
|||||||
sym_arr = sym_re_search(dialog_input);
|
sym_arr = sym_re_search(dialog_input);
|
||||||
do {
|
do {
|
||||||
LIST_HEAD(head);
|
LIST_HEAD(head);
|
||||||
struct menu *targets[JUMP_NB];
|
|
||||||
int keys[JUMP_NB + 1], i;
|
|
||||||
struct search_data data = {
|
struct search_data data = {
|
||||||
.head = &head,
|
.head = &head,
|
||||||
.targets = targets,
|
|
||||||
.keys = keys,
|
|
||||||
};
|
};
|
||||||
struct jump_key *pos, *tmp;
|
struct jump_key *pos, *tmp;
|
||||||
|
|
||||||
|
jump_key_char = 0;
|
||||||
res = get_relations_str(sym_arr, &head);
|
res = get_relations_str(sym_arr, &head);
|
||||||
set_subtitle();
|
set_subtitle();
|
||||||
dres = show_textbox_ext("Search Results", (char *)
|
dres = show_textbox_ext("Search Results", str_get(&res), 0, 0,
|
||||||
str_get(&res), 0, 0, keys, &vscroll,
|
&vscroll, &hscroll,
|
||||||
&hscroll, &update_text, (void *)
|
handle_search_keys, &data);
|
||||||
&data);
|
|
||||||
again = false;
|
again = false;
|
||||||
for (i = 0; i < JUMP_NB && keys[i]; i++)
|
if (dres >= '1' && dres <= '9') {
|
||||||
if (dres == keys[i]) {
|
assert(data.target != NULL);
|
||||||
conf(targets[i]->parent, targets[i]);
|
conf(data.target->parent, data.target);
|
||||||
again = true;
|
again = true;
|
||||||
}
|
}
|
||||||
str_free(&res);
|
str_free(&res);
|
||||||
@ -641,158 +682,6 @@ conf_childs:
|
|||||||
indent -= doint;
|
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)
|
static void conf_choice(struct menu *menu)
|
||||||
{
|
{
|
||||||
const char *prompt = menu_get_prompt(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)
|
static int handle_exit(void)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
@ -661,11 +661,6 @@ const char *menu_get_prompt(struct menu *menu)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct menu *menu_get_root_menu(struct menu *menu)
|
|
||||||
{
|
|
||||||
return &rootmenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct menu *menu_get_parent_menu(struct menu *menu)
|
struct menu *menu_get_parent_menu(struct menu *menu)
|
||||||
{
|
{
|
||||||
enum prop_type type;
|
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,
|
static void get_prompt_str(struct gstr *r, struct property *prop,
|
||||||
struct list_head *head)
|
struct list_head *head)
|
||||||
{
|
{
|
||||||
@ -727,45 +727,35 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
|
|||||||
if (!expr_eq(prop->menu->dep, prop->visible.expr))
|
if (!expr_eq(prop->menu->dep, prop->visible.expr))
|
||||||
get_dep_str(r, prop->visible.expr, " Visible if: ");
|
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) {
|
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
|
||||||
bool accessible = menu_is_visible(menu);
|
|
||||||
|
|
||||||
submenu[i++] = menu;
|
submenu[i++] = menu;
|
||||||
if (location == NULL && accessible)
|
if (location == NULL && menu_is_visible(menu))
|
||||||
location = menu;
|
location = menu;
|
||||||
}
|
}
|
||||||
if (head && location) {
|
if (head && location) {
|
||||||
jump = xmalloc(sizeof(struct jump_key));
|
jump = xmalloc(sizeof(struct jump_key));
|
||||||
|
|
||||||
if (menu_is_visible(prop->menu)) {
|
|
||||||
/*
|
|
||||||
* There is not enough room to put the hint at the
|
|
||||||
* beginning of the "Prompt" line. Put the hint on the
|
|
||||||
* last "Location" line even when it would belong on
|
|
||||||
* the former.
|
|
||||||
*/
|
|
||||||
jump->target = prop->menu;
|
|
||||||
} else
|
|
||||||
jump->target = location;
|
jump->target = location;
|
||||||
|
|
||||||
if (list_empty(head))
|
|
||||||
jump->index = 0;
|
|
||||||
else
|
|
||||||
jump->index = list_entry(head->prev, struct jump_key,
|
|
||||||
entries)->index + 1;
|
|
||||||
|
|
||||||
list_add_tail(&jump->entries, head);
|
list_add_tail(&jump->entries, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > 0) {
|
|
||||||
str_printf(r, " Location:\n");
|
str_printf(r, " Location:\n");
|
||||||
for (j = 4; --i >= 0; j += 2) {
|
for (j = 0; --i >= 0; j++) {
|
||||||
|
int jk = -1;
|
||||||
|
int indent = 2 * j + 4;
|
||||||
|
|
||||||
menu = submenu[i];
|
menu = submenu[i];
|
||||||
if (jump && menu == location)
|
if (jump && menu == location) {
|
||||||
jump->offset = strlen(r->s);
|
jump->offset = strlen(r->s);
|
||||||
str_printf(r, "%*c-> %s", j, ' ',
|
jk = get_jump_key_char();
|
||||||
menu_get_prompt(menu));
|
}
|
||||||
|
|
||||||
|
if (jk >= 0) {
|
||||||
|
str_printf(r, "(%c)", jk);
|
||||||
|
indent -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
str_printf(r, "%*c-> %s", indent, ' ', menu_get_prompt(menu));
|
||||||
if (menu->sym) {
|
if (menu->sym) {
|
||||||
str_printf(r, " (%s [=%s])", menu->sym->name ?
|
str_printf(r, " (%s [=%s])", menu->sym->name ?
|
||||||
menu->sym->name : "<choice>",
|
menu->sym->name : "<choice>",
|
||||||
@ -774,7 +764,6 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
|
|||||||
str_append(r, "\n");
|
str_append(r, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
|
static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
|
||||||
enum prop_type tok, const char *prefix)
|
enum prop_type tok, const char *prefix)
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
cflags=$1
|
||||||
|
libs=$2
|
||||||
|
|
||||||
PKG="ncursesw menuw panelw"
|
PKG="ncursesw menuw panelw"
|
||||||
PKG2="ncurses menu panel"
|
PKG2="ncurses menu panel"
|
||||||
|
|
||||||
if [ -n "$(command -v pkg-config)" ]; then
|
if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then
|
||||||
if pkg-config --exists $PKG; then
|
if ${HOSTPKG_CONFIG} --exists $PKG; then
|
||||||
echo cflags=\"$(pkg-config --cflags $PKG)\"
|
${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
|
||||||
echo libs=\"$(pkg-config --libs $PKG)\"
|
${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if pkg-config --exists $PKG2; then
|
if ${HOSTPKG_CONFIG} --exists $PKG2; then
|
||||||
echo cflags=\"$(pkg-config --cflags $PKG2)\"
|
${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags}
|
||||||
echo libs=\"$(pkg-config --libs $PKG2)\"
|
${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -22,20 +25,20 @@ fi
|
|||||||
# (Even if it is installed, some distributions such as openSUSE cannot
|
# (Even if it is installed, some distributions such as openSUSE cannot
|
||||||
# find ncurses by pkg-config.)
|
# find ncurses by pkg-config.)
|
||||||
if [ -f /usr/include/ncursesw/ncurses.h ]; then
|
if [ -f /usr/include/ncursesw/ncurses.h ]; then
|
||||||
echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
|
echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags}
|
||||||
echo libs=\"-lncursesw -lmenuw -lpanelw\"
|
echo -lncursesw -lmenuw -lpanelw > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f /usr/include/ncurses/ncurses.h ]; then
|
if [ -f /usr/include/ncurses/ncurses.h ]; then
|
||||||
echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
|
echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags}
|
||||||
echo libs=\"-lncurses -lmenu -lpanel\"
|
echo -lncurses -lmenu -lpanel > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f /usr/include/ncurses.h ]; then
|
if [ -f /usr/include/ncurses.h ]; then
|
||||||
echo cflags=\"-D_GNU_SOURCE\"
|
echo -D_GNU_SOURCE > ${cflags}
|
||||||
echo libs=\"-lncurses -lmenu -lpanel\"
|
echo -lncurses -lmenu -lpanel > ${libs}
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -44,7 +47,7 @@ echo >&2 "* Unable to find the ncurses package."
|
|||||||
echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
|
echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
|
||||||
echo >&2 "* depending on your distribution)."
|
echo >&2 "* depending on your distribution)."
|
||||||
echo >&2 "*"
|
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 "* ncurses installed in a non-default location."
|
||||||
echo >&2 "*"
|
echo >&2 "*"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -55,8 +55,8 @@ static const char nconf_global_help[] =
|
|||||||
"\n"
|
"\n"
|
||||||
"Menu navigation keys\n"
|
"Menu navigation keys\n"
|
||||||
"----------------------------------------------------------------------\n"
|
"----------------------------------------------------------------------\n"
|
||||||
"Linewise up <Up>\n"
|
"Linewise up <Up> <k>\n"
|
||||||
"Linewise down <Down>\n"
|
"Linewise down <Down> <j>\n"
|
||||||
"Pagewise up <Page Up>\n"
|
"Pagewise up <Page Up>\n"
|
||||||
"Pagewise down <Page Down>\n"
|
"Pagewise down <Page Down>\n"
|
||||||
"First entry <Home>\n"
|
"First entry <Home>\n"
|
||||||
@ -223,7 +223,7 @@ search_help[] =
|
|||||||
"Location:\n"
|
"Location:\n"
|
||||||
" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
|
" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
|
||||||
" -> PCI support (PCI [ = y])\n"
|
" -> PCI support (PCI [ = y])\n"
|
||||||
" -> PCI access mode (<choice> [ = y])\n"
|
"(1) -> PCI access mode (<choice> [ = y])\n"
|
||||||
"Selects: LIBCRC32\n"
|
"Selects: LIBCRC32\n"
|
||||||
"Selected by: BAR\n"
|
"Selected by: BAR\n"
|
||||||
"-----------------------------------------------------------------\n"
|
"-----------------------------------------------------------------\n"
|
||||||
@ -234,9 +234,13 @@ search_help[] =
|
|||||||
"o The 'Depends on:' line lists symbols that need to be defined for\n"
|
"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"
|
" this symbol to be visible and selectable in the menu.\n"
|
||||||
"o The 'Location:' lines tell, where in the menu structure this symbol\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"
|
" 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"
|
" a selectable menu item, and the current value is displayed inside\n"
|
||||||
" brackets.\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"
|
"o The 'Selects:' line tells, what symbol will be automatically selected\n"
|
||||||
" if this symbol is selected (y or m).\n"
|
" if this symbol is selected (y or m).\n"
|
||||||
"o The 'Selected by' line tells what symbol has selected this symbol.\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 char *dialog_input_result;
|
||||||
static int dialog_input_result_len;
|
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(struct menu *menu);
|
||||||
static void conf_choice(struct menu *menu);
|
static void conf_choice(struct menu *menu);
|
||||||
static void conf_string(struct menu *menu);
|
static void conf_string(struct menu *menu);
|
||||||
@ -688,6 +694,57 @@ static int do_exit(void)
|
|||||||
return 0;
|
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)
|
static void search_conf(void)
|
||||||
{
|
{
|
||||||
@ -695,7 +752,8 @@ static void search_conf(void)
|
|||||||
struct gstr res;
|
struct gstr res;
|
||||||
struct gstr title;
|
struct gstr title;
|
||||||
char *dialog_input;
|
char *dialog_input;
|
||||||
int dres;
|
int dres, vscroll = 0, hscroll = 0;
|
||||||
|
bool again;
|
||||||
|
|
||||||
title = str_new();
|
title = str_new();
|
||||||
str_printf( &title, "Enter (sub)string or regexp to search for "
|
str_printf( &title, "Enter (sub)string or regexp to search for "
|
||||||
@ -724,11 +782,28 @@ again:
|
|||||||
dialog_input += strlen(CONFIG_);
|
dialog_input += strlen(CONFIG_);
|
||||||
|
|
||||||
sym_arr = sym_re_search(dialog_input);
|
sym_arr = sym_re_search(dialog_input);
|
||||||
res = get_relations_str(sym_arr, NULL);
|
|
||||||
free(sym_arr);
|
do {
|
||||||
show_scroll_win(main_window,
|
LIST_HEAD(head);
|
||||||
"Search Results", str_get(&res));
|
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);
|
str_free(&res);
|
||||||
|
} while (again);
|
||||||
|
free(sym_arr);
|
||||||
str_free(&title);
|
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)
|
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 menu *submenu = NULL;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
int res;
|
int i, res;
|
||||||
int current_index = 0;
|
int current_index = 0;
|
||||||
int last_top_row = 0;
|
int last_top_row = 0;
|
||||||
struct match_state match_state = {
|
struct match_state match_state = {
|
||||||
@ -1084,6 +1164,19 @@ static void conf(struct menu *menu)
|
|||||||
if (!child_count)
|
if (!child_count)
|
||||||
break;
|
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,
|
show_menu(menu_get_prompt(menu), menu_instructions,
|
||||||
current_index, &last_top_row);
|
current_index, &last_top_row);
|
||||||
keypad((menu_win(curses_menu)), TRUE);
|
keypad((menu_win(curses_menu)), TRUE);
|
||||||
@ -1108,9 +1201,11 @@ static void conf(struct menu *menu)
|
|||||||
break;
|
break;
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
|
case 'j':
|
||||||
menu_driver(curses_menu, REQ_DOWN_ITEM);
|
menu_driver(curses_menu, REQ_DOWN_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
|
case 'k':
|
||||||
menu_driver(curses_menu, REQ_UP_ITEM);
|
menu_driver(curses_menu, REQ_UP_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_NPAGE:
|
case KEY_NPAGE:
|
||||||
@ -1291,9 +1386,11 @@ static void conf_choice(struct menu *menu)
|
|||||||
break;
|
break;
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
|
case 'j':
|
||||||
menu_driver(curses_menu, REQ_DOWN_ITEM);
|
menu_driver(curses_menu, REQ_DOWN_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
|
case 'k':
|
||||||
menu_driver(curses_menu, REQ_UP_ITEM);
|
menu_driver(curses_menu, REQ_UP_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_NPAGE:
|
case KEY_NPAGE:
|
||||||
|
@ -497,10 +497,17 @@ void refresh_all_windows(WINDOW *main_window)
|
|||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* layman's scrollable window... */
|
|
||||||
void show_scroll_win(WINDOW *main_window,
|
void show_scroll_win(WINDOW *main_window,
|
||||||
const char *title,
|
const char *title,
|
||||||
const char *text)
|
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 res;
|
||||||
int total_lines = get_line_no(text);
|
int total_lines = get_line_no(text);
|
||||||
@ -514,6 +521,12 @@ void show_scroll_win(WINDOW *main_window,
|
|||||||
WINDOW *win;
|
WINDOW *win;
|
||||||
WINDOW *pad;
|
WINDOW *pad;
|
||||||
PANEL *panel;
|
PANEL *panel;
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
if (hscroll)
|
||||||
|
start_x = *hscroll;
|
||||||
|
if (vscroll)
|
||||||
|
start_y = *vscroll;
|
||||||
|
|
||||||
getmaxyx(stdscr, lines, columns);
|
getmaxyx(stdscr, lines, columns);
|
||||||
|
|
||||||
@ -549,8 +562,7 @@ void show_scroll_win(WINDOW *main_window,
|
|||||||
panel = new_panel(win);
|
panel = new_panel(win);
|
||||||
|
|
||||||
/* handle scrolling */
|
/* handle scrolling */
|
||||||
do {
|
while (!done) {
|
||||||
|
|
||||||
copywin(pad, win, start_y, start_x, 2, 2, text_lines,
|
copywin(pad, win, start_y, start_x, 2, 2, text_lines,
|
||||||
text_cols, 0);
|
text_cols, 0);
|
||||||
print_in_middle(win,
|
print_in_middle(win,
|
||||||
@ -593,8 +605,18 @@ void show_scroll_win(WINDOW *main_window,
|
|||||||
case 'l':
|
case 'l':
|
||||||
start_x++;
|
start_x++;
|
||||||
break;
|
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_HELP) || res == KEY_F(F_BACK) ||
|
||||||
res == KEY_F(F_EXIT))
|
res == KEY_F(F_EXIT))
|
||||||
break;
|
break;
|
||||||
@ -606,9 +628,14 @@ void show_scroll_win(WINDOW *main_window,
|
|||||||
start_x = 0;
|
start_x = 0;
|
||||||
if (start_x >= total_cols-text_cols)
|
if (start_x >= total_cols-text_cols)
|
||||||
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);
|
del_panel(panel);
|
||||||
delwin(win);
|
delwin(win);
|
||||||
refresh_all_windows(main_window);
|
refresh_all_windows(main_window);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,8 @@ typedef enum {
|
|||||||
|
|
||||||
void set_colors(void);
|
void set_colors(void);
|
||||||
|
|
||||||
|
typedef int (*extra_key_cb_fn)(int, size_t, size_t, void *);
|
||||||
|
|
||||||
/* this changes the windows attributes !!! */
|
/* this changes the windows attributes !!! */
|
||||||
void print_in_middle(WINDOW *win, int y, int width, const char *str, int attrs);
|
void print_in_middle(WINDOW *win, int y, int width, const char *str, int attrs);
|
||||||
int get_line_length(const char *line);
|
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 *title, const char *prompt,
|
||||||
const char *init, char **resultp, int *result_len);
|
const char *init, char **resultp, int *result_len);
|
||||||
void refresh_all_windows(WINDOW *main_window);
|
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,
|
void show_scroll_win(WINDOW *main_window,
|
||||||
const char *title,
|
const char *title,
|
||||||
const char *text);
|
const char *text);
|
||||||
|
@ -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
|
/* Bison implementation for Yacc-like parsers in C
|
||||||
|
|
||||||
@ -46,10 +46,10 @@
|
|||||||
USER NAME SPACE" below. */
|
USER NAME SPACE" below. */
|
||||||
|
|
||||||
/* Identify Bison output, and Bison version. */
|
/* Identify Bison output, and Bison version. */
|
||||||
#define YYBISON 30706
|
#define YYBISON 30802
|
||||||
|
|
||||||
/* Bison version string. */
|
/* Bison version string. */
|
||||||
#define YYBISON_VERSION "3.7.6"
|
#define YYBISON_VERSION "3.8.2"
|
||||||
|
|
||||||
/* Skeleton name. */
|
/* Skeleton name. */
|
||||||
#define YYSKELETON_NAME "yacc.c"
|
#define YYSKELETON_NAME "yacc.c"
|
||||||
@ -379,12 +379,18 @@ typedef int yy_state_fast_t;
|
|||||||
# define YY_USE(E) /* empty */
|
# define YY_USE(E) /* empty */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
|
|
||||||
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
|
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
|
||||||
|
#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 \
|
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
|
||||||
_Pragma ("GCC diagnostic push") \
|
_Pragma ("GCC diagnostic push") \
|
||||||
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
|
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
|
||||||
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
|
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
|
||||||
|
# endif
|
||||||
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
|
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
|
||||||
_Pragma ("GCC diagnostic pop")
|
_Pragma ("GCC diagnostic pop")
|
||||||
#else
|
#else
|
||||||
@ -661,20 +667,6 @@ yysymbol_name (yysymbol_kind_t yysymbol)
|
|||||||
}
|
}
|
||||||
#endif
|
#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_NINF (-105)
|
||||||
|
|
||||||
#define yypact_value_is_default(Yyn) \
|
#define yypact_value_is_default(Yyn) \
|
||||||
@ -807,8 +799,8 @@ static const yytype_int16 yycheck[] =
|
|||||||
34, -1, -1, -1, 38
|
34, -1, -1, -1, 38
|
||||||
};
|
};
|
||||||
|
|
||||||
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
|
/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
|
||||||
symbol of state STATE-NUM. */
|
state STATE-NUM. */
|
||||||
static const yytype_int8 yystos[] =
|
static const yytype_int8 yystos[] =
|
||||||
{
|
{
|
||||||
0, 24, 52, 53, 54, 5, 0, 54, 1, 4,
|
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
|
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[] =
|
static const yytype_int8 yyr1[] =
|
||||||
{
|
{
|
||||||
0, 51, 52, 52, 53, 54, 54, 54, 54, 54,
|
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
|
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[] =
|
static const yytype_int8 yyr2[] =
|
||||||
{
|
{
|
||||||
0, 2, 2, 1, 3, 0, 2, 2, 2, 2,
|
0, 2, 2, 1, 3, 0, 2, 2, 2, 2,
|
||||||
@ -873,6 +865,7 @@ enum { YYENOMEM = -2 };
|
|||||||
#define YYACCEPT goto yyacceptlab
|
#define YYACCEPT goto yyacceptlab
|
||||||
#define YYABORT goto yyabortlab
|
#define YYABORT goto yyabortlab
|
||||||
#define YYERROR goto yyerrorlab
|
#define YYERROR goto yyerrorlab
|
||||||
|
#define YYNOMEM goto yyexhaustedlab
|
||||||
|
|
||||||
|
|
||||||
#define YYRECOVERING() (!!yyerrstatus)
|
#define YYRECOVERING() (!!yyerrstatus)
|
||||||
@ -913,10 +906,7 @@ do { \
|
|||||||
YYFPRINTF Args; \
|
YYFPRINTF Args; \
|
||||||
} while (0)
|
} 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) \
|
# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
|
||||||
@ -943,10 +933,6 @@ yy_symbol_value_print (FILE *yyo,
|
|||||||
YY_USE (yyoutput);
|
YY_USE (yyoutput);
|
||||||
if (!yyvaluep)
|
if (!yyvaluep)
|
||||||
return;
|
return;
|
||||||
# ifdef YYPRINT
|
|
||||||
if (yykind < YYNTOKENS)
|
|
||||||
YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
|
|
||||||
# endif
|
|
||||||
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
||||||
YY_USE (yykind);
|
YY_USE (yykind);
|
||||||
YY_IGNORE_MAYBE_UNINITIALIZED_END
|
YY_IGNORE_MAYBE_UNINITIALIZED_END
|
||||||
@ -1162,6 +1148,7 @@ yyparse (void)
|
|||||||
YYDPRINTF ((stderr, "Starting parse\n"));
|
YYDPRINTF ((stderr, "Starting parse\n"));
|
||||||
|
|
||||||
yychar = YYEMPTY; /* Cause a token to be read. */
|
yychar = YYEMPTY; /* Cause a token to be read. */
|
||||||
|
|
||||||
goto yysetstate;
|
goto yysetstate;
|
||||||
|
|
||||||
|
|
||||||
@ -1187,7 +1174,7 @@ yysetstate:
|
|||||||
|
|
||||||
if (yyss + yystacksize - 1 <= yyssp)
|
if (yyss + yystacksize - 1 <= yyssp)
|
||||||
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
|
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
|
||||||
goto yyexhaustedlab;
|
YYNOMEM;
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
/* Get the current used size of the three stacks, in elements. */
|
/* Get the current used size of the three stacks, in elements. */
|
||||||
@ -1215,7 +1202,7 @@ yysetstate:
|
|||||||
# else /* defined YYSTACK_RELOCATE */
|
# else /* defined YYSTACK_RELOCATE */
|
||||||
/* Extend the stack our own way. */
|
/* Extend the stack our own way. */
|
||||||
if (YYMAXDEPTH <= yystacksize)
|
if (YYMAXDEPTH <= yystacksize)
|
||||||
goto yyexhaustedlab;
|
YYNOMEM;
|
||||||
yystacksize *= 2;
|
yystacksize *= 2;
|
||||||
if (YYMAXDEPTH < yystacksize)
|
if (YYMAXDEPTH < yystacksize)
|
||||||
yystacksize = YYMAXDEPTH;
|
yystacksize = YYMAXDEPTH;
|
||||||
@ -1226,7 +1213,7 @@ yysetstate:
|
|||||||
YY_CAST (union yyalloc *,
|
YY_CAST (union yyalloc *,
|
||||||
YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
|
YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
|
||||||
if (! yyptr)
|
if (! yyptr)
|
||||||
goto yyexhaustedlab;
|
YYNOMEM;
|
||||||
YYSTACK_RELOCATE (yyss_alloc, yyss);
|
YYSTACK_RELOCATE (yyss_alloc, yyss);
|
||||||
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
|
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
|
||||||
# undef YYSTACK_RELOCATE
|
# undef YYSTACK_RELOCATE
|
||||||
@ -1248,6 +1235,7 @@ yysetstate:
|
|||||||
}
|
}
|
||||||
#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
|
#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
|
||||||
|
|
||||||
|
|
||||||
if (yystate == YYFINAL)
|
if (yystate == YYFINAL)
|
||||||
YYACCEPT;
|
YYACCEPT;
|
||||||
|
|
||||||
@ -1832,6 +1820,7 @@ yyerrorlab:
|
|||||||
label yyerrorlab therefore never appears in user code. */
|
label yyerrorlab therefore never appears in user code. */
|
||||||
if (0)
|
if (0)
|
||||||
YYERROR;
|
YYERROR;
|
||||||
|
++yynerrs;
|
||||||
|
|
||||||
/* Do not reclaim the symbols of the rule whose action triggered
|
/* Do not reclaim the symbols of the rule whose action triggered
|
||||||
this YYERROR. */
|
this YYERROR. */
|
||||||
@ -1892,7 +1881,7 @@ yyerrlab1:
|
|||||||
`-------------------------------------*/
|
`-------------------------------------*/
|
||||||
yyacceptlab:
|
yyacceptlab:
|
||||||
yyresult = 0;
|
yyresult = 0;
|
||||||
goto yyreturn;
|
goto yyreturnlab;
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------.
|
/*-----------------------------------.
|
||||||
@ -1900,24 +1889,22 @@ yyacceptlab:
|
|||||||
`-----------------------------------*/
|
`-----------------------------------*/
|
||||||
yyabortlab:
|
yyabortlab:
|
||||||
yyresult = 1;
|
yyresult = 1;
|
||||||
goto yyreturn;
|
goto yyreturnlab;
|
||||||
|
|
||||||
|
|
||||||
#if !defined yyoverflow
|
/*-----------------------------------------------------------.
|
||||||
/*-------------------------------------------------.
|
| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
|
||||||
| yyexhaustedlab -- memory exhaustion comes here. |
|
`-----------------------------------------------------------*/
|
||||||
`-------------------------------------------------*/
|
|
||||||
yyexhaustedlab:
|
yyexhaustedlab:
|
||||||
yyerror (YY_("memory exhausted"));
|
yyerror (YY_("memory exhausted"));
|
||||||
yyresult = 2;
|
yyresult = 2;
|
||||||
goto yyreturn;
|
goto yyreturnlab;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------.
|
/*----------------------------------------------------------.
|
||||||
| yyreturn -- parsing is finished, clean up and return. |
|
| yyreturnlab -- parsing is finished, clean up and return. |
|
||||||
`-------------------------------------------------------*/
|
`----------------------------------------------------------*/
|
||||||
yyreturn:
|
yyreturnlab:
|
||||||
if (yychar != YYEMPTY)
|
if (yychar != YYEMPTY)
|
||||||
{
|
{
|
||||||
/* Make sure we have latest lookahead translation. See comments at
|
/* Make sure we have latest lookahead translation. See comments at
|
||||||
|
@ -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
|
/* Bison interface for Yacc-like parsers in C
|
||||||
|
|
||||||
@ -128,6 +128,8 @@ typedef union YYSTYPE YYSTYPE;
|
|||||||
|
|
||||||
extern YYSTYPE yylval;
|
extern YYSTYPE yylval;
|
||||||
|
|
||||||
|
|
||||||
int yyparse (void);
|
int yyparse (void);
|
||||||
|
|
||||||
|
|
||||||
#endif /* !YY_YY_PARSER_TAB_H_INCLUDED */
|
#endif /* !YY_YY_PARSER_TAB_H_INCLUDED */
|
||||||
|
@ -141,7 +141,7 @@ static char *do_lineno(int argc, char *argv[])
|
|||||||
static char *do_shell(int argc, char *argv[])
|
static char *do_shell(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
FILE *p;
|
FILE *p;
|
||||||
char buf[256];
|
char buf[4096];
|
||||||
char *cmd;
|
char *cmd;
|
||||||
size_t nread;
|
size_t nread;
|
||||||
int i;
|
int i;
|
||||||
@ -396,6 +396,9 @@ static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
|
|||||||
|
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new_argc >= FUNCTION_MAX_ARGS)
|
||||||
|
pperror("too many function arguments");
|
||||||
new_argv[new_argc++] = prev;
|
new_argv[new_argc++] = prev;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,24 +1,40 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# 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 "*"
|
||||||
echo >&2 "* 'make xconfig' requires 'pkg-config'. Please install it."
|
echo >&2 "* 'make xconfig' requires '${HOSTPKG_CONFIG}'. Please install it."
|
||||||
echo >&2 "*"
|
echo >&2 "*"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if pkg-config --exists $PKG; then
|
if ${HOSTPKG_CONFIG} --exists $PKG6; then
|
||||||
echo cflags=\"-std=c++11 -fPIC $(pkg-config --cflags $PKG)\"
|
${HOSTPKG_CONFIG} --cflags ${PKG6} > ${cflags}
|
||||||
echo libs=\"$(pkg-config --libs $PKG)\"
|
# Qt6 requires C++17.
|
||||||
echo moc=\"$(pkg-config --variable=host_bins Qt5Core)/moc\"
|
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
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo >&2 "*"
|
echo >&2 "*"
|
||||||
echo >&2 "* Could not find Qt5 via pkg-config."
|
echo >&2 "* Could not find Qt6 or Qt5 via ${HOSTPKG_CONFIG}."
|
||||||
echo >&2 "* Please install Qt5 and make sure it's in PKG_CONFIG_PATH"
|
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 "*"
|
echo >&2 "*"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QActionGroup>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDesktopWidget>
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
@ -16,6 +16,8 @@
|
|||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QScreen>
|
||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -1126,7 +1128,7 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
|
|||||||
|
|
||||||
QString ConfigInfoView::print_filter(const QString &str)
|
QString ConfigInfoView::print_filter(const QString &str)
|
||||||
{
|
{
|
||||||
QRegExp re("[<>&\"\\n]");
|
QRegularExpression re("[<>&\"\\n]");
|
||||||
QString res = str;
|
QString res = str;
|
||||||
for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
|
for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
|
||||||
switch (res[i].toLatin1()) {
|
switch (res[i].toLatin1()) {
|
||||||
@ -1322,15 +1324,15 @@ ConfigMainWindow::ConfigMainWindow(void)
|
|||||||
int width, height;
|
int width, height;
|
||||||
char title[256];
|
char title[256];
|
||||||
|
|
||||||
QDesktopWidget *d = configApp->desktop();
|
|
||||||
snprintf(title, sizeof(title), "%s%s",
|
snprintf(title, sizeof(title), "%s%s",
|
||||||
rootmenu.prompt->text,
|
rootmenu.prompt->text,
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
setWindowTitle(title);
|
setWindowTitle(title);
|
||||||
|
|
||||||
width = configSettings->value("/window width", d->width() - 64).toInt();
|
QRect g = configApp->primaryScreen()->geometry();
|
||||||
height = configSettings->value("/window height", d->height() - 64).toInt();
|
width = configSettings->value("/window width", g.width() - 64).toInt();
|
||||||
|
height = configSettings->value("/window height", g.height() - 64).toInt();
|
||||||
resize(width, height);
|
resize(width, height);
|
||||||
x = configSettings->value("/window x");
|
x = configSettings->value("/window x");
|
||||||
y = configSettings->value("/window y");
|
y = configSettings->value("/window y");
|
||||||
@ -1379,17 +1381,17 @@ ConfigMainWindow::ConfigMainWindow(void)
|
|||||||
this, &ConfigMainWindow::goBack);
|
this, &ConfigMainWindow::goBack);
|
||||||
|
|
||||||
QAction *quitAction = new QAction("&Quit", this);
|
QAction *quitAction = new QAction("&Quit", this);
|
||||||
quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
|
quitAction->setShortcut(Qt::CTRL | Qt::Key_Q);
|
||||||
connect(quitAction, &QAction::triggered,
|
connect(quitAction, &QAction::triggered,
|
||||||
this, &ConfigMainWindow::close);
|
this, &ConfigMainWindow::close);
|
||||||
|
|
||||||
QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
|
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,
|
connect(loadAction, &QAction::triggered,
|
||||||
this, &ConfigMainWindow::loadConfig);
|
this, &ConfigMainWindow::loadConfig);
|
||||||
|
|
||||||
saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
|
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,
|
connect(saveAction, &QAction::triggered,
|
||||||
this, &ConfigMainWindow::saveConfig);
|
this, &ConfigMainWindow::saveConfig);
|
||||||
|
|
||||||
@ -1403,7 +1405,7 @@ ConfigMainWindow::ConfigMainWindow(void)
|
|||||||
connect(saveAsAction, &QAction::triggered,
|
connect(saveAsAction, &QAction::triggered,
|
||||||
this, &ConfigMainWindow::saveConfigAs);
|
this, &ConfigMainWindow::saveConfigAs);
|
||||||
QAction *searchAction = new QAction("&Find", this);
|
QAction *searchAction = new QAction("&Find", this);
|
||||||
searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
|
searchAction->setShortcut(Qt::CTRL | Qt::Key_F);
|
||||||
connect(searchAction, &QAction::triggered,
|
connect(searchAction, &QAction::triggered,
|
||||||
this, &ConfigMainWindow::searchConfig);
|
this, &ConfigMainWindow::searchConfig);
|
||||||
singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
|
singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
|
||||||
@ -1750,11 +1752,21 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
|
|||||||
e->accept();
|
e->accept();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
|
|
||||||
QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
|
QMessageBox mb(QMessageBox::Icon::Warning, "qconf",
|
||||||
mb.setButtonText(QMessageBox::Yes, "&Save Changes");
|
"Save configuration?");
|
||||||
mb.setButtonText(QMessageBox::No, "&Discard Changes");
|
|
||||||
mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
|
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()) {
|
switch (mb.exec()) {
|
||||||
case QMessageBox::Yes:
|
case QMessageBox::Yes:
|
||||||
if (saveConfig())
|
if (saveConfig())
|
||||||
|
@ -123,9 +123,9 @@ static long long sym_get_range_val(struct symbol *sym, int base)
|
|||||||
static void sym_validate_range(struct symbol *sym)
|
static void sym_validate_range(struct symbol *sym)
|
||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
struct symbol *range_sym;
|
||||||
int base;
|
int base;
|
||||||
long long val, val2;
|
long long val, val2;
|
||||||
char str[64];
|
|
||||||
|
|
||||||
switch (sym->type) {
|
switch (sym->type) {
|
||||||
case S_INT:
|
case S_INT:
|
||||||
@ -141,17 +141,15 @@ static void sym_validate_range(struct symbol *sym)
|
|||||||
if (!prop)
|
if (!prop)
|
||||||
return;
|
return;
|
||||||
val = strtoll(sym->curr.val, NULL, base);
|
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) {
|
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)
|
if (val <= val2)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sym->type == S_INT)
|
sym->curr.val = range_sym->curr.val;
|
||||||
sprintf(str, "%lld", val2);
|
|
||||||
else
|
|
||||||
sprintf(str, "0x%llx", val2);
|
|
||||||
sym->curr.val = xstrdup(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sym_set_changed(struct symbol *sym)
|
static void sym_set_changed(struct symbol *sym)
|
||||||
@ -851,49 +849,6 @@ struct symbol *sym_find(const char *name)
|
|||||||
return symbol;
|
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 sym_match {
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
off_t so, eo;
|
off_t so, eo;
|
||||||
|
@ -74,7 +74,7 @@ void str_printf(struct gstr *gs, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve value of growable string */
|
/* Retrieve value of growable string */
|
||||||
const char *str_get(struct gstr *gs)
|
char *str_get(struct gstr *gs)
|
||||||
{
|
{
|
||||||
return gs->s;
|
return gs->s;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user