Commit b80c4996 authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch 'adam-uplift_config'

Uplift config utilities in the wr-switch repo and the target.
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parents 67a53d69 3301add3
......@@ -2022,9 +2022,9 @@ BR2_PACKAGE_LIBESTR=y
# BR2_PACKAGE_LINENOISE is not set
BR2_PACKAGE_NCURSES=y
# BR2_PACKAGE_NCURSES_WCHAR is not set
# BR2_PACKAGE_NCURSES_TARGET_PANEL is not set
BR2_PACKAGE_NCURSES_TARGET_PANEL=y
# BR2_PACKAGE_NCURSES_TARGET_FORM is not set
# BR2_PACKAGE_NCURSES_TARGET_MENU is not set
BR2_PACKAGE_NCURSES_TARGET_MENU=y
# BR2_PACKAGE_NCURSES_TARGET_PROGS is not set
# BR2_PACKAGE_NEWT is not set
BR2_PACKAGE_PCRE=y
......
......@@ -3,9 +3,11 @@
# Convenient variables
comma := ,
quote := "
squote := '
empty :=
space := $(empty) $(empty)
space_escape := _-_SPACE_-_
###
# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
......@@ -20,6 +22,10 @@ depfile = $(subst $(comma),_,$(dot-target).d)
# filename of target with directory and extension stripped
basetarget = $(basename $(notdir $@))
###
# filename of first prerequisite with directory and extension stripped
baseprereq = $(basename $(notdir $<))
###
# Escape single quote for use in echo statements
escsq = $(subst $(squote),'\$(squote)',$1)
......@@ -94,52 +100,72 @@ try-run = $(shell set -e; \
# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
as-option = $(call try-run,\
$(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2))
$(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
# as-instr
# Usage: cflags-y += $(call as-instr,instr,option1,option2)
as-instr = $(call try-run,\
/bin/echo -e "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
# cc-option
# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
cc-option = $(call try-run,\
$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2))
$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
# cc-option-yn
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
cc-option-yn = $(call try-run,\
$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n)
$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
# cc-option-align
# Prefix align with either -falign or -malign
cc-option-align = $(subst -functions=0,,\
$(call cc-option,-falign-functions=0,-malign-functions=0))
# cc-disable-warning
# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
cc-disable-warning = $(call try-run,\
$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
# cc-name
# Expands to either gcc or clang
cc-name = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
# cc-version
# Usage gcc-ver := $(call cc-version)
cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
# cc-fullversion
# Usage gcc-ver := $(call cc-fullversion)
cc-fullversion = $(shell $(CONFIG_SHELL) \
$(srctree)/scripts/gcc-version.sh -p $(CC))
# cc-ifversion
# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
cc-ifversion = $(shell [ $(cc-version) $(1) $(2) ] && echo $(3) || echo $(4))
# cc-ldoption
# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
cc-ldoption = $(call try-run,\
$(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2))
$(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
# ld-option
# Usage: LDFLAGS += $(call ld-option, -X)
ld-option = $(call try-run,\
$(CC) /dev/null -c -o "$$TMPO" ; $(LD) $(1) "$$TMPO" -o "$$TMP",$(1),$(2))
$(CC) -x c /dev/null -c -o "$$TMPO" ; $(LD) $(1) "$$TMPO" -o "$$TMP",$(1),$(2))
# ar-option
# Usage: KBUILD_ARFLAGS := $(call ar-option,D)
# Important: no spaces around options
ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
# ld-version
# Note this is mainly for HJ Lu's 3 number binutil versions
ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh)
# ld-ifversion
# Usage: $(call ld-ifversion, -ge, 22252, y)
ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3) || echo $(4))
######
......@@ -147,18 +173,36 @@ ld-option = $(call try-run,\
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
# Usage:
# $(Q)$(MAKE) $(build)=dir
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
build := -f $(srctree)/scripts/Makefile.build obj
###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
# Usage:
# $(Q)$(MAKE) $(modbuiltin)=dir
modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj
modbuiltin := -f $(srctree)/scripts/Makefile.modbuiltin obj
###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj=
# Usage:
# $(Q)$(MAKE) $(dtbinst)=dir
dtbinst := -f $(if $(KBUILD_SRC),$(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
###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.headersinst obj=
# Usage:
# $(Q)$(MAKE) $(hdr-inst)=dir
hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj
# Prefix -I with $(srctree) if it is not an absolute path.
# skip if -I has no parameter
addtree = $(if $(patsubst -I%,%,$(1)), \
$(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1))
$(if $(filter-out -I/% -I./% -I../%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1)),$(1)))
# Find all -I options and call addtree
flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
......@@ -183,17 +227,21 @@ objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
# See Documentation/kbuild/makefiles.txt for more info
ifneq ($(KBUILD_NOCMDDEP),1)
# Check if both arguments has same arguments. Result is empty string if equal.
# User may override this check using make KBUILD_NOCMDDEP=1
arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
$(filter-out $(cmd_$@), $(cmd_$(1))) )
# Check if both arguments are the same including their order. Result is empty
# string if equal. User may override this check using make KBUILD_NOCMDDEP=1
arg-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(cmd_$@))), \
$(subst $(space),$(space_escape),$(strip $(cmd_$1))))
else
arg-check = $(if $(strip $(cmd_$@)),,1)
endif
# >'< substitution is for echo to work,
# >$< substitution to preserve $ when reloading .cmd file
# note: when using inline perl scripts [perl -e '...$$t=1;...']
# in $(cmd_xxx) double $$ your perl vars
make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
# Replace >$< with >$$< to preserve $ when reloading the .cmd file
# (needed for make)
# Replace >#< with >\#< 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 \#,\\\#,$(subst $$,$$$$,$(cmd_$(1)))))
# Find any prerequisites that is newer than target or that does not exist.
# PHONY targets skipped in both cases.
......@@ -204,22 +252,54 @@ any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
@set -e; \
$(echo-cmd) $(cmd_$(1)); \
echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
# Execute the command and also postprocess generated .d dependencies file.
if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \
@set -e; \
$(cmd_and_fixdep), @:)
ifndef CONFIG_TRIM_UNUSED_KSYMS
cmd_and_fixdep = \
$(echo-cmd) $(cmd_$(1)); \
scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\
rm -f $(depfile); \
mv -f $(dot-target).tmp $(dot-target).cmd)
mv -f $(dot-target).tmp $(dot-target).cmd;
else
# Filter out exported kernel symbol names from the preprocessor output.
# See also __KSYM_DEPS__ in include/linux/export.h.
# We disable the depfile generation here, so as not to overwrite the existing
# depfile while fixdep is parsing it.
flags_nodeps = $(filter-out -Wp$(comma)-M%, $($(1)))
ksym_dep_filter = \
case "$(1)" in \
cc_*_c|cpp_i_c) \
$(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \
as_*_S|cpp_s_S) \
$(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \
boot*|build*|*cpp_lds_S|dtc|host*|vdso*) : ;; \
*) echo "Don't know how to preprocess $(1)" >&2; false ;; \
esac | tr ";" "\n" | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p'
cmd_and_fixdep = \
$(echo-cmd) $(cmd_$(1)); \
$(ksym_dep_filter) | \
scripts/basic/fixdep -e $(depfile) $@ '$(make-cmd)' \
> $(dot-target).tmp; \
rm -f $(depfile); \
mv -f $(dot-target).tmp $(dot-target).cmd;
endif
# Usage: $(call if_changed_rule,foo)
# Will check if $(cmd_foo) or any of the prerequisites changed,
# and if so will execute $(rule_foo).
if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \
@set -e; \
$(rule_$(1)))
$(rule_$(1)), @:)
###
# why - tell why a a target got build
......@@ -260,3 +340,52 @@ why = \
echo-why = $(call escsq, $(strip $(why)))
endif
###############################################################################
#
# When a Kconfig string contains a filename, it is suitable for
# passing to shell commands. It is surrounded by double-quotes, and
# any double-quotes or backslashes within it are escaped by
# backslashes.
#
# This is no use for dependencies or $(wildcard). We need to strip the
# surrounding quotes and the escaping from quotes and backslashes, and
# we *do* need to escape any spaces in the string. So, for example:
#
# Usage: $(eval $(call config_filename,FOO))
#
# Defines FOO_FILENAME based on the contents of the CONFIG_FOO option,
# transformed as described above to be suitable for use within the
# makefile.
#
# Also, if the filename is a relative filename and exists in the source
# tree but not the build tree, define FOO_SRCPREFIX as $(srctree)/ to
# be prefixed to *both* command invocation and dependencies.
#
# Note: We also print the filenames in the quiet_cmd_foo text, and
# perhaps ought to have a version specially escaped for that purpose.
# But it's only cosmetic, and $(patsubst "%",%,$(CONFIG_FOO)) is good
# enough. It'll strip the quotes in the common case where there's no
# space and it's a simple filename, and it'll retain the quotes when
# there's a space. There are some esoteric cases in which it'll print
# the wrong thing, but we don't really care. The actual dependencies
# and commands *do* get it right, with various combinations of single
# and double quotes, backslashes and spaces in the filenames.
#
###############################################################################
#
define config_filename
ifneq ($$(CONFIG_$(1)),"")
$(1)_FILENAME := $$(subst \\,\,$$(subst \$$(quote),$$(quote),$$(subst $$(space_escape),\$$(space),$$(patsubst "%",%,$$(subst $$(space),$$(space_escape),$$(CONFIG_$(1)))))))
ifneq ($$(patsubst /%,%,$$(firstword $$($(1)_FILENAME))),$$(firstword $$($(1)_FILENAME)))
else
ifeq ($$(wildcard $$($(1)_FILENAME)),)
ifneq ($$(wildcard $$(srctree)/$$($(1)_FILENAME)),)
$(1)_SRCPREFIX := $(srctree)/
endif
endif
endif
endif
endef
#
###############################################################################
#!/bin/sh
PARAM="-npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1"
RES=`indent --version`
if [ "$RES" = "" ]; then
exit 1
fi
V1=`echo $RES | cut -d' ' -f3 | cut -d'.' -f1`
V2=`echo $RES | cut -d' ' -f3 | cut -d'.' -f2`
V3=`echo $RES | cut -d' ' -f3 | cut -d'.' -f3`
......
......@@ -46,9 +46,10 @@ include $(kbuild-file)
# If the save-* variables changed error out
ifeq ($(KBUILD_NOPEDANTIC),)
ifneq ("$(save-cflags)","$(CFLAGS)")
$(error CFLAGS was changed in "$(kbuild-file)". Fix it to use EXTRA_CFLAGS)
$(error CFLAGS was changed in "$(kbuild-file)". Fix it to use ccflags-y)
endif
endif
include scripts/Makefile.lib
ifdef host-progs
......@@ -59,7 +60,7 @@ endif
endif
# Do not include host rules unless needed
ifneq ($(hostprogs-y)$(hostprogs-m),)
ifneq ($(hostprogs-y)$(hostprogs-m)$(hostlibs-y)$(hostlibs-m)$(hostcxxlibs-y)$(hostcxxlibs-m),)
include scripts/Makefile.host
endif
......@@ -78,11 +79,11 @@ endif
# ===========================================================================
ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a
endif
ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),)
ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
builtin-target := $(obj)/built-in.o
endif
......@@ -115,7 +116,10 @@ endif
# ---------------------------------------------------------------------------
# Default is built-in, unless we know otherwise
modkern_cflags = $(if $(part-of-module), $(CFLAGS_MODULE), $(CFLAGS_KERNEL))
modkern_cflags = \
$(if $(part-of-module), \
$(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
$(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL))
quiet_modtag := $(empty) $(empty)
$(real-objs-m) : part-of-module := y
......@@ -143,27 +147,28 @@ $(multi-objs-y:.o=.s) : modname = $(modname-multi)
$(multi-objs-y:.o=.lst) : modname = $(modname-multi)
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
cmd_cc_s_c = $(CC) $(c_flags) $(DISABLE_LTO) -fverbose-asm -S -o $@ $<
$(obj)/%.s: $(src)/%.c FORCE
$(call if_changed_dep,cc_s_c)
quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@
cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $<
quiet_cmd_cpp_i_c = CPP $(quiet_modtag) $@
cmd_cpp_i_c = $(CPP) $(c_flags) -o $@ $<
$(obj)/%.i: $(src)/%.c FORCE
$(call if_changed_dep,cc_i_c)
$(call if_changed_dep,cpp_i_c)
cmd_gensymtypes = \
$(CPP) -D__GENKSYMS__ $(c_flags) $< | \
$(GENKSYMS) -T $@ -a $(ARCH) \
$(GENKSYMS) $(if $(1), -T $(2)) \
$(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \
$(if $(KBUILD_PRESERVE),-p) \
$(if $(1),-r $(firstword $(wildcard $(@:.symtypes=.symref) /dev/null)))
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
cmd_cc_symtypes_c = \
set -e; \
$(call cmd_gensymtypes, true) >/dev/null; \
$(call cmd_gensymtypes,true,$@) >/dev/null; \
test -s $@ || rm -f $@
$(obj)/%.symtypes : $(src)/%.c FORCE
......@@ -192,50 +197,105 @@ else
# the actual value of the checksum generated by genksyms
cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
cmd_modversions = \
if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
$(call cmd_gensymtypes, $(KBUILD_SYMTYPES)) \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
-T $(@D)/.tmp_$(@F:.o=.ver); \
rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
else \
mv -f $(@D)/.tmp_$(@F) $@; \
cmd_modversions = \
if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
$(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
-T $(@D)/.tmp_$(@F:.o=.ver); \
rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
else \
mv -f $(@D)/.tmp_$(@F) $@; \
fi;
endif
ifdef CONFIG_FTRACE_MCOUNT_RECORD
cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
ifdef BUILD_C_RECORDMCOUNT
ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
RECORDMCOUNT_FLAGS = -w
endif
# Due to recursion, we must skip empty.o.
# The empty.o file is created in the make process in order to determine
# the target endianness and word size. It is made before all other C
# files, including recordmcount.
sub_cmd_record_mcount = \
if [ $(@) != "scripts/mod/empty.o" ]; then \
$(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \
fi;
recordmcount_source := $(srctree)/scripts/recordmcount.c \
$(srctree)/scripts/recordmcount.h
else
sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
"$(if $(CONFIG_64BIT),64,32)" \
"$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
"$(LD)" "$(NM)" "$(RM)" "$(MV)" \
"$(if $(part-of-module),1,0)" "$(@)";
recordmcount_source := $(srctree)/scripts/recordmcount.pl
endif
cmd_record_mcount = \
if [ "$(findstring $(CC_FLAGS_FTRACE),$(_c_flags))" = \
"$(CC_FLAGS_FTRACE)" ]; then \
$(sub_cmd_record_mcount) \
fi;
endif
ifdef CONFIG_STACK_VALIDATION
ifneq ($(SKIP_STACK_VALIDATION),1)
__objtool_obj := $(objtree)/tools/objtool/objtool
objtool_args = check
ifndef CONFIG_FRAME_POINTER
objtool_args += --no-fp
endif
# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
cmd_objtool = $(if $(patsubst y%,, \
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
$(__objtool_obj) $(objtool_args) "$(@)";)
objtool_obj = $(if $(patsubst y%,, \
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
$(__objtool_obj))
endif # SKIP_STACK_VALIDATION
endif # CONFIG_STACK_VALIDATION
define rule_cc_o_c
$(call echo-cmd,checksrc) $(cmd_checksrc) \
$(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \
$(call cmd_and_fixdep,cc_o_c) \
$(cmd_modversions) \
$(call echo-cmd,record_mcount) \
$(cmd_record_mcount) \
scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \
$(dot-target).tmp; \
rm -f $(depfile); \
mv -f $(dot-target).tmp $(dot-target).cmd
$(cmd_objtool) \
$(call echo-cmd,record_mcount) $(cmd_record_mcount)
endef
define rule_as_o_S
$(call cmd_and_fixdep,as_o_S) \
$(cmd_objtool)
endef
# List module undefined symbols (or empty line if not enabled)
ifdef CONFIG_TRIM_UNUSED_KSYMS
cmd_undef_syms = $(NM) $@ | sed -n 's/^ \+U //p' | xargs echo
else
cmd_undef_syms = echo
endif
# Built-in and composite module parts
$(obj)/%.o: $(src)/%.c FORCE
$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_obj) FORCE
$(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)
# Single-part modules are special since we need to mark them in $(MODVERDIR)
$(single-used-m): $(obj)/%.o: $(src)/%.c FORCE
$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_obj) FORCE
$(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)
@{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
@{ echo $(@:.o=.ko); echo $@; \
$(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod)
quiet_cmd_cc_lst_c = MKLST $@
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
......@@ -248,22 +308,22 @@ $(obj)/%.lst: $(src)/%.c FORCE
# Compile assembler sources (.S)
# ---------------------------------------------------------------------------
modkern_aflags := $(AFLAGS_KERNEL)
modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL)
$(real-objs-m) : modkern_aflags := $(AFLAGS_MODULE)
$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE)
$(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
$(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
quiet_cmd_as_s_S = CPP $(quiet_modtag) $@
cmd_as_s_S = $(CPP) $(a_flags) -o $@ $<
quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@
cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $<
$(obj)/%.s: $(src)/%.S FORCE
$(call if_changed_dep,as_s_S)
$(call if_changed_dep,cpp_s_S)
quiet_cmd_as_o_S = AS $(quiet_modtag) $@
cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
$(obj)/%.o: $(src)/%.S FORCE
$(call if_changed_dep,as_o_S)
$(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
$(call if_changed_rule,as_o_S)
targets += $(real-objs-y) $(real-objs-m) $(lib-y)
targets += $(extra-y) $(MAKECMDGOALS) $(always)
......@@ -277,6 +337,17 @@ quiet_cmd_cpp_lds_S = LDS $@
$(obj)/%.lds: $(src)/%.lds.S FORCE
$(call if_changed_dep,cpp_lds_S)
# ASN.1 grammar
# ---------------------------------------------------------------------------
quiet_cmd_asn1_compiler = ASN.1 $@
cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
$(subst .h,.c,$@) $(subst .c,.h,$@)
.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h
$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
$(call cmd,asn1_compiler)
# Build the compiled-in targets
# ---------------------------------------------------------------------------
......@@ -292,7 +363,7 @@ quiet_cmd_link_o_target = LD $@
cmd_link_o_target = $(if $(strip $(obj-y)),\
$(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \
$(cmd_secanalysis),\
rm -f $@; $(AR) rcs $@)
rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@)
$(builtin-target): $(obj-y) FORCE
$(call if_changed,link_o_target)
......@@ -318,7 +389,7 @@ $(modorder-target): $(subdir-ym) FORCE
#
ifdef lib-target
quiet_cmd_link_l_target = AR $@
cmd_link_l_target = rm -f $@; $(AR) rcs $@ $(lib-y)
cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y)
$(lib-target): $(lib-y) FORCE
$(call if_changed,link_l_target)
......@@ -333,27 +404,30 @@ endif
# <composite-object>-objs := <list of .o files>
# or
# <composite-object>-y := <list of .o files>
# or
# <composite-object>-m := <list of .o files>
# The -m syntax only works if <composite object> is a module
link_multi_deps = \
$(filter $(addprefix $(obj)/, \
$($(subst $(obj)/,,$(@:.o=-objs))) \
$($(subst $(obj)/,,$(@:.o=-y)))), $^)
$($(subst $(obj)/,,$(@:.o=-y))) \
$($(subst $(obj)/,,$(@:.o=-m)))), $^)
quiet_cmd_link_multi-y = LD $@
cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalysis)
quiet_cmd_link_multi-m = LD [M] $@
cmd_link_multi-m = $(cmd_link_multi-y)
# We would rather have a list of rules like
# foo.o: $(foo-objs)
# but that's not so easy, so we rather make all composite objects depend
# on the set of all their parts
$(multi-used-y) : %.o: $(multi-objs-y) FORCE
$(multi-used-y): FORCE
$(call if_changed,link_multi-y)
$(call multi_depend, $(multi-used-y), .o, -objs -y)
$(multi-used-m) : %.o: $(multi-objs-m) FORCE
$(multi-used-m): FORCE
$(call if_changed,link_multi-m)
@{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
@{ echo $(@:.o=.ko); echo $(link_multi_deps); \
$(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod)
$(call multi_depend, $(multi-used-m), .o, -objs -y -m)
targets += $(multi-used-y) $(multi-used-m)
......@@ -384,7 +458,6 @@ ifneq ($(cmd_files),)
include $(cmd_files)
endif
# Declare the contents of the .PHONY variable as phony. We keep that
# information in a variable se we can use it in if_changed and friends.
......
......@@ -20,21 +20,20 @@
# Will compile qconf as a C++ program, and menu as a C program.
# They are linked as C++ code to the executable qconf
# hostprogs-y := conf
# conf-objs := conf.o libkconfig.so
# libkconfig-objs := expr.o type.o
# Will create a shared library named libkconfig.so that consists of
# expr.o and type.o (they are both compiled as C code and the object files
# are made as position independent code).
# conf.c is compiled as a C program, and conf.o is linked together with
# libkconfig.so as the executable conf.
# Note: Shared libraries consisting of C++ files are not supported
# hostcc-option
# Usage: cflags-y += $(call hostcc-option,-march=winchip-c6,-march=i586)
hostcc-option = $(call try-run,\
$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
host-cshlib := $(sort $(hostlibs-y) $(hostlibs-m))
host-cxxshlib := $(sort $(hostcxxlibs-y) $(hostcxxlibs-m))
# C code
# Executables compiled from a single .c file
host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m)))
host-csingle := $(foreach m,$(__hostprogs), \
$(if $($(m)-objs)$($(m)-cxxobjs),,$(m)))
# C executables linked based on several .o files
host-cmulti := $(foreach m,$(__hostprogs),\
......@@ -44,33 +43,21 @@ host-cmulti := $(foreach m,$(__hostprogs),\
host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
# C++ code
# C++ executables compiled from at least on .cc file
# C++ executables compiled from at least one .cc file
# and zero or more .c files
host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m)))
# C++ Object (.o) files compiled from .cc files
host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
# Shared libaries (only .c supported)
# Shared libraries (.so) - all .so files referenced in "xxx-objs"
host-cshlib := $(sort $(filter %.so, $(host-cobjs)))
# Remove .so files from "xxx-objs"
host-cobjs := $(filter-out %.so,$(host-cobjs))
#Object (.o) files used by the shared libaries
# Object (.o) files used by the shared libaries
host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
host-cxxshobjs := $(sort $(foreach m,$(host-cxxshlib),$($(m:.so=-objs))))
# output directory for programs/.o files
# hostprogs-y := tools/build may have been specified. Retrieve directory
host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
# directory of .o files from prog-objs notation
host-objdirs += $(foreach f,$(host-cmulti), \
$(foreach m,$($(f)-objs), \
$(if $(dir $(m)),$(dir $(m)))))
# directory of .o files from prog-cxxobjs notation
host-objdirs += $(foreach f,$(host-cxxmulti), \
$(foreach m,$($(f)-cxxobjs), \
$(if $(dir $(m)),$(dir $(m)))))
# hostprogs-y := tools/build may have been specified.
# Retrieve also directory of .o files from prog-objs or prog-cxxobjs notation
host-objdirs := $(dir $(__hostprogs) $(host-cobjs) $(host-cxxobjs))
host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs))))
......@@ -82,7 +69,9 @@ host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
host-cshlib := $(addprefix $(obj)/,$(host-cshlib))
host-cxxshlib := $(addprefix $(obj)/,$(host-cxxshlib))
host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs))
host-cxxshobjs := $(addprefix $(obj)/,$(host-cxxshobjs))
host-objdirs := $(addprefix $(obj)/,$(host-objdirs))
obj-dirs += $(host-objdirs)
......@@ -123,8 +112,9 @@ quiet_cmd_host-cmulti = HOSTLD $@
cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
$(addprefix $(obj)/,$($(@F)-objs)) \
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-cmulti): $(obj)/%: $(host-cobjs) $(host-cshlib) FORCE
$(host-cmulti): FORCE
$(call if_changed,host-cmulti)
$(call multi_depend, $(host-cmulti), , -objs)
# Create .o file from a single .c file
# host-cobjs -> .o
......@@ -140,8 +130,9 @@ quiet_cmd_host-cxxmulti = HOSTLD $@
$(foreach o,objs cxxobjs,\
$(addprefix $(obj)/,$($(@F)-$(o)))) \
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-cxxmulti): $(obj)/%: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
$(host-cxxmulti): FORCE
$(call if_changed,host-cxxmulti)
$(call multi_depend, $(host-cxxmulti), , -objs -cxxobjs)
# Create .o file from a single .cc (C++) file
quiet_cmd_host-cxxobjs = HOSTCXX $@
......@@ -156,15 +147,35 @@ quiet_cmd_host-cshobjs = HOSTCC -fPIC $@
$(host-cshobjs): $(obj)/%.o: $(src)/%.c FORCE
$(call if_changed_dep,host-cshobjs)
# Compile .c file, create position independent .o file
# Note that plugin capable gcc versions can be either C or C++ based
# therefore plugin source files have to be compilable in both C and C++ mode.
# This is why a C++ compiler is invoked on a .c file.
# host-cxxshobjs -> .o
quiet_cmd_host-cxxshobjs = HOSTCXX -fPIC $@
cmd_host-cxxshobjs = $(HOSTCXX) $(hostcxx_flags) -fPIC -c -o $@ $<
$(host-cxxshobjs): $(obj)/%.o: $(src)/%.c FORCE
$(call if_changed_dep,host-cxxshobjs)
# Link a shared library, based on position independent .o files
# *.o -> .so shared library (host-cshlib)
quiet_cmd_host-cshlib = HOSTLLD -shared $@
cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
$(addprefix $(obj)/,$($(@F:.so=-objs))) \
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-cshlib): $(obj)/%: $(host-cshobjs) FORCE
$(host-cshlib): FORCE
$(call if_changed,host-cshlib)
$(call multi_depend, $(host-cshlib), .so, -objs)
targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
$(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs)
# Link a shared library, based on position independent .o files
# *.o -> .so shared library (host-cxxshlib)
quiet_cmd_host-cxxshlib = HOSTLLD -shared $@
cmd_host-cxxshlib = $(HOSTCXX) $(HOSTLDFLAGS) -shared -o $@ \
$(addprefix $(obj)/,$($(@F:.so=-objs))) \
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-cxxshlib): FORCE
$(call if_changed,host-cxxshlib)
$(call multi_depend, $(host-cxxshlib), .so, -objs)
targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
$(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) $(host-cxxshlib) $(host-cxxshobjs)
......@@ -27,7 +27,7 @@ lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))
# ---------------------------------------------------------------------------
# o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o
# and add the directory to the list of dirs to descend into: $(subdir-y)
# o if we encounter foo/ in $(obj-m), remove it from $(obj-m)
# o if we encounter foo/ in $(obj-m), remove it from $(obj-m)
# and add the directory to the list of dirs to descend into: $(subdir-m)
# Determine modorder.
......@@ -46,9 +46,9 @@ obj-m := $(filter-out %/, $(obj-m))
subdir-ym := $(sort $(subdir-y) $(subdir-m))
# if $(foo-objs) exists, foo.o is a composite object
# if $(foo-objs) exists, foo.o is a composite object
multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))), $(m))))
multi-used := $(multi-used-y) $(multi-used-m)
single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m)))
......@@ -63,11 +63,11 @@ multi-objs := $(multi-objs-y) $(multi-objs-m)
subdir-obj-y := $(filter %/built-in.o, $(obj-y))
# $(obj-dirs) is a list of directories that contain object files
obj-dirs := $(dir $(multi-objs) $(subdir-obj-y))
obj-dirs := $(dir $(multi-objs) $(obj-y))
# Replace multi-part objects by their individual parts, look at local dir only
real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y)
real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))),$($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)),$(m)))
# Add subdir path
......@@ -91,29 +91,22 @@ obj-dirs := $(addprefix $(obj)/,$(obj-dirs))
# These flags are needed for modversions and compiling, so we define them here
# already
# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will
# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will
# end up in (or would, if it gets compiled in)
# Note: It's possible that one object gets potentially linked into more
# than one module. In that case KBUILD_MODNAME will be set to foo_bar,
# where foo and bar are the name of the modules.
name-fix = $(subst $(comma),_,$(subst -,_,$1))
basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
# Note: Files that end up in two or more modules are compiled without the
# KBUILD_MODNAME definition. The reason is that any made-up name would
# differ in different configs.
name-fix = $(squote)$(quote)$(subst $(comma),_,$(subst -,_,$1))$(quote)$(squote)
basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))
modname_flags = $(if $(filter 1,$(words $(modname))),\
-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
#hash values
ifdef CONFIG_DYNAMIC_DEBUG
debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
-D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
else
debug_flags =
endif
-DKBUILD_MODNAME=$(call name-fix,$(modname)))
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
$(ccflags-y) $(CFLAGS_$(basetarget).o)
_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \
orig_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \
$(asflags-y) $(AFLAGS_$(basetarget).o)
_a_flags = $(filter-out $(AFLAGS_REMOVE_$(basetarget).o), $(orig_a_flags))
_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F))
#
......@@ -127,10 +120,27 @@ _c_flags += $(if $(patsubst n%,, \
$(CFLAGS_GCOV))
endif
ifdef CONFIG_SYMBOL_PREFIX
_cpp_flags += -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX))
#
# Enable address sanitizer flags for kernel except some files or directories
# we don't want to check (depends on variables KASAN_SANITIZE_obj.o, KASAN_SANITIZE)
#
ifeq ($(CONFIG_KASAN),y)
_c_flags += $(if $(patsubst n%,, \
$(KASAN_SANITIZE_$(basetarget).o)$(KASAN_SANITIZE)y), \
$(CFLAGS_KASAN))
endif
ifeq ($(CONFIG_UBSAN),y)
_c_flags += $(if $(patsubst n%,, \
$(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SANITIZE)$(CONFIG_UBSAN_SANITIZE_ALL)), \
$(CFLAGS_UBSAN))
endif
ifeq ($(CONFIG_KCOV),y)
_c_flags += $(if $(patsubst n%,, \
$(KCOV_INSTRUMENT_$(basetarget).o)$(KCOV_INSTRUMENT)$(CONFIG_KCOV_INSTRUMENT_ALL)), \
$(CFLAGS_KCOV))
endif
# If building the kernel in a separate objtree expand all occurrences
# of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
......@@ -145,15 +155,15 @@ else
# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files
# and locates generated .h files
# FIXME: Replace both with specific CFLAGS* statements in the makefiles
__c_flags = $(call addtree,-I$(obj)) $(call flags,_c_flags)
__a_flags = $(call flags,_a_flags)
__cpp_flags = $(call flags,_cpp_flags)
__c_flags = $(if $(obj),-I$(srctree)/$(src) -I$(obj)) \
$(call flags,_c_flags)
__a_flags = $(call flags,_a_flags)
__cpp_flags = $(call flags,_cpp_flags)
endif
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__c_flags) $(modkern_cflags) \
-D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \
$(debug_flags)
$(basename_flags) $(modname_flags)
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__a_flags) $(modkern_aflags)
......@@ -163,22 +173,79 @@ cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
ld_flags = $(LDFLAGS) $(ldflags-y)
dtc_cpp_flags = -Wp,-MD,$(depfile).pre.tmp -nostdinc \
-I$(srctree)/arch/$(SRCARCH)/boot/dts \
-I$(srctree)/arch/$(SRCARCH)/boot/dts/include \
-I$(srctree)/drivers/of/testcase-data \
-undef -D__DTS__
# Finds the multi-part object the current object will be linked into
modname-multi = $(sort $(foreach m,$(multi-used),\
$(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=))))
# Useful for describing the dependency of composite objects
# Usage:
# $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add)
define multi_depend
$(foreach m, $(notdir $1), \
$(eval $(obj)/$m: \
$(addprefix $(obj)/, $(foreach s, $3, $($(m:%$(strip $2)=%$(s)))))))
endef
ifdef REGENERATE_PARSERS
# GPERF
# ---------------------------------------------------------------------------
quiet_cmd_gperf = GPERF $@
cmd_gperf = gperf -t --output-file $@ -a -C -E -g -k 1,3,$$ -p -t $<
.PRECIOUS: $(src)/%.hash.c_shipped
$(src)/%.hash.c_shipped: $(src)/%.gperf
$(call cmd,gperf)
# LEX
# ---------------------------------------------------------------------------
LEX_PREFIX = $(if $(LEX_PREFIX_${baseprereq}),$(LEX_PREFIX_${baseprereq}),yy)
quiet_cmd_flex = LEX $@
cmd_flex = flex -o$@ -L -P $(LEX_PREFIX) $<
.PRECIOUS: $(src)/%.lex.c_shipped
$(src)/%.lex.c_shipped: $(src)/%.l
$(call cmd,flex)
# YACC
# ---------------------------------------------------------------------------
YACC_PREFIX = $(if $(YACC_PREFIX_${baseprereq}),$(YACC_PREFIX_${baseprereq}),yy)
quiet_cmd_bison = YACC $@
cmd_bison = bison -o$@ -t -l -p $(YACC_PREFIX) $<
.PRECIOUS: $(src)/%.tab.c_shipped
$(src)/%.tab.c_shipped: $(src)/%.y
$(call cmd,bison)
quiet_cmd_bison_h = YACC $@
cmd_bison_h = bison -o/dev/null --defines=$@ -t -l -p $(YACC_PREFIX) $<
.PRECIOUS: $(src)/%.tab.h_shipped
$(src)/%.tab.h_shipped: $(src)/%.y
$(call cmd,bison_h)
endif
# Shipped files
# ===========================================================================
quiet_cmd_shipped = SHIPPED $@
cmd_shipped = cat $< > $@
$(obj)/%:: $(src)/%_shipped
$(obj)/%: $(src)/%_shipped
$(call cmd,shipped)
# Commands useful for building a boot image
# ===========================================================================
#
#
# Use as following:
#
# target: source(s) FORCE
......@@ -192,7 +259,7 @@ $(obj)/%:: $(src)/%_shipped
quiet_cmd_ld = LD $@
cmd_ld = $(LD) $(LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) \
$(filter-out FORCE,$^) -o $@
$(filter-out FORCE,$^) -o $@
# Objcopy
# ---------------------------------------------------------------------------
......@@ -204,9 +271,48 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
# ---------------------------------------------------------------------------
quiet_cmd_gzip = GZIP $@
cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -f -9 > $@) || \
cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
(rm -f $@ ; false)
# DTC
# ---------------------------------------------------------------------------
DTC ?= $(objtree)/scripts/dtc/dtc
# Disable noisy checks by default
ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),)
DTC_FLAGS += -Wno-unit_address_vs_reg
endif
# Generate an assembly file to wrap the output of the device tree compiler
quiet_cmd_dt_S_dtb= DTB $@
cmd_dt_S_dtb= \
( \
echo '\#include <asm-generic/vmlinux.lds.h>'; \
echo '.section .dtb.init.rodata,"a"'; \
echo '.balign STRUCT_ALIGNMENT'; \
echo '.global __dtb_$(*F)_begin'; \
echo '__dtb_$(*F)_begin:'; \
echo '.incbin "$<" '; \
echo '__dtb_$(*F)_end:'; \
echo '.global __dtb_$(*F)_end'; \
echo '.balign STRUCT_ALIGNMENT'; \
) > $@
$(obj)/%.dtb.S: $(obj)/%.dtb
$(call cmd,dt_S_dtb)
quiet_cmd_dtc = DTC $@
cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(DTC) -O dtb -o $@ -b 0 \
-i $(dir $<) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
$(obj)/%.dtb: $(src)/%.dts FORCE
$(call if_changed_dep,dtc)
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
# Bzip2
# ---------------------------------------------------------------------------
......@@ -241,7 +347,64 @@ cmd_lzma = (cat $(filter-out FORCE,$^) | \
lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
quiet_cmd_lzo = LZO $@
quiet_cmd_lzo = LZO $@
cmd_lzo = (cat $(filter-out FORCE,$^) | \
lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
quiet_cmd_lz4 = LZ4 $@
cmd_lz4 = (cat $(filter-out FORCE,$^) | \
lz4c -l -c1 stdin stdout && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
# U-Boot mkimage
# ---------------------------------------------------------------------------
MKIMAGE := $(srctree)/scripts/mkuboot.sh
# SRCARCH just happens to match slightly more than ARCH (on sparc), so reduces
# the number of overrides in arch makefiles
UIMAGE_ARCH ?= $(SRCARCH)
UIMAGE_COMPRESSION ?= $(if $(2),$(2),none)
UIMAGE_OPTS-y ?=
UIMAGE_TYPE ?= kernel
UIMAGE_LOADADDR ?= arch_must_set_this
UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR)
UIMAGE_NAME ?= 'Linux-$(KERNELRELEASE)'
UIMAGE_IN ?= $<
UIMAGE_OUT ?= $@
quiet_cmd_uimage = UIMAGE $(UIMAGE_OUT)
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \
-C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \
-T $(UIMAGE_TYPE) \
-a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \
-n $(UIMAGE_NAME) -d $(UIMAGE_IN) $(UIMAGE_OUT)
# XZ
# ---------------------------------------------------------------------------
# Use xzkern to compress the kernel image and xzmisc to compress other things.
#
# xzkern uses a big LZMA2 dictionary since it doesn't increase memory usage
# of the kernel decompressor. A BCJ filter is used if it is available for
# the target architecture. xzkern also appends uncompressed size of the data
# using size_append. The .xz format has the size information available at
# the end of the file too, but it's in more complex format and it's good to
# avoid changing the part of the boot code that reads the uncompressed size.
# Note that the bytes added by size_append will make the xz tool think that
# the file is corrupt. This is expected.
#
# xzmisc doesn't use size_append, so it can be used to create normal .xz
# files. xzmisc uses smaller LZMA2 dictionary than xzkern, because a very
# big dictionary would increase the memory usage too much in the multi-call
# decompression mode. A BCJ filter isn't used either.
quiet_cmd_xzkern = XZKERN $@
cmd_xzkern = (cat $(filter-out FORCE,$^) | \
sh $(srctree)/scripts/xz_wrap.sh && \
$(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
quiet_cmd_xzmisc = XZMISC $@
cmd_xzmisc = (cat $(filter-out FORCE,$^) | \
xz --check=crc32 --lzma2=dict=1MiB) > $@ || \
(rm -f $@ ; false)
......@@ -2,12 +2,11 @@
# Generated files
#
config*
lex.*.c
*.lex.c
*.tab.c
*.tab.h
zconf.hash.c
*.moc
lkc_defs.h
gconf.glade.h
*.pot
*.mo
......@@ -17,6 +16,7 @@ gconf.glade.h
#
conf
mconf
nconf
qconf
gconf
kxgettext
......@@ -2,199 +2,185 @@
# Kernel configuration targets
# These targets are used from top-level makefile
PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \
PHONY += xconfig gconfig menuconfig config silentoldconfig update-po-config \
localmodconfig localyesconfig
ifdef KBUILD_KCONFIG
Kconfig := $(KBUILD_KCONFIG)
else
Kconfig := arch/$(SRCARCH)/Kconfig
Kconfig := Kconfig
endif
ifeq ($(quiet),silent_)
silent := -s
endif
# We need this, in case the user has it in its environment
unexport CONFIG_
xconfig: $(obj)/qconf
$< $(Kconfig)
$< $(silent) $(Kconfig)
gconfig: $(obj)/gconf
$< $(Kconfig)
$< $(silent) $(Kconfig)
menuconfig: $(obj)/mconf
$< $(Kconfig)
$< $(silent) $(Kconfig)
config: $(obj)/conf
$< $(Kconfig)
$< $(silent) --oldaskconfig $(Kconfig)
oldconfig: $(obj)/conf
$< -o $(Kconfig)
nconfig: $(obj)/nconf
$< $(silent) $(Kconfig)
silentoldconfig: $(obj)/conf
$(Q)mkdir -p include/generated
$< -s $(Kconfig)
# if no path is given, then use src directory to find file
ifdef LSMOD
LSMOD_F := $(LSMOD)
ifeq ($(findstring /,$(LSMOD)),)
LSMOD_F := $(objtree)/$(LSMOD)
endif
endif
localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
$(Q)mkdir -p include/generated
$(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config
$(Q)if [ -f .config ]; then \
cmp -s .tmp.config .config || \
(mv -f .config .config.old.1; \
mv -f .tmp.config .config; \
$(obj)/conf -s $(Kconfig); \
mv -f .config.old.1 .config.old) \
else \
mv -f .tmp.config .config; \
$(obj)/conf -s $(Kconfig); \
fi
$(Q)rm -f .tmp.config
localyesconfig: $(obj)/streamline_config.pl $(obj)/conf
$(Q)mkdir -p include/generated
$(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config
$(Q)sed -i s/=m/=y/ .tmp.config
$(Q)if [ -f .config ]; then \
cmp -s .tmp.config .config || \
(mv -f .config .config.old.1; \
mv -f .tmp.config .config; \
$(obj)/conf -s $(Kconfig); \
mv -f .config.old.1 .config.old) \
else \
mv -f .tmp.config .config; \
$(obj)/conf -s $(Kconfig); \
$(Q)mkdir -p include/config include/generated
$< $(silent) --$@ $(Kconfig)
localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
$(Q)mkdir -p include/config include/generated
$(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
$(Q)if [ -f .config ]; then \
cmp -s .tmp.config .config || \
(mv -f .config .config.old.1; \
mv -f .tmp.config .config; \
$(obj)/conf $(silent) --silentoldconfig $(Kconfig); \
mv -f .config.old.1 .config.old) \
else \
mv -f .tmp.config .config; \
$(obj)/conf $(silent) --silentoldconfig $(Kconfig); \
fi
$(Q)rm -f .tmp.config
# Create new linux.pot file
# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files
# The symlink is used to repair a deficiency in arch/um
update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
$(Q)echo " GEN config"
$(Q)xgettext --default-domain=linux \
--add-comments --keyword=_ --keyword=N_ \
--from-code=UTF-8 \
--files-from=scripts/kconfig/POTFILES.in \
$(Q)$(kecho) " GEN config.pot"
$(Q)xgettext --default-domain=linux \
--add-comments --keyword=_ --keyword=N_ \
--from-code=UTF-8 \
--files-from=$(srctree)/scripts/kconfig/POTFILES.in \
--directory=$(srctree) --directory=$(objtree) \
--output $(obj)/config.pot
$(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot
$(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch
$(Q)(for i in `ls arch/*/Kconfig`; \
$(Q)(for i in `ls $(srctree)/arch/*/Kconfig \
$(srctree)/arch/*/um/Kconfig`; \
do \
echo " GEN $$i"; \
$(kecho) " GEN $$i"; \
$(obj)/kxgettext $$i \
>> $(obj)/config.pot; \
done )
$(Q)$(kecho) " GEN linux.pot"
$(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \
--output $(obj)/linux.pot
$(Q)rm -f arch/um/Kconfig.arch
$(Q)rm -f $(obj)/config.pot
PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig
# These targets map 1:1 to the commandline options of 'conf'
simple-targets := oldconfig allnoconfig allyesconfig \
alldefconfig randconfig listnewconfig olddefconfig
PHONY += $(simple-targets)
randconfig: $(obj)/conf
$< -r $(Kconfig)
$(simple-targets): $(obj)/conf
$< $(silent) --$@ $(Kconfig)
allyesconfig: $(obj)/conf
$< -y $(Kconfig)
PHONY += oldnoconfig savedefconfig defconfig
allnoconfig: $(obj)/conf
$< -n $(Kconfig)
# oldnoconfig is an alias of olddefconfig, because people already are dependent
# on its behavior (sets new symbols to their default value but not 'n') with the
# counter-intuitive name.
oldnoconfig: olddefconfig
allmodconfig: $(obj)/conf
$< -m $(Kconfig)
savedefconfig: $(obj)/conf
$< $(silent) --$@=defconfig $(Kconfig)
defconfig: $(obj)/conf
ifeq ($(KBUILD_DEFCONFIG),)
$< -d $(Kconfig)
$< $(silent) --defconfig $(Kconfig)
else
@echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
$(Q)$< -D arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
ifneq ($(wildcard $(srctree)/configs/$(KBUILD_DEFCONFIG)),)
@$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
$(Q)$< $(silent) --defconfig=configs/$(KBUILD_DEFCONFIG) $(Kconfig)
else
@$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'"
$(Q)$(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG)
endif
endif
%_defconfig: $(obj)/conf
$(Q)$< -D configs/$@ $(Kconfig)
$(Q)$< $(silent) --defconfig=configs/$@ $(Kconfig)
configfiles=$(wildcard $(srctree)/configs/$@)
%.config: $(obj)/conf
$(if $(call configfiles),, $(error No configuration exists for this target on this architecture))
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles)
+$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
# Help text used by make help
help:
@echo ' config - Update current config utilising a line-oriented program'
@echo ' nconfig - Update current config utilising a ncurses menu based'
@echo ' program'
@echo ' menuconfig - Update current config utilising a menu based program'
@echo ' xconfig - Update current config utilising a QT based front-end'
@echo ' gconfig - Update current config utilising a GTK based front-end'
@echo ' xconfig - Update current config utilising a Qt based front-end'
@echo ' gconfig - Update current config utilising a GTK+ based front-end'
@echo ' oldconfig - Update current config utilising a provided .config as base'
@echo ' localmodconfig - Update current config disabling modules not loaded'
@echo ' localyesconfig - Update current config converting local mods to core'
@echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps'
@echo ' randconfig - New config with random answer to all options'
@echo ' defconfig - New config with default answer to all options'
@echo ' allmodconfig - New config selecting modules when possible'
@echo ' allyesconfig - New config where all options are accepted with yes'
@echo ' defconfig - New config with default from ARCH supplied defconfig'
@echo ' savedefconfig - Save current config as ./defconfig (minimal config)'
@echo ' allnoconfig - New config where all options are answered with no'
@echo ' allyesconfig - New config where all options are accepted with yes'
@echo ' alldefconfig - New config with all symbols set to default'
@echo ' randconfig - New config with random answer to all options'
@echo ' listnewconfig - List new options'
@echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their'
@echo ' default value'
# lxdialog stuff
check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
# Use recursively expanded variables so we do not call gcc unless
# we really need to do so. (Do not call gcc as part of make mrproper)
HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
HOST_EXTRACFLAGS += -DLOCALE
HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
-DLOCALE
# ===========================================================================
# Shared Makefile for the various kconfig executables:
# conf: Used for defconfig, oldconfig and related targets
# nconf: Used for the nconfig target.
# Utilizes ncurses
# mconf: Used for the menuconfig target
# Utilizes the lxdialog package
# qconf: Used for the xconfig target
# Based on QT which needs to be installed to compile it
# Based on Qt which needs to be installed to compile it
# gconf: Used for the gconfig target
# Based on GTK which needs to be installed to compile it
# Based on GTK+ which needs to be installed to compile it
# object files used by all kconfig flavours
lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
conf-objs := conf.o zconf.tab.o
mconf-objs := mconf.o zconf.tab.o $(lxdialog)
mconf-objs := mconf.o zconf.tab.o $(lxdialog)
nconf-objs := nconf.o zconf.tab.o nconf.gui.o
kxgettext-objs := kxgettext.o zconf.tab.o
hostprogs-y := conf qconf gconf kxgettext
ifeq ($(MAKECMDGOALS),menuconfig)
hostprogs-y += mconf
endif
ifeq ($(MAKECMDGOALS),xconfig)
qconf-target := 1
endif
ifeq ($(MAKECMDGOALS),gconfig)
gconf-target := 1
endif
ifeq ($(qconf-target),1)
qconf-cxxobjs := qconf.o
qconf-objs := kconfig_load.o zconf.tab.o
endif
qconf-objs := zconf.tab.o
gconf-objs := gconf.o zconf.tab.o
ifeq ($(gconf-target),1)
gconf-objs := gconf.o kconfig_load.o zconf.tab.o
endif
hostprogs-y := conf nconf mconf kxgettext qconf gconf
clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \
.tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h
clean-files += mconf qconf gconf
clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck
clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h
clean-files += config.pot linux.pot
# Check that we have the required ncurses stuff installed for lxdialog (menuconfig)
PHONY += $(obj)/dochecklxdialog
$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog
$(obj)/dochecklxdialog:
$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES)
$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf)
always := dochecklxdialog
......@@ -202,59 +188,48 @@ always := dochecklxdialog
HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS))
# generated files seem to need this to find local include files
HOSTCFLAGS_lex.zconf.o := -I$(src)
HOSTCFLAGS_zconf.lex.o := -I$(src)
HOSTCFLAGS_zconf.tab.o := -I$(src)
HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl
HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
LEX_PREFIX_zconf := zconf
YACC_PREFIX_zconf := zconf
HOSTLOADLIBES_qconf = $(KC_QT_LIBS)
HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS)
HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
-D LKC_DIRECT_LINK
-Wno-missing-prototypes
HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
HOSTLOADLIBES_nconf = $(shell \
pkg-config --libs menuw panelw ncursesw 2>/dev/null \
|| pkg-config --libs menu panel ncurses 2>/dev/null \
|| echo "-lmenu -lpanel -lncurses" )
$(obj)/qconf.o: $(obj)/.tmp_qtcheck
ifeq ($(qconf-target),1)
ifeq ($(MAKECMDGOALS),xconfig)
$(obj)/.tmp_qtcheck: $(src)/Makefile
-include $(obj)/.tmp_qtcheck
# QT needs some extra effort...
# Qt needs some extra effort...
$(obj)/.tmp_qtcheck:
@set -e; echo " CHECK qt"; dir=""; pkg=""; \
pkg-config --exists qt 2> /dev/null && pkg=qt; \
pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \
if [ -n "$$pkg" ]; then \
cflags="\$$(shell pkg-config $$pkg --cflags)"; \
libs="\$$(shell pkg-config $$pkg --libs)"; \
moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \
dir="$$(pkg-config $$pkg --variable=prefix)"; \
@set -e; $(kecho) " CHECK qt"; \
if pkg-config --exists Qt5Core; then \
cflags="-std=c++11 -fPIC `pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets`"; \
libs=`pkg-config --libs Qt5Core Qt5Gui Qt5Widgets`; \
moc=`pkg-config --variable=host_bins Qt5Core`/moc; \
elif pkg-config --exists QtCore; then \
cflags=`pkg-config --cflags QtCore QtGui`; \
libs=`pkg-config --libs QtCore QtGui`; \
moc=`pkg-config --variable=moc_location QtCore`; \
else \
for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \
if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
done; \
if [ -z "$$dir" ]; then \
echo "*"; \
echo "* Unable to find the QT3 installation. Please make sure that"; \
echo "* the QT3 development package is correctly installed and"; \
echo "* either install pkg-config or set the QTDIR environment"; \
echo "* variable to the correct location."; \
echo "*"; \
false; \
fi; \
libpath=$$dir/lib; lib=qt; osdir=""; \
$(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \
osdir=x$$($(HOSTCXX) -print-multi-os-directory); \
test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \
test -f $$libpath/libqt-mt.so && lib=qt-mt; \
cflags="-I$$dir/include"; \
libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \
moc="$$dir/bin/moc"; \
fi; \
if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \
echo "*"; \
echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \
echo "*"; \
moc="/usr/bin/moc"; \
echo >&2 "*"; \
echo >&2 "* Could not find Qt via pkg-config."; \
echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH"; \
echo >&2 "*"; \
exit 1; \
fi; \
echo "KC_QT_CFLAGS=$$cflags" > $@; \
echo "KC_QT_LIBS=$$libs" >> $@; \
......@@ -263,70 +238,41 @@ endif
$(obj)/gconf.o: $(obj)/.tmp_gtkcheck
ifeq ($(gconf-target),1)
ifeq ($(MAKECMDGOALS),gconfig)
-include $(obj)/.tmp_gtkcheck
# GTK needs some extra effort, too...
# GTK+ needs some extra effort, too...
$(obj)/.tmp_gtkcheck:
@if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \
if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \
touch $@; \
else \
echo "*"; \
echo "* GTK+ is present but version >= 2.0.0 is required."; \
echo "*"; \
echo >&2 "*"; \
echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \
echo >&2 "*"; \
false; \
fi \
else \
echo "*"; \
echo "* Unable to find the GTK+ installation. Please make sure that"; \
echo "* the GTK+ 2.0 development package is correctly installed..."; \
echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \
echo "*"; \
echo >&2 "*"; \
echo >&2 "* Unable to find the GTK+ installation. Please make sure that"; \
echo >&2 "* the GTK+ 2.0 development package is correctly installed..."; \
echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \
echo >&2 "*"; \
false; \
fi
endif
$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c
$(obj)/kconfig_load.o: $(obj)/lkc_defs.h
$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h
$(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c
$(obj)/gconf.o: $(obj)/lkc_defs.h
$(obj)/qconf.o: $(obj)/qconf.moc
$(obj)/%.moc: $(src)/%.h
$(KC_QT_MOC) -i $< -o $@
quiet_cmd_moc = MOC $@
cmd_moc = $(KC_QT_MOC) -i $< -o $@
$(obj)/lkc_defs.h: $(src)/lkc_proto.h
sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck
$(call cmd,moc)
# Extract gconf menu items for I18N support
# Extract gconf menu items for i18n support
$(obj)/gconf.glade.h: $(obj)/gconf.glade
intltool-extract --type=gettext/glade $(obj)/gconf.glade
###
# The following requires flex/bison/gperf
# By default we use the _shipped versions, uncomment the following line if
# you are modifying the flex/bison src.
# LKC_GENPARSER := 1
ifdef LKC_GENPARSER
$(obj)/zconf.tab.c: $(src)/zconf.y
$(obj)/lex.zconf.c: $(src)/zconf.l
$(obj)/zconf.hash.c: $(src)/zconf.gperf
%.tab.c: %.y
bison -l -b $* -p $(notdir $*) $<
cp $@ $@_shipped
lex.%.c: %.l
flex -L -P$(notdir $*) -o$@ $<
cp $@ $@_shipped
%.hash.c: %.gperf
gperf < $< > $@
cp $@ $@_shipped
endif
$(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \
$(obj)/gconf.glade
#!/bin/sh
# Needed for systems without gettext
$* -xc -o /dev/null - > /dev/null 2>&1 << EOF
$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
#include <libintl.h>
int main()
{
......@@ -11,4 +11,3 @@ EOF
if [ ! "$?" -eq "0" ]; then
echo -DKBUILD_NO_NLS;
fi
......@@ -5,37 +5,44 @@
#include <locale.h>
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <errno.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
static void conf(struct menu *menu);
static void check_conf(struct menu *menu);
enum {
ask_all,
ask_new,
ask_silent,
set_default,
set_yes,
set_mod,
set_no,
set_random
} input_mode = ask_all;
char *defconfig_file;
static void xfgets(char *str, int size, FILE *in);
enum input_mode {
oldaskconfig,
silentoldconfig,
oldconfig,
allnoconfig,
allyesconfig,
allmodconfig,
alldefconfig,
randconfig,
defconfig,
savedefconfig,
listnewconfig,
olddefconfig,
} input_mode = oldaskconfig;
static int indent = 1;
static int tty_stdio;
static int valid_stdin = 1;
static int sync_kconfig;
static int conf_cnt;
static char line[128];
static char line[PATH_MAX];
static struct menu *rootEntry;
static void print_help(struct menu *menu)
......@@ -93,16 +100,19 @@ static int conf_askvalue(struct symbol *sym, const char *def)
}
switch (input_mode) {
case ask_new:
case ask_silent:
case oldconfig:
case silentoldconfig:
if (sym_has_value(sym)) {
printf("%s\n", def);
return 0;
}
check_stdin();
case ask_all:
/* fall through */
case oldaskconfig:
fflush(stdout);
fgets(line, 128, stdin);
xfgets(line, sizeof(line), stdin);
if (!tty_stdio)
printf("\n");
return 1;
default:
break;
......@@ -144,6 +154,7 @@ static int conf_string(struct menu *menu)
def = NULL;
break;
}
/* fall through */
default:
line[strlen(line)-1] = 0;
def = line;
......@@ -156,14 +167,12 @@ static int conf_string(struct menu *menu)
static int conf_sym(struct menu *menu)
{
struct symbol *sym = menu->sym;
int type;
tristate oldval, newval;
while (1) {
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
if (sym->name)
printf("(%s) ", sym->name);
type = sym_get_type(sym);
putchar('[');
oldval = sym_get_tristate_value(sym);
switch (oldval) {
......@@ -228,11 +237,9 @@ static int conf_choice(struct menu *menu)
{
struct symbol *sym, *def_sym;
struct menu *child;
int type;
bool is_new;
sym = menu->sym;
type = sym_get_type(sym);
is_new = !sym_has_value(sym);
if (sym_is_changable(sym)) {
conf_sym(menu);
......@@ -294,17 +301,18 @@ static int conf_choice(struct menu *menu)
printf("?");
printf("]: ");
switch (input_mode) {
case ask_new:
case ask_silent:
case oldconfig:
case silentoldconfig:
if (!is_new) {
cnt = def;
printf("%d\n", cnt);
break;
}
check_stdin();
case ask_all:
/* fall through */
case oldaskconfig:
fflush(stdout);
fgets(line, 128, stdin);
xfgets(line, sizeof(line), stdin);
strip(line);
if (line[0] == '?') {
print_help(menu);
......@@ -330,7 +338,7 @@ static int conf_choice(struct menu *menu)
}
if (!child)
continue;
if (line[strlen(line) - 1] == '?') {
if (line[0] && line[strlen(line) - 1] == '?') {
print_help(child);
continue;
}
......@@ -360,10 +368,14 @@ static void conf(struct menu *menu)
switch (prop->type) {
case P_MENU:
if (input_mode == ask_silent && rootEntry != menu) {
if ((input_mode == silentoldconfig ||
input_mode == listnewconfig ||
input_mode == olddefconfig) &&
rootEntry != menu) {
check_conf(menu);
return;
}
/* fall through */
case P_COMMENT:
prompt = menu_get_prompt(menu);
if (prompt)
......@@ -418,10 +430,16 @@ static void check_conf(struct menu *menu)
if (sym && !sym_has_value(sym)) {
if (sym_is_changable(sym) ||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
if (!conf_cnt++)
printf(_("*\n* Restart config...\n*\n"));
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
if (input_mode == listnewconfig) {
if (sym->name && !sym_is_choice_value(sym)) {
printf("%s%s\n", CONFIG_, sym->name);
}
} else if (input_mode != olddefconfig) {
if (!conf_cnt++)
printf(_("*\n* Restart config...\n*\n"));
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
}
}
......@@ -429,69 +447,118 @@ static void check_conf(struct menu *menu)
check_conf(child);
}
static struct option long_opts[] = {
{"oldaskconfig", no_argument, NULL, oldaskconfig},
{"oldconfig", no_argument, NULL, oldconfig},
{"silentoldconfig", no_argument, NULL, silentoldconfig},
{"defconfig", optional_argument, NULL, defconfig},
{"savedefconfig", required_argument, NULL, savedefconfig},
{"allnoconfig", no_argument, NULL, allnoconfig},
{"allyesconfig", no_argument, NULL, allyesconfig},
{"allmodconfig", no_argument, NULL, allmodconfig},
{"alldefconfig", no_argument, NULL, alldefconfig},
{"randconfig", no_argument, NULL, randconfig},
{"listnewconfig", no_argument, NULL, listnewconfig},
{"olddefconfig", no_argument, NULL, olddefconfig},
/*
* oldnoconfig is an alias of olddefconfig, because people already
* are dependent on its behavior(sets new symbols to their default
* value but not 'n') with the counter-intuitive name.
*/
{"oldnoconfig", no_argument, NULL, olddefconfig},
{NULL, 0, NULL, 0}
};
static void conf_usage(const char *progname)
{
printf("Usage: %s [-s] [option] <kconfig-file>\n", progname);
printf("[option] is _one_ of the following:\n");
printf(" --listnewconfig List new options\n");
printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
printf(" --oldconfig Update a configuration using a provided .config as base\n");
printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n");
printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n");
printf(" --oldnoconfig An alias of olddefconfig\n");
printf(" --defconfig <file> New config with default defined in <file>\n");
printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
printf(" --allnoconfig New config where all options are answered with no\n");
printf(" --allyesconfig New config where all options are answered with yes\n");
printf(" --allmodconfig New config where all options are answered with mod\n");
printf(" --alldefconfig New config with all symbols set to default\n");
printf(" --randconfig New config with random answer to all options\n");
}
int main(int ac, char **av)
{
const char *progname = av[0];
int opt;
const char *name;
const char *name, *defconfig_file = NULL /* gcc uninit */;
struct stat tmpstat;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
tty_stdio = isatty(0) && isatty(1) && isatty(2);
while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
if (opt == 's') {
conf_set_message_callback(NULL);
continue;
}
input_mode = (enum input_mode)opt;
switch (opt) {
case 'o':
input_mode = ask_silent;
break;
case 's':
input_mode = ask_silent;
case silentoldconfig:
sync_kconfig = 1;
break;
case 'd':
input_mode = set_default;
break;
case 'D':
input_mode = set_default;
case defconfig:
case savedefconfig:
defconfig_file = optarg;
break;
case 'n':
input_mode = set_no;
break;
case 'm':
input_mode = set_mod;
break;
case 'y':
input_mode = set_yes;
break;
case 'r':
case randconfig:
{
struct timeval now;
unsigned int seed;
char *seed_env;
/*
* Use microseconds derived seed,
* compensate for systems where it may be zero
*/
gettimeofday(&now, NULL);
seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
srand(seed);
input_mode = set_random;
seed_env = getenv("KCONFIG_SEED");
if( seed_env && *seed_env ) {
char *endp;
int tmp = (int)strtol(seed_env, &endp, 0);
if (*endp == '\0') {
seed = tmp;
}
}
fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
srand(seed);
break;
}
case 'h':
printf(_("See README for usage info\n"));
exit(0);
case oldaskconfig:
case oldconfig:
case allnoconfig:
case allyesconfig:
case allmodconfig:
case alldefconfig:
case listnewconfig:
case olddefconfig:
break;
default:
fprintf(stderr, _("See README for usage info\n"));
case '?':
conf_usage(progname);
exit(1);
break;
}
}
if (ac == optind) {
printf(_("%s: Kconfig file missing\n"), av[0]);
conf_usage(progname);
exit(1);
}
name = av[optind];
......@@ -501,8 +568,7 @@ int main(int ac, char **av)
name = conf_get_configname();
if (stat(name, &tmpstat)) {
fprintf(stderr, _("***\n"
"*** You have not yet configured your WRS-sw!\n"
"*** (missing config file \"%s\")\n"
"*** Configuration file \"%s\" not found!\n"
"***\n"
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
"*** \"make menuconfig\" or \"make xconfig\").\n"
......@@ -512,7 +578,7 @@ int main(int ac, char **av)
}
switch (input_mode) {
case set_default:
case defconfig:
if (!defconfig_file)
defconfig_file = conf_get_default_confname();
if (conf_read(defconfig_file)) {
......@@ -522,31 +588,46 @@ int main(int ac, char **av)
exit(1);
}
break;
case ask_silent:
case ask_all:
case ask_new:
case savedefconfig:
case silentoldconfig:
case oldaskconfig:
case oldconfig:
case listnewconfig:
case olddefconfig:
conf_read(NULL);
break;
case set_no:
case set_mod:
case set_yes:
case set_random:
case allnoconfig:
case allyesconfig:
case allmodconfig:
case alldefconfig:
case randconfig:
name = getenv("KCONFIG_ALLCONFIG");
if (name && !stat(name, &tmpstat)) {
conf_read_simple(name, S_DEF_USER);
if (!name)
break;
if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
if (conf_read_simple(name, S_DEF_USER)) {
fprintf(stderr,
_("*** Can't read seed configuration \"%s\"!\n"),
name);
exit(1);
}
break;
}
switch (input_mode) {
case set_no: name = "allno.config"; break;
case set_mod: name = "allmod.config"; break;
case set_yes: name = "allyes.config"; break;
case set_random: name = "allrandom.config"; break;
case allnoconfig: name = "allno.config"; break;
case allyesconfig: name = "allyes.config"; break;
case allmodconfig: name = "allmod.config"; break;
case alldefconfig: name = "alldef.config"; break;
case randconfig: name = "allrandom.config"; break;
default: break;
}
if (!stat(name, &tmpstat))
conf_read_simple(name, S_DEF_USER);
else if (!stat("all.config", &tmpstat))
conf_read_simple("all.config", S_DEF_USER);
if (conf_read_simple(name, S_DEF_USER) &&
conf_read_simple("all.config", S_DEF_USER)) {
fprintf(stderr,
_("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
name);
exit(1);
}
break;
default:
break;
......@@ -557,41 +638,51 @@ int main(int ac, char **av)
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
fprintf(stderr,
_("\n*** WRS-sw configuration requires explicit update.\n\n"));
_("\n*** The configuration requires explicit update.\n\n"));
return 1;
}
}
valid_stdin = isatty(0) && isatty(1) && isatty(2);
valid_stdin = tty_stdio;
}
switch (input_mode) {
case set_no:
case allnoconfig:
conf_set_all_new_symbols(def_no);
break;
case set_yes:
case allyesconfig:
conf_set_all_new_symbols(def_yes);
break;
case set_mod:
case allmodconfig:
conf_set_all_new_symbols(def_mod);
break;
case set_random:
conf_set_all_new_symbols(def_random);
case alldefconfig:
conf_set_all_new_symbols(def_default);
break;
case set_default:
case randconfig:
/* Really nothing to do in this loop */
while (conf_set_all_new_symbols(def_random)) ;
break;
case defconfig:
conf_set_all_new_symbols(def_default);
break;
case ask_new:
case ask_all:
case savedefconfig:
break;
case oldaskconfig:
rootEntry = &rootmenu;
conf(&rootmenu);
input_mode = ask_silent;
input_mode = silentoldconfig;
/* fall through */
case ask_silent:
case oldconfig:
case listnewconfig:
case olddefconfig:
case silentoldconfig:
/* Update until a loop caused no more changes */
do {
conf_cnt = 0;
check_conf(&rootmenu);
} while (conf_cnt);
} while (conf_cnt &&
(input_mode != listnewconfig &&
input_mode != olddefconfig));
break;
}
......@@ -607,7 +698,13 @@ int main(int ac, char **av)
fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
return 1;
}
} else {
} else if (input_mode == savedefconfig) {
if (conf_write_defconfig(defconfig_file)) {
fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
defconfig_file);
return 1;
}
} else if (input_mode != listnewconfig) {
if (conf_write(NULL)) {
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
exit(1);
......@@ -615,3 +712,12 @@ int main(int ac, char **av)
}
return 0;
}
/*
* Helper function to facilitate fgets() by Jean Sacren.
*/
void xfgets(char *str, int size, FILE *in)
{
if (fgets(str, size, in) == NULL)
fprintf(stderr, "\nError in reading or end of file.\n");
}
......@@ -5,23 +5,32 @@
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
struct conf_printer {
void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
void (*print_comment)(FILE *, const char *, void *);
};
static void conf_warning(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
static void conf_message(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
static const char *conf_filename;
static int conf_lineno, conf_warnings, conf_unsaved;
const char conf_defname[] = "Kconfig";
const char conf_defname[] = "arch/$ARCH/defconfig";
static void conf_warning(const char *fmt, ...)
{
......@@ -34,6 +43,30 @@ static void conf_warning(const char *fmt, ...)
conf_warnings++;
}
static void conf_default_message_callback(const char *fmt, va_list ap)
{
printf("#\n# ");
vprintf(fmt, ap);
printf("\n#\n");
}
static void (*conf_message_callback) (const char *fmt, va_list ap) =
conf_default_message_callback;
void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
{
conf_message_callback = fn;
}
static void conf_message(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (conf_message_callback)
conf_message_callback(fmt, ap);
va_end(ap);
}
const char *conf_get_configname(void)
{
char *name = getenv("KCONFIG_CONFIG");
......@@ -101,6 +134,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
sym->flags |= def_flags;
break;
}
/* fall through */
case S_BOOLEAN:
if (p[0] == 'y') {
sym->def[def].tri = yes;
......@@ -112,8 +146,10 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
sym->flags |= def_flags;
break;
}
conf_warning("symbol value '%s' invalid for %s", p, sym->name);
break;
if (def != S_DEF_AUTO)
conf_warning("symbol value '%s' invalid for %s",
p, sym->name);
return 1;
case S_OTHER:
if (*p != '"') {
for (p2 = p; *p2 && !isspace(*p2); p2++)
......@@ -121,6 +157,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
sym->type = S_STRING;
goto done;
}
/* fall through */
case S_STRING:
if (*p++ != '"')
break;
......@@ -132,9 +169,11 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
memmove(p2, p2 + 1, strlen(p2));
}
if (!p2) {
conf_warning("invalid string found");
if (def != S_DEF_AUTO)
conf_warning("invalid string found");
return 1;
}
/* fall through */
case S_INT:
case S_HEX:
done:
......@@ -142,7 +181,9 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
sym->def[def].val = strdup(p);
sym->flags |= def_flags;
} else {
conf_warning("symbol value '%s' invalid for %s", p, sym->name);
if (def != S_DEF_AUTO)
conf_warning("symbol value '%s' invalid for %s",
p, sym->name);
return 1;
}
break;
......@@ -152,10 +193,66 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
return 0;
}
#define LINE_GROWTH 16
static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
{
char *nline;
size_t new_size = slen + 1;
if (new_size > *n) {
new_size += LINE_GROWTH - 1;
new_size *= 2;
nline = realloc(*lineptr, new_size);
if (!nline)
return -1;
*lineptr = nline;
*n = new_size;
}
(*lineptr)[slen] = c;
return 0;
}
static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
{
char *line = *lineptr;
size_t slen = 0;
for (;;) {
int c = getc(stream);
switch (c) {
case '\n':
if (add_byte(c, &line, slen, n) < 0)
goto e_out;
slen++;
/* fall through */
case EOF:
if (add_byte('\0', &line, slen, n) < 0)
goto e_out;
*lineptr = line;
if (slen == 0)
return -1;
return slen;
default:
if (add_byte(c, &line, slen, n) < 0)
goto e_out;
slen++;
}
}
e_out:
line[slen-1] = '\0';
*lineptr = line;
return -1;
}
int conf_read_simple(const char *name, int def)
{
FILE *in = NULL;
char line[1024];
char *line = NULL;
size_t line_asize = 0;
char *p, *p2;
struct symbol *sym;
int i, def_flags;
......@@ -180,9 +277,8 @@ int conf_read_simple(const char *name, int def)
name = conf_expand_value(prop->expr->left.sym->name);
in = zconf_fopen(name);
if (in) {
printf(_("#\n"
"# using defaults found in %s\n"
"#\n"), name);
conf_message(_("using defaults found in %s"),
name);
goto load;
}
}
......@@ -208,33 +304,33 @@ load:
case S_STRING:
if (sym->def[def].val)
free(sym->def[def].val);
/* fall through */
default:
sym->def[def].val = NULL;
sym->def[def].tri = no;
}
}
while (fgets(line, sizeof(line), in)) {
while (compat_getline(&line, &line_asize, in) != -1) {
conf_lineno++;
sym = NULL;
switch (line[0]) {
case '#':
if (memcmp(line + 2, "CONFIG_", 7))
if (line[0] == '#') {
if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
continue;
p = strchr(line + 9, ' ');
p = strchr(line + 2 + strlen(CONFIG_), ' ');
if (!p)
continue;
*p++ = 0;
if (strncmp(p, "is not set", 10))
continue;
if (def == S_DEF_USER) {
sym = sym_find(line + 9);
sym = sym_find(line + 2 + strlen(CONFIG_));
if (!sym) {
sym_add_change_count(1);
break;
goto setsym;
}
} else {
sym = sym_lookup(line + 9, 0);
sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
if (sym->type == S_UNKNOWN)
sym->type = S_BOOLEAN;
}
......@@ -250,13 +346,8 @@ load:
default:
;
}
break;
case 'C':
if (memcmp(line, "CONFIG_", 7)) {
conf_warning("unexpected data");
continue;
}
p = strchr(line + 7, '=');
} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
p = strchr(line + strlen(CONFIG_), '=');
if (!p)
continue;
*p++ = 0;
......@@ -267,13 +358,13 @@ load:
*p2 = 0;
}
if (def == S_DEF_USER) {
sym = sym_find(line + 7);
sym = sym_find(line + strlen(CONFIG_));
if (!sym) {
sym_add_change_count(1);
break;
goto setsym;
}
} else {
sym = sym_lookup(line + 7, 0);
sym = sym_lookup(line + strlen(CONFIG_), 0);
if (sym->type == S_UNKNOWN)
sym->type = S_OTHER;
}
......@@ -282,14 +373,14 @@ load:
}
if (conf_set_sym_val(sym, def, def_flags, p))
continue;
break;
case '\r':
case '\n':
break;
default:
conf_warning("unexpected data");
} else {
if (line[0] != '\r' && line[0] != '\n')
conf_warning("unexpected data: %.*s",
(int)strcspn(line, "\r\n"), line);
continue;
}
setsym:
if (sym && sym_is_choice_value(sym)) {
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
switch (sym->def[def].tri) {
......@@ -310,29 +401,29 @@ load:
cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
}
}
free(line);
fclose(in);
if (modules_sym)
sym_calc_value(modules_sym);
return 0;
}
int conf_read(const char *name)
{
struct symbol *sym, *choice_sym;
struct property *prop;
struct expr *e;
int i, flags;
struct symbol *sym;
int i;
sym_set_change_count(0);
if (conf_read_simple(name, S_DEF_USER))
if (conf_read_simple(name, S_DEF_USER)) {
sym_calc_value(modules_sym);
return 1;
}
sym_calc_value(modules_sym);
for_all_symbols(i, sym) {
sym_calc_value(sym);
if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
goto sym_ok;
continue;
if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
/* check that calculated value agrees with saved value */
switch (sym->type) {
......@@ -341,29 +432,18 @@ int conf_read(const char *name)
if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
break;
if (!sym_is_choice(sym))
goto sym_ok;
continue;
/* fall through */
default:
if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
goto sym_ok;
continue;
break;
}
} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
/* no previous value and not saved */
goto sym_ok;
continue;
conf_unsaved++;
/* maybe print value in verbose mode... */
sym_ok:
if (!sym_is_choice(sym))
continue;
/* The choice symbol only has a set value (and thus is not new)
* if all its visible childs have values.
*/
prop = sym_get_choice_prop(sym);
flags = sym->flags;
expr_list_for_each_sym(prop->expr, e, choice_sym)
if (choice_sym->visible != no)
flags &= choice_sym->flags;
sym->flags &= flags | ~SYMBOL_DEF_USER;
}
for_all_symbols(i, sym) {
......@@ -396,17 +476,276 @@ int conf_read(const char *name)
return 0;
}
/*
* Kconfig configuration printer
*
* This printer is used when generating the resulting configuration after
* kconfig invocation and `defconfig' files. Unset symbol might be omitted by
* passing a non-NULL argument to the printer.
*
*/
static void
kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
{
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
if (*value == 'n') {
bool skip_unset = (arg != NULL);
if (!skip_unset)
fprintf(fp, "# %s%s is not set\n",
CONFIG_, sym->name);
return;
}
break;
default:
break;
}
fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
}
static void
kconfig_print_comment(FILE *fp, const char *value, void *arg)
{
const char *p = value;
size_t l;
for (;;) {
l = strcspn(p, "\n");
fprintf(fp, "#");
if (l) {
fprintf(fp, " ");
xfwrite(p, l, 1, fp);
p += l;
}
fprintf(fp, "\n");
if (*p++ == '\0')
break;
}
}
static struct conf_printer kconfig_printer_cb =
{
.print_symbol = kconfig_print_symbol,
.print_comment = kconfig_print_comment,
};
/*
* Header printer
*
* This printer is used when generating the `include/generated/autoconf.h' file.
*/
static void
header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
{
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE: {
const char *suffix = "";
switch (*value) {
case 'n':
break;
case 'm':
suffix = "_MODULE";
/* fall through */
default:
fprintf(fp, "#define %s%s%s 1\n",
CONFIG_, sym->name, suffix);
}
break;
}
case S_HEX: {
const char *prefix = "";
if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
prefix = "0x";
fprintf(fp, "#define %s%s %s%s\n",
CONFIG_, sym->name, prefix, value);
break;
}
case S_STRING:
case S_INT:
fprintf(fp, "#define %s%s %s\n",
CONFIG_, sym->name, value);
break;
default:
break;
}
}
static void
header_print_comment(FILE *fp, const char *value, void *arg)
{
const char *p = value;
size_t l;
fprintf(fp, "/*\n");
for (;;) {
l = strcspn(p, "\n");
fprintf(fp, " *");
if (l) {
fprintf(fp, " ");
xfwrite(p, l, 1, fp);
p += l;
}
fprintf(fp, "\n");
if (*p++ == '\0')
break;
}
fprintf(fp, " */\n");
}
static struct conf_printer header_printer_cb =
{
.print_symbol = header_print_symbol,
.print_comment = header_print_comment,
};
/*
* Tristate printer
*
* This printer is used when generating the `include/config/tristate.conf' file.
*/
static void
tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
{
if (sym->type == S_TRISTATE && *value != 'n')
fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
}
static struct conf_printer tristate_printer_cb =
{
.print_symbol = tristate_print_symbol,
.print_comment = kconfig_print_comment,
};
static void conf_write_symbol(FILE *fp, struct symbol *sym,
struct conf_printer *printer, void *printer_arg)
{
const char *str;
switch (sym->type) {
case S_OTHER:
case S_UNKNOWN:
break;
case S_STRING:
str = sym_get_string_value(sym);
str = sym_escape_string_value(str);
printer->print_symbol(fp, sym, str, printer_arg);
free((void *)str);
break;
default:
str = sym_get_string_value(sym);
printer->print_symbol(fp, sym, str, printer_arg);
}
}
static void
conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
{
char buf[256];
snprintf(buf, sizeof(buf),
"\n"
"Automatically generated file; DO NOT EDIT.\n"
"%s\n",
rootmenu.prompt->text);
printer->print_comment(fp, buf, printer_arg);
}
/*
* Write out a minimal config.
* All values that has default values are skipped as this is redundant.
*/
int conf_write_defconfig(const char *filename)
{
struct symbol *sym;
struct menu *menu;
FILE *out;
out = fopen(filename, "w");
if (!out)
return 1;
sym_clear_all_valid();
/* Traverse all menus to find all relevant symbols */
menu = rootmenu.list;
while (menu != NULL)
{
sym = menu->sym;
if (sym == NULL) {
if (!menu_is_visible(menu))
goto next_menu;
} else if (!sym_is_choice(sym)) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE))
goto next_menu;
sym->flags &= ~SYMBOL_WRITE;
/* If we cannot change the symbol - skip */
if (!sym_is_changable(sym))
goto next_menu;
/* If symbol equals to default value - skip */
if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
goto next_menu;
/*
* If symbol is a choice value and equals to the
* default for a choice - skip.
* But only if value is bool and equal to "y" and
* choice is not "optional".
* (If choice is "optional" then all values can be "n")
*/
if (sym_is_choice_value(sym)) {
struct symbol *cs;
struct symbol *ds;
cs = prop_get_symbol(sym_get_choice_prop(sym));
ds = sym_choice_default(cs);
if (!sym_is_optional(cs) && sym == ds) {
if ((sym->type == S_BOOLEAN) &&
sym_get_tristate_value(sym) == yes)
goto next_menu;
}
}
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
}
next_menu:
if (menu->list != NULL) {
menu = menu->list;
}
else if (menu->next != NULL) {
menu = menu->next;
} else {
while ((menu = menu->parent)) {
if (menu->next != NULL) {
menu = menu->next;
break;
}
}
}
}
fclose(out);
return 0;
}
int conf_write(const char *name)
{
FILE *out;
struct symbol *sym;
struct menu *menu;
const char *basename;
char dirname[128], tmpname[128], newname[128];
int type, l;
const char *str;
time_t now;
int use_timestamp = 1;
char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
char *env;
dirname[0] = 0;
......@@ -443,16 +782,7 @@ int conf_write(const char *name)
if (!out)
return 1;
sym = sym_lookup("KERNELVERSION", 0);
sym_calc_value(sym);
time(&now);
env = getenv("KCONFIG_NOTIMESTAMP");
if (env && *env)
use_timestamp = 0;
fprintf(out, _("#\n"
"# Automatically generated make config: don't edit\n"
"#\n"));
conf_write_heading(out, &kconfig_printer_cb, NULL);
if (!conf_get_changed())
sym_clear_all_valid();
......@@ -473,56 +803,11 @@ int conf_write(const char *name)
if (!(sym->flags & SYMBOL_WRITE))
goto next;
sym->flags &= ~SYMBOL_WRITE;
type = sym->type;
if (type == S_TRISTATE) {
sym_calc_value(modules_sym);
if (modules_sym->curr.tri == no)
type = S_BOOLEAN;
}
switch (type) {
case S_BOOLEAN:
case S_TRISTATE:
switch (sym_get_tristate_value(sym)) {
case no:
fprintf(out, "# CONFIG_%s is not set\n", sym->name);
break;
case mod:
fprintf(out, "CONFIG_%s=m\n", sym->name);
break;
case yes:
fprintf(out, "CONFIG_%s=y\n", sym->name);
break;
}
break;
case S_STRING:
str = sym_get_string_value(sym);
fprintf(out, "CONFIG_%s=\"", sym->name);
while (1) {
l = strcspn(str, "\"\\");
if (l) {
fwrite(str, l, 1, out);
str += l;
}
if (!*str)
break;
fprintf(out, "\\%c", *str++);
}
fputs("\"\n", out);
break;
case S_HEX:
str = sym_get_string_value(sym);
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
break;
}
case S_INT:
str = sym_get_string_value(sym);
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
break;
}
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
}
next:
next:
if (menu->list) {
menu = menu->list;
continue;
......@@ -546,9 +831,7 @@ int conf_write(const char *name)
return 1;
}
printf(_("#\n"
"# configuration written to %s\n"
"#\n"), newname);
conf_message(_("configuration written to %s"), newname);
sym_set_change_count(0);
......@@ -558,7 +841,7 @@ int conf_write(const char *name)
static int conf_split_config(void)
{
const char *name;
char path[128];
char path[PATH_MAX+1];
char *s, *d, c;
struct symbol *sym;
struct stat sb;
......@@ -566,6 +849,7 @@ static int conf_split_config(void)
name = conf_get_autoconfig_name();
conf_read_simple(name, S_DEF_AUTO);
sym_calc_value(modules_sym);
if (chdir("include/config"))
return 1;
......@@ -670,11 +954,9 @@ out:
int conf_write_autoconf(void)
{
struct symbol *sym;
const char *str;
const char *name;
FILE *out, *tristate, *out_h;
time_t now;
int i, l;
int i;
sym_clear_all_valid();
......@@ -700,83 +982,23 @@ int conf_write_autoconf(void)
return 1;
}
sym = sym_lookup("KERNELVERSION", 0);
sym_calc_value(sym);
time(&now);
fprintf(out, "#\n"
"# Automatically generated make config: don't edit\n"
"# %s"
"#\n",
ctime(&now));
fprintf(tristate, "#\n"
"# Automatically generated - do not edit\n"
"\n");
fprintf(out_h, "/*\n"
" * Automatically generated C config: don't edit\n"
" * %s"
" */\n"
"#define AUTOCONF_INCLUDED\n",
ctime(&now));
conf_write_heading(out, &kconfig_printer_cb, NULL);
conf_write_heading(tristate, &tristate_printer_cb, NULL);
conf_write_heading(out_h, &header_printer_cb, NULL);
for_all_symbols(i, sym) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
continue;
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
switch (sym_get_tristate_value(sym)) {
case no:
break;
case mod:
fprintf(out, "CONFIG_%s=m\n", sym->name);
fprintf(tristate, "CONFIG_%s=M\n", sym->name);
fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
break;
case yes:
fprintf(out, "CONFIG_%s=y\n", sym->name);
if (sym->type == S_TRISTATE)
fprintf(tristate, "CONFIG_%s=Y\n",
sym->name);
fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
break;
}
break;
case S_STRING:
str = sym_get_string_value(sym);
fprintf(out, "CONFIG_%s=\"", sym->name);
fprintf(out_h, "#define CONFIG_%s \"", sym->name);
while (1) {
l = strcspn(str, "\"\\");
if (l) {
fwrite(str, l, 1, out);
fwrite(str, l, 1, out_h);
str += l;
}
if (!*str)
break;
fprintf(out, "\\%c", *str);
fprintf(out_h, "\\%c", *str);
str++;
}
fputs("\"\n", out);
fputs("\"\n", out_h);
break;
case S_HEX:
str = sym_get_string_value(sym);
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
break;
}
case S_INT:
str = sym_get_string_value(sym);
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
break;
default:
break;
}
/* write symbol to auto.conf, tristate and header files */
conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
}
fclose(out);
fclose(tristate);
......@@ -830,20 +1052,131 @@ void conf_set_changed_callback(void (*fn)(void))
conf_changed_callback = fn;
}
static bool randomize_choice_values(struct symbol *csym)
{
struct property *prop;
struct symbol *sym;
struct expr *e;
int cnt, def;
/*
* If choice is mod then we may have more items selected
* and if no then no-one.
* In both cases stop.
*/
if (csym->curr.tri != yes)
return false;
prop = sym_get_choice_prop(csym);
/* count entries in choice block */
cnt = 0;
expr_list_for_each_sym(prop->expr, e, sym)
cnt++;
/*
* find a random value and set it to yes,
* set the rest to no so we have only one set
*/
def = (rand() % cnt);
cnt = 0;
expr_list_for_each_sym(prop->expr, e, sym) {
if (def == cnt++) {
sym->def[S_DEF_USER].tri = yes;
csym->def[S_DEF_USER].val = sym;
}
else {
sym->def[S_DEF_USER].tri = no;
}
sym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */
sym->flags &= ~SYMBOL_VALID;
}
csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */
csym->flags &= ~(SYMBOL_VALID);
return true;
}
void conf_set_all_new_symbols(enum conf_def_mode mode)
void set_all_choice_values(struct symbol *csym)
{
struct symbol *sym, *csym;
struct property *prop;
struct symbol *sym;
struct expr *e;
int i, cnt, def;
prop = sym_get_choice_prop(csym);
/*
* Set all non-assinged choice values to no
*/
expr_list_for_each_sym(prop->expr, e, sym) {
if (!sym_has_value(sym))
sym->def[S_DEF_USER].tri = no;
}
csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */
csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
}
bool conf_set_all_new_symbols(enum conf_def_mode mode)
{
struct symbol *sym, *csym;
int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y
* pty: probability of tristate = y
* ptm: probability of tristate = m
*/
pby = 50; pty = ptm = 33; /* can't go as the default in switch-case
* below, otherwise gcc whines about
* -Wmaybe-uninitialized */
if (mode == def_random) {
int n, p[3];
char *env = getenv("KCONFIG_PROBABILITY");
n = 0;
while( env && *env ) {
char *endp;
int tmp = strtol( env, &endp, 10 );
if( tmp >= 0 && tmp <= 100 ) {
p[n++] = tmp;
} else {
errno = ERANGE;
perror( "KCONFIG_PROBABILITY" );
exit( 1 );
}
env = (*endp == ':') ? endp+1 : endp;
if( n >=3 ) {
break;
}
}
switch( n ) {
case 1:
pby = p[0]; ptm = pby/2; pty = pby-ptm;
break;
case 2:
pty = p[0]; ptm = p[1]; pby = pty + ptm;
break;
case 3:
pby = p[0]; pty = p[1]; ptm = p[2];
break;
}
if( pty+ptm > 100 ) {
errno = ERANGE;
perror( "KCONFIG_PROBABILITY" );
exit( 1 );
}
}
bool has_changed = false;
for_all_symbols(i, sym) {
if (sym_has_value(sym))
if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
continue;
switch (sym_get_type(sym)) {
case S_BOOLEAN:
case S_TRISTATE:
has_changed = true;
switch (mode) {
case def_yes:
sym->def[S_DEF_USER].tri = yes;
......@@ -852,10 +1185,21 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
sym->def[S_DEF_USER].tri = mod;
break;
case def_no:
sym->def[S_DEF_USER].tri = no;
if (sym->flags & SYMBOL_ALLNOCONFIG_Y)
sym->def[S_DEF_USER].tri = yes;
else
sym->def[S_DEF_USER].tri = no;
break;
case def_random:
sym->def[S_DEF_USER].tri = (tristate)(rand() % 3);
sym->def[S_DEF_USER].tri = no;
cnt = rand() % 100;
if (sym->type == S_TRISTATE) {
if (cnt < pty)
sym->def[S_DEF_USER].tri = yes;
else if (cnt < (pty+ptm))
sym->def[S_DEF_USER].tri = mod;
} else if (cnt < pby)
sym->def[S_DEF_USER].tri = yes;
break;
default:
continue;
......@@ -871,51 +1215,35 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
sym_clear_all_valid();
if (mode != def_random)
return;
/*
* We have different type of choice blocks.
* If curr.tri equal to mod then we can select several
* If curr.tri equals to mod then we can select several
* choice symbols in one block.
* In this case we do nothing.
* If curr.tri equal yes then only one symbol can be
* If curr.tri equals yes then only one symbol can be
* selected in a choice block and we set it to yes,
* and the rest to no.
*/
if (mode != def_random) {
for_all_symbols(i, csym) {
if ((sym_is_choice(csym) && !sym_has_value(csym)) ||
sym_is_choice_value(csym))
csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;
}
}
for_all_symbols(i, csym) {
if (sym_has_value(csym) || !sym_is_choice(csym))
continue;
sym_calc_value(csym);
if (csym->curr.tri != yes)
continue;
prop = sym_get_choice_prop(csym);
/* count entries in choice block */
cnt = 0;
expr_list_for_each_sym(prop->expr, e, sym)
cnt++;
/*
* find a random value and set it to yes,
* set the rest to no so we have only one set
*/
def = (rand() % cnt);
cnt = 0;
expr_list_for_each_sym(prop->expr, e, sym) {
if (def == cnt++) {
sym->def[S_DEF_USER].tri = yes;
csym->def[S_DEF_USER].val = sym;
}
else {
sym->def[S_DEF_USER].tri = no;
}
if (mode == def_random)
has_changed = randomize_choice_values(csym);
else {
set_all_choice_values(csym);
has_changed = true;
}
csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */
csym->flags &= ~(SYMBOL_VALID);
}
return has_changed;
}
......@@ -7,15 +7,16 @@
#include <stdlib.h>
#include <string.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
#define DEBUG_EXPR 0
static int expr_eq(struct expr *e1, struct expr *e2);
static struct expr *expr_eliminate_yn(struct expr *e);
struct expr *expr_alloc_symbol(struct symbol *sym)
{
struct expr *e = malloc(sizeof(*e));
memset(e, 0, sizeof(*e));
struct expr *e = xcalloc(1, sizeof(*e));
e->type = E_SYMBOL;
e->left.sym = sym;
return e;
......@@ -23,8 +24,7 @@ struct expr *expr_alloc_symbol(struct symbol *sym)
struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
{
struct expr *e = malloc(sizeof(*e));
memset(e, 0, sizeof(*e));
struct expr *e = xcalloc(1, sizeof(*e));
e->type = type;
e->left.expr = ce;
return e;
......@@ -32,8 +32,7 @@ struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
{
struct expr *e = malloc(sizeof(*e));
memset(e, 0, sizeof(*e));
struct expr *e = xcalloc(1, sizeof(*e));
e->type = type;
e->left.expr = e1;
e->right.expr = e2;
......@@ -42,8 +41,7 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
{
struct expr *e = malloc(sizeof(*e));
memset(e, 0, sizeof(*e));
struct expr *e = xcalloc(1, sizeof(*e));
e->type = type;
e->left.sym = s1;
e->right.sym = s2;
......@@ -64,14 +62,14 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
}
struct expr *expr_copy(struct expr *org)
struct expr *expr_copy(const struct expr *org)
{
struct expr *e;
if (!org)
return NULL;
e = malloc(sizeof(*org));
e = xmalloc(sizeof(*org));
memcpy(e, org, sizeof(*org));
switch (org->type) {
case E_SYMBOL:
......@@ -81,6 +79,10 @@ struct expr *expr_copy(struct expr *org)
e->left.expr = expr_copy(org->left.expr);
break;
case E_EQUAL:
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
e->left.sym = org->left.sym;
e->right.sym = org->right.sym;
......@@ -113,6 +115,10 @@ void expr_free(struct expr *e)
expr_free(e->left.expr);
return;
case E_EQUAL:
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
break;
case E_OR:
......@@ -191,7 +197,7 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
#undef e1
#undef e2
int expr_eq(struct expr *e1, struct expr *e2)
static int expr_eq(struct expr *e1, struct expr *e2)
{
int res, old_count;
......@@ -199,6 +205,10 @@ int expr_eq(struct expr *e1, struct expr *e2)
return 0;
switch (e1->type) {
case E_EQUAL:
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
case E_SYMBOL:
......@@ -233,7 +243,7 @@ int expr_eq(struct expr *e1, struct expr *e2)
return 0;
}
struct expr *expr_eliminate_yn(struct expr *e)
static struct expr *expr_eliminate_yn(struct expr *e)
{
struct expr *tmp;
......@@ -558,62 +568,6 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
#undef e2
}
static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
#define e1 (*ep1)
#define e2 (*ep2)
struct expr *tmp, *tmp1, *tmp2;
if (e1->type == type) {
expr_eliminate_dups2(type, &e1->left.expr, &e2);
expr_eliminate_dups2(type, &e1->right.expr, &e2);
return;
}
if (e2->type == type) {
expr_eliminate_dups2(type, &e1, &e2->left.expr);
expr_eliminate_dups2(type, &e1, &e2->right.expr);
}
if (e1 == e2)
return;
switch (e1->type) {
case E_OR:
expr_eliminate_dups2(e1->type, &e1, &e1);
// (FOO || BAR) && (!FOO && !BAR) -> n
tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
tmp2 = expr_copy(e2);
tmp = expr_extract_eq_and(&tmp1, &tmp2);
if (expr_is_yes(tmp1)) {
expr_free(e1);
e1 = expr_alloc_symbol(&symbol_no);
trans_count++;
}
expr_free(tmp2);
expr_free(tmp1);
expr_free(tmp);
break;
case E_AND:
expr_eliminate_dups2(e1->type, &e1, &e1);
// (FOO && BAR) || (!FOO || !BAR) -> y
tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
tmp2 = expr_copy(e2);
tmp = expr_extract_eq_or(&tmp1, &tmp2);
if (expr_is_no(tmp1)) {
expr_free(e1);
e1 = expr_alloc_symbol(&symbol_yes);
trans_count++;
}
expr_free(tmp2);
expr_free(tmp1);
expr_free(tmp);
break;
default:
;
}
#undef e1
#undef e2
}
struct expr *expr_eliminate_dups(struct expr *e)
{
int oldcount;
......@@ -626,7 +580,6 @@ struct expr *expr_eliminate_dups(struct expr *e)
switch (e->type) {
case E_OR: case E_AND:
expr_eliminate_dups1(e->type, &e, &e);
expr_eliminate_dups2(e->type, &e, &e);
default:
;
}
......@@ -646,6 +599,10 @@ struct expr *expr_transform(struct expr *e)
return NULL;
switch (e->type) {
case E_EQUAL:
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
case E_SYMBOL:
case E_LIST:
......@@ -718,6 +675,22 @@ struct expr *expr_transform(struct expr *e)
e = tmp;
e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
break;
case E_LEQ:
case E_GEQ:
// !a<='x' -> a>'x'
tmp = e->left.expr;
free(e);
e = tmp;
e->type = e->type == E_LEQ ? E_GTH : E_LTH;
break;
case E_LTH:
case E_GTH:
// !a<'x' -> a>='x'
tmp = e->left.expr;
free(e);
e = tmp;
e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
break;
case E_OR:
// !(a || b) -> !a && !b
tmp = e->left.expr;
......@@ -788,6 +761,10 @@ int expr_contains_symbol(struct expr *dep, struct symbol *sym)
case E_SYMBOL:
return dep->left.sym == sym;
case E_EQUAL:
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
return dep->left.sym == sym ||
dep->right.sym == sym;
......@@ -828,57 +805,6 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
return false;
}
struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
{
struct expr *tmp = NULL;
expr_extract_eq(E_AND, &tmp, ep1, ep2);
if (tmp) {
*ep1 = expr_eliminate_yn(*ep1);
*ep2 = expr_eliminate_yn(*ep2);
}
return tmp;
}
struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
{
struct expr *tmp = NULL;
expr_extract_eq(E_OR, &tmp, ep1, ep2);
if (tmp) {
*ep1 = expr_eliminate_yn(*ep1);
*ep2 = expr_eliminate_yn(*ep2);
}
return tmp;
}
void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
{
#define e1 (*ep1)
#define e2 (*ep2)
if (e1->type == type) {
expr_extract_eq(type, ep, &e1->left.expr, &e2);
expr_extract_eq(type, ep, &e1->right.expr, &e2);
return;
}
if (e2->type == type) {
expr_extract_eq(type, ep, ep1, &e2->left.expr);
expr_extract_eq(type, ep, ep1, &e2->right.expr);
return;
}
if (expr_eq(e1, e2)) {
*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
expr_free(e2);
if (type == E_AND) {
e1 = expr_alloc_symbol(&symbol_yes);
e2 = expr_alloc_symbol(&symbol_yes);
} else if (type == E_OR) {
e1 = expr_alloc_symbol(&symbol_no);
e2 = expr_alloc_symbol(&symbol_no);
}
}
#undef e1
#undef e2
}
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
{
struct expr *e1, *e2;
......@@ -913,6 +839,10 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
case E_NOT:
return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
case E_UNEQUAL:
case E_LTH:
case E_LEQ:
case E_GTH:
case E_GEQ:
case E_EQUAL:
if (type == E_EQUAL) {
if (sym == &symbol_yes)
......@@ -940,10 +870,57 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
return NULL;
}
enum string_value_kind {
k_string,
k_signed,
k_unsigned,
k_invalid
};
union string_value {
unsigned long long u;
signed long long s;
};
static enum string_value_kind expr_parse_string(const char *str,
enum symbol_type type,
union string_value *val)
{
char *tail;
enum string_value_kind kind;
errno = 0;
switch (type) {
case S_BOOLEAN:
case S_TRISTATE:
return k_string;
case S_INT:
val->s = strtoll(str, &tail, 10);
kind = k_signed;
break;
case S_HEX:
val->u = strtoull(str, &tail, 16);
kind = k_unsigned;
break;
case S_STRING:
case S_UNKNOWN:
val->s = strtoll(str, &tail, 0);
kind = k_signed;
break;
default:
return k_invalid;
}
return !errno && !*tail && tail > str && isxdigit(tail[-1])
? kind : k_string;
}
tristate expr_calc_value(struct expr *e)
{
tristate val1, val2;
const char *str1, *str2;
enum string_value_kind k1 = k_string, k2 = k_string;
union string_value lval = {}, rval = {};
int res;
if (!e)
return yes;
......@@ -964,31 +941,70 @@ tristate expr_calc_value(struct expr *e)
val1 = expr_calc_value(e->left.expr);
return EXPR_NOT(val1);
case E_EQUAL:
sym_calc_value(e->left.sym);
sym_calc_value(e->right.sym);
str1 = sym_get_string_value(e->left.sym);
str2 = sym_get_string_value(e->right.sym);
return !strcmp(str1, str2) ? yes : no;
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
sym_calc_value(e->left.sym);
sym_calc_value(e->right.sym);
str1 = sym_get_string_value(e->left.sym);
str2 = sym_get_string_value(e->right.sym);
return !strcmp(str1, str2) ? no : yes;
break;
default:
printf("expr_calc_value: %d?\n", e->type);
return no;
}
sym_calc_value(e->left.sym);
sym_calc_value(e->right.sym);
str1 = sym_get_string_value(e->left.sym);
str2 = sym_get_string_value(e->right.sym);
if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {
k1 = expr_parse_string(str1, e->left.sym->type, &lval);
k2 = expr_parse_string(str2, e->right.sym->type, &rval);
}
if (k1 == k_string || k2 == k_string)
res = strcmp(str1, str2);
else if (k1 == k_invalid || k2 == k_invalid) {
if (e->type != E_EQUAL && e->type != E_UNEQUAL) {
printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2);
return no;
}
res = strcmp(str1, str2);
} else if (k1 == k_unsigned || k2 == k_unsigned)
res = (lval.u > rval.u) - (lval.u < rval.u);
else /* if (k1 == k_signed && k2 == k_signed) */
res = (lval.s > rval.s) - (lval.s < rval.s);
switch(e->type) {
case E_EQUAL:
return res ? no : yes;
case E_GEQ:
return res >= 0 ? yes : no;
case E_GTH:
return res > 0 ? yes : no;
case E_LEQ:
return res <= 0 ? yes : no;
case E_LTH:
return res < 0 ? yes : no;
case E_UNEQUAL:
return res ? yes : no;
default:
printf("expr_calc_value: relation %d?\n", e->type);
return no;
}
}
int expr_compare_type(enum expr_type t1, enum expr_type t2)
static int expr_compare_type(enum expr_type t1, enum expr_type t2)
{
#if 0
return 1;
#else
if (t1 == t2)
return 0;
switch (t1) {
case E_LEQ:
case E_LTH:
case E_GEQ:
case E_GTH:
if (t2 == E_EQUAL || t2 == E_UNEQUAL)
return 1;
case E_EQUAL:
case E_UNEQUAL:
if (t2 == E_NOT)
......@@ -1010,7 +1026,48 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2)
}
printf("[%dgt%d?]", t1, t2);
return 0;
#endif
}
static inline struct expr *
expr_get_leftmost_symbol(const struct expr *e)
{
if (e == NULL)
return NULL;
while (e->type != E_SYMBOL)
e = e->left.expr;
return expr_copy(e);
}
/*
* Given expression `e1' and `e2', returns the leaf of the longest
* sub-expression of `e1' not containing 'e2.
*/
struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
{
struct expr *ret;
switch (e1->type) {
case E_OR:
return expr_alloc_and(
expr_simplify_unmet_dep(e1->left.expr, e2),
expr_simplify_unmet_dep(e1->right.expr, e2));
case E_AND: {
struct expr *e;
e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
e = expr_eliminate_dups(e);
ret = (!expr_eq(e, e1)) ? e1 : NULL;
expr_free(e);
break;
}
default:
ret = e1;
break;
}
return expr_get_leftmost_symbol(ret);
}
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
......@@ -1041,6 +1098,24 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
fn(data, NULL, "=");
fn(data, e->right.sym, e->right.sym->name);
break;
case E_LEQ:
case E_LTH:
if (e->left.sym->name)
fn(data, e->left.sym, e->left.sym->name);
else
fn(data, NULL, "<choice>");
fn(data, NULL, e->type == E_LEQ ? "<=" : "<");
fn(data, e->right.sym, e->right.sym->name);
break;
case E_GEQ:
case E_GTH:
if (e->left.sym->name)
fn(data, e->left.sym, e->left.sym->name);
else
fn(data, NULL, "<choice>");
fn(data, NULL, e->type == E_GEQ ? ">=" : ">");
fn(data, e->right.sym, e->right.sym->name);
break;
case E_UNEQUAL:
if (e->left.sym->name)
fn(data, e->left.sym, e->left.sym->name);
......@@ -1087,7 +1162,7 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
{
fwrite(str, strlen(str), 1, data);
xfwrite(str, strlen(str), 1, data);
}
void expr_fprint(struct expr *e, FILE *out)
......@@ -1097,9 +1172,32 @@ void expr_fprint(struct expr *e, FILE *out)
static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
{
str_append((struct gstr*)data, str);
struct gstr *gs = (struct gstr*)data;
const char *sym_str = NULL;
if (sym)
str_printf((struct gstr*)data, " [=%s]", sym_get_string_value(sym));
sym_str = sym_get_string_value(sym);
if (gs->max_width) {
unsigned extra_length = strlen(str);
const char *last_cr = strrchr(gs->s, '\n');
unsigned last_line_length;
if (sym_str)
extra_length += 4 + strlen(sym_str);
if (!last_cr)
last_cr = gs->s;
last_line_length = strlen(gs->s) - (last_cr - gs->s);
if ((last_line_length + extra_length) > gs->max_width)
str_append(gs, "\\\n");
}
str_append(gs, str);
if (sym && sym->type != S_UNKNOWN)
str_printf(gs, " [=%s]", sym_str);
}
void expr_gstr_print(struct expr *e, struct gstr *gs)
......
......@@ -10,7 +10,9 @@
extern "C" {
#endif
#include <assert.h>
#include <stdio.h>
#include "list.h"
#ifndef __cplusplus
#include <stdbool.h>
#endif
......@@ -18,20 +20,18 @@ extern "C" {
struct file {
struct file *next;
struct file *parent;
char *name;
const char *name;
int lineno;
int flags;
};
#define FILE_BUSY 0x0001
#define FILE_SCANNED 0x0002
typedef enum tristate {
no, mod, yes
} tristate;
enum expr_type {
E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE
E_NONE, E_OR, E_AND, E_NOT,
E_EQUAL, E_UNEQUAL, E_LTH, E_LEQ, E_GTH, E_GEQ,
E_LIST, E_SYMBOL, E_RANGE
};
union expr_data {
......@@ -83,10 +83,11 @@ struct symbol {
tristate visible;
int flags;
struct property *prop;
struct expr_value dir_dep;
struct expr_value rev_dep;
};
#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
#define SYMBOL_CONST 0x0001 /* symbol is const */
#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
......@@ -94,7 +95,7 @@ struct symbol {
#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */
#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
#define SYMBOL_WRITE 0x0200 /* ? */
#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */
#define SYMBOL_CHANGED 0x0400 /* ? */
#define SYMBOL_AUTO 0x1000 /* value from environment variable */
#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
......@@ -107,9 +108,14 @@ struct symbol {
#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */
#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */
/* choice values need to be set before calculating this symbol value */
#define SYMBOL_NEED_SET_CHOICE_VALUES 0x100000
/* Set symbol to y if allnoconfig; used for symbols that hide others */
#define SYMBOL_ALLNOCONFIG_Y 0x200000
#define SYMBOL_MAXLENGTH 256
#define SYMBOL_HASHSIZE 257
#define SYMBOL_HASHMASK 0xff
#define SYMBOL_HASHSIZE 9973
/* A property represent the config options that can be associated
* with a config "symbol".
......@@ -132,6 +138,7 @@ enum prop_type {
P_SELECT, /* select BAR */
P_RANGE, /* range 7..100 (for a symbol) */
P_ENV, /* value from environment variable */
P_SYMBOL, /* where a symbol is defined */
};
struct property {
......@@ -163,6 +170,7 @@ struct menu {
struct menu *list;
struct symbol *sym;
struct property *prompt;
struct expr *visibility;
struct expr *dep;
unsigned int flags;
char *help;
......@@ -174,7 +182,14 @@ struct menu {
#define MENU_CHANGED 0x0001
#define MENU_ROOT 0x0002
#ifndef SWIG
struct jump_key {
struct list_head entries;
size_t offset;
struct menu *target;
int index;
};
#define JUMP_NB 9
extern struct file *file_list;
extern struct file *current_file;
......@@ -190,21 +205,17 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
struct expr *expr_copy(struct expr *org);
struct expr *expr_copy(const struct expr *org);
void expr_free(struct expr *e);
int expr_eq(struct expr *e1, struct expr *e2);
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
tristate expr_calc_value(struct expr *e);
struct expr *expr_eliminate_yn(struct expr *e);
struct expr *expr_trans_bool(struct expr *e);
struct expr *expr_eliminate_dups(struct expr *e);
struct expr *expr_transform(struct expr *e);
int expr_contains_symbol(struct expr *dep, struct symbol *sym);
bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2);
void expr_fprint(struct expr *e, FILE *out);
struct gstr; /* forward */
......@@ -219,7 +230,6 @@ static inline int expr_is_no(struct expr *e)
{
return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
}
#endif
#ifdef __cplusplus
}
......
......@@ -10,6 +10,7 @@
# include <config.h>
#endif
#include <stdlib.h>
#include "lkc.h"
#include "images.c"
......@@ -22,7 +23,6 @@
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
//#define DEBUG
......@@ -30,13 +30,16 @@ enum {
SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
};
enum {
OPT_NORMAL, OPT_ALL, OPT_PROMPT
};
static gint view_mode = FULL_VIEW;
static gboolean show_name = TRUE;
static gboolean show_range = TRUE;
static gboolean show_value = TRUE;
static gboolean show_all = FALSE;
static gboolean show_debug = FALSE;
static gboolean resizeable = FALSE;
static int opt_mode = OPT_NORMAL;
GtkWidget *main_wnd = NULL;
GtkWidget *tree1_w = NULL; // left frame
......@@ -76,36 +79,7 @@ static void conf_changed(void);
/* Helping/Debugging Functions */
const char *dbg_print_stype(int val)
{
static char buf[256];
bzero(buf, 256);
if (val == S_UNKNOWN)
strcpy(buf, "unknown");
if (val == S_BOOLEAN)
strcpy(buf, "boolean");
if (val == S_TRISTATE)
strcpy(buf, "tristate");
if (val == S_INT)
strcpy(buf, "int");
if (val == S_HEX)
strcpy(buf, "hex");
if (val == S_STRING)
strcpy(buf, "string");
if (val == S_OTHER)
strcpy(buf, "other");
#ifdef DEBUG
printf("%s", buf);
#endif
return buf;
}
const char *dbg_print_flags(int val)
const char *dbg_sym_flags(int val)
{
static char buf[256];
......@@ -131,40 +105,10 @@ const char *dbg_print_flags(int val)
strcat(buf, "auto/");
buf[strlen(buf) - 1] = '\0';
#ifdef DEBUG
printf("%s", buf);
#endif
return buf;
}
const char *dbg_print_ptype(int val)
{
static char buf[256];
bzero(buf, 256);
if (val == P_UNKNOWN)
strcpy(buf, "unknown");
if (val == P_PROMPT)
strcpy(buf, "prompt");
if (val == P_COMMENT)
strcpy(buf, "comment");
if (val == P_MENU)
strcpy(buf, "menu");
if (val == P_DEFAULT)
strcpy(buf, "default");
if (val == P_CHOICE)
strcpy(buf, "choice");
#ifdef DEBUG
printf("%s", buf);
#endif
return buf;
}
void replace_button_icon(GladeXML * xml, GdkDrawable * window,
GtkStyle * style, gchar * btn_name, gchar ** xpm)
{
......@@ -189,7 +133,6 @@ void init_main_window(const gchar * glade_file)
GladeXML *xml;
GtkWidget *widget;
GtkTextBuffer *txtbuf;
char title[256];
GtkStyle *style;
xml = glade_xml_new(glade_file, "window1", NULL);
......@@ -226,14 +169,6 @@ void init_main_window(const gchar * glade_file)
style = gtk_widget_get_style(main_wnd);
widget = glade_xml_get_widget(xml, "toolbar1");
#if 0 /* Use stock Gtk icons instead */
replace_button_icon(xml, main_wnd->window, style,
"button1", (gchar **) xpm_back);
replace_button_icon(xml, main_wnd->window, style,
"button2", (gchar **) xpm_load);
replace_button_icon(xml, main_wnd->window, style,
"button3", (gchar **) xpm_save);
#endif
replace_button_icon(xml, main_wnd->window, style,
"button4", (gchar **) xpm_single_view);
replace_button_icon(xml, main_wnd->window, style,
......@@ -241,22 +176,6 @@ void init_main_window(const gchar * glade_file)
replace_button_icon(xml, main_wnd->window, style,
"button6", (gchar **) xpm_tree_view);
#if 0
switch (view_mode) {
case SINGLE_VIEW:
widget = glade_xml_get_widget(xml, "button4");
g_signal_emit_by_name(widget, "clicked");
break;
case SPLIT_VIEW:
widget = glade_xml_get_widget(xml, "button5");
g_signal_emit_by_name(widget, "clicked");
break;
case FULL_VIEW:
widget = glade_xml_get_widget(xml, "button6");
g_signal_emit_by_name(widget, "clicked");
break;
}
#endif
txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
"foreground", "red",
......@@ -266,9 +185,7 @@ void init_main_window(const gchar * glade_file)
/*"style", PANGO_STYLE_OBLIQUE, */
NULL);
sprintf(title, _("WRS-sw v%s Configuration"),
getenv("KERNELVERSION"));
gtk_window_set_title(GTK_WINDOW(main_wnd), title);
gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
gtk_widget_show(main_wnd);
}
......@@ -312,7 +229,7 @@ void init_left_tree(void)
gtk_tree_view_set_model(view, model1);
gtk_tree_view_set_headers_visible(view, TRUE);
gtk_tree_view_set_rules_hint(view, FALSE);
gtk_tree_view_set_rules_hint(view, TRUE);
column = gtk_tree_view_column_new();
gtk_tree_view_append_column(view, column);
......@@ -344,8 +261,6 @@ void init_left_tree(void)
static void renderer_edited(GtkCellRendererText * cell,
const gchar * path_string,
const gchar * new_text, gpointer user_data);
static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
gchar * arg1, gpointer user_data);
void init_right_tree(void)
{
......@@ -357,7 +272,7 @@ void init_right_tree(void)
gtk_tree_view_set_model(view, model2);
gtk_tree_view_set_headers_visible(view, TRUE);
gtk_tree_view_set_rules_hint(view, FALSE);
gtk_tree_view_set_rules_hint(view, TRUE);
column = gtk_tree_view_column_new();
gtk_tree_view_append_column(view, column);
......@@ -379,8 +294,6 @@ void init_right_tree(void)
"inconsistent", COL_BTNINC,
"visible", COL_BTNVIS,
"radio", COL_BTNRAD, NULL);
/*g_signal_connect(G_OBJECT(renderer), "toggled",
G_CALLBACK(renderer_toggled), NULL); */
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
renderer, FALSE);
......@@ -697,20 +610,29 @@ void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
void
on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
opt_mode = OPT_NORMAL;
gtk_tree_store_clear(tree2);
display_tree(&rootmenu); /* instead of update_tree to speed-up */
}
void
on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
{
opt_mode = OPT_ALL;
gtk_tree_store_clear(tree2);
display_tree(&rootmenu); // instead of update_tree to speed-up
display_tree(&rootmenu); /* instead of update_tree to speed-up */
}
void
on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
{
show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
update_tree(&rootmenu, NULL);
opt_mode = OPT_PROMPT;
gtk_tree_store_clear(tree2);
display_tree(&rootmenu); /* instead of update_tree to speed-up */
}
......@@ -719,7 +641,6 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
GtkWidget *dialog;
const gchar *intro_text = _(
"Welcome to gkc, the GTK+ graphical configuration tool\n"
"for WRS-sw software support.\n"
"For each option, a blank box indicates the feature is disabled, a\n"
"check indicates it is enabled, and a dot indicates that it is to\n"
"be compiled as a module. Clicking on the box will cycle through the three states.\n"
......@@ -738,7 +659,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE, intro_text);
GTK_BUTTONS_CLOSE, "%s", intro_text);
g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
G_CALLBACK(gtk_widget_destroy),
GTK_OBJECT(dialog));
......@@ -756,7 +677,7 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE, about_text);
GTK_BUTTONS_CLOSE, "%s", about_text);
g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
G_CALLBACK(gtk_widget_destroy),
GTK_OBJECT(dialog));
......@@ -775,7 +696,7 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE, license_text);
GTK_BUTTONS_CLOSE, "%s", license_text);
g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
G_CALLBACK(gtk_widget_destroy),
GTK_OBJECT(dialog));
......@@ -807,7 +728,6 @@ void on_load_clicked(GtkButton * button, gpointer user_data)
void on_single_clicked(GtkButton * button, gpointer user_data)
{
view_mode = SINGLE_VIEW;
gtk_paned_set_position(GTK_PANED(hpaned), 0);
gtk_widget_hide(tree1_w);
current = &rootmenu;
display_tree_part();
......@@ -833,7 +753,6 @@ void on_split_clicked(GtkButton * button, gpointer user_data)
void on_full_clicked(GtkButton * button, gpointer user_data)
{
view_mode = FULL_VIEW;
gtk_paned_set_position(GTK_PANED(hpaned), 0);
gtk_widget_hide(tree1_w);
if (tree2)
gtk_tree_store_clear(tree2);
......@@ -887,7 +806,7 @@ static void renderer_edited(GtkCellRendererText * cell,
static void change_sym_value(struct menu *menu, gint col)
{
struct symbol *sym = menu->sym;
tristate oldval, newval;
tristate newval;
if (!sym)
return;
......@@ -904,7 +823,6 @@ static void change_sym_value(struct menu *menu, gint col)
switch (sym_get_type(sym)) {
case S_BOOLEAN:
case S_TRISTATE:
oldval = sym_get_tristate_value(sym);
if (!sym_tristate_within_range(sym, newval))
newval = yes;
sym_set_tristate_value(sym, newval);
......@@ -941,35 +859,6 @@ static void toggle_sym_value(struct menu *menu)
display_tree_part(); //fixme: keep exp/coll
}
static void renderer_toggled(GtkCellRendererToggle * cell,
gchar * path_string, gpointer user_data)
{
GtkTreePath *path, *sel_path = NULL;
GtkTreeIter iter, sel_iter;
GtkTreeSelection *sel;
struct menu *menu;
path = gtk_tree_path_new_from_string(path_string);
if (!gtk_tree_model_get_iter(model2, &iter, path))
return;
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
sel_path = gtk_tree_model_get_path(model2, &sel_iter);
if (!sel_path)
goto out1;
if (gtk_tree_path_compare(path, sel_path))
goto out2;
gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
toggle_sym_value(menu);
out2:
gtk_tree_path_free(sel_path);
out1:
gtk_tree_path_free(path);
}
static gint column2index(GtkTreeViewColumn * column)
{
gint i;
......@@ -1161,9 +1050,12 @@ static gchar **fill_row(struct menu *menu)
row[COL_OPTION] =
g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
sym && sym_has_value(sym) ? "(NEW)" : "");
sym && !sym_has_value(sym) ? "(NEW)" : "");
if (show_all && !menu_is_visible(menu))
if (opt_mode == OPT_ALL && !menu_is_visible(menu))
row[COL_COLOR] = g_strdup("DarkGray");
else if (opt_mode == OPT_PROMPT &&
menu_has_prompt(menu) && !menu_is_visible(menu))
row[COL_COLOR] = g_strdup("DarkGray");
else
row[COL_COLOR] = g_strdup("Black");
......@@ -1222,6 +1114,7 @@ static gchar **fill_row(struct menu *menu)
row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
if (sym_is_choice(sym))
break;
/* fall through */
case S_TRISTATE:
val = sym_get_tristate_value(sym);
switch (val) {
......@@ -1360,7 +1253,6 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
gboolean valid;
GtkTreeIter *sibling;
struct symbol *sym;
struct property *prop;
struct menu *menu1, *menu2;
if (src == &rootmenu)
......@@ -1369,7 +1261,6 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
valid = gtk_tree_model_iter_children(model2, child2, dst);
for (child1 = src->list; child1; child1 = child1->next) {
prop = child1->prompt;
sym = child1->sym;
reparse:
......@@ -1386,16 +1277,20 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
menu2 ? menu_get_prompt(menu2) : "nil");
#endif
if (!menu_is_visible(child1) && !show_all) { // remove node
if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
(opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
(opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
/* remove node */
if (gtktree_iter_find_node(dst, menu1) != NULL) {
memcpy(&tmp, child2, sizeof(GtkTreeIter));
valid = gtk_tree_model_iter_next(model2,
child2);
gtk_tree_store_remove(tree2, &tmp);
if (!valid)
return; // next parent
return; /* next parent */
else
goto reparse; // next child
goto reparse; /* next child */
} else
continue;
}
......@@ -1464,17 +1359,19 @@ static void display_tree(struct menu *menu)
&& (tree == tree2))
continue;
if (menu_is_visible(child) || show_all)
if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
(opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
(opt_mode == OPT_ALL && menu_get_prompt(child)))
place_node(child, fill_row(child));
#ifdef DEBUG
printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
dbg_print_ptype(ptype);
printf("%s", prop_get_type_name(ptype));
printf(" | ");
if (sym) {
dbg_print_stype(sym->type);
printf("%s", sym_type_name(sym->type));
printf(" | ");
dbg_print_flags(sym->flags);
printf("%s", dbg_sym_flags(sym->flags));
printf("\n");
} else
printf("\n");
......@@ -1483,9 +1380,15 @@ static void display_tree(struct menu *menu)
&& (tree == tree2))
continue;
/*
if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
|| (view_mode == FULL_VIEW)
|| (view_mode == SPLIT_VIEW))*/
/* Change paned position if the view is not in 'split mode' */
if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {
gtk_paned_set_position(GTK_PANED(hpaned), 0);
}
if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
|| (view_mode == FULL_VIEW)
|| (view_mode == SPLIT_VIEW)) {
......@@ -1544,10 +1447,6 @@ int main(int ac, char *av[])
char *env;
gchar *glade_file;
#ifndef LKC_DIRECT_LINK
kconfig_load();
#endif
bindtextdomain(PACKAGE, LOCALEDIR);
bind_textdomain_codeset(PACKAGE, "UTF-8");
textdomain(PACKAGE);
......@@ -1569,21 +1468,18 @@ int main(int ac, char *av[])
else
glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
/* Load the interface and connect signals */
init_main_window(glade_file);
init_tree_model();
init_left_tree();
init_right_tree();
/* Conf stuffs */
if (ac > 1 && av[1][0] == '-') {
switch (av[1][1]) {
case 'a':
//showAll = 1;
break;
case 's':
conf_set_message_callback(NULL);
break;
case 'h':
case '?':
printf("%s <config>\n", av[0]);
printf("%s [-s] <config>\n", av[0]);
exit(0);
}
name = av[2];
......@@ -1594,6 +1490,12 @@ int main(int ac, char *av[])
fixup_rootmenu(&rootmenu);
conf_read(NULL);
/* Load the interface and connect signals */
init_main_window(glade_file);
init_tree_model();
init_left_tree();
init_right_tree();
switch (view_mode) {
case SINGLE_VIEW:
display_tree_part();
......
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="visible">True</property>
<property name="title" translatable="yes">Gtk Configurator</property>
<property name="title" translatable="yes">Gtk Kernel Configurator</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
......@@ -190,26 +189,40 @@
</child>
<child>
<widget class="GtkCheckMenuItem" id="show_all_options1">
<widget class="GtkRadioMenuItem" id="set_option_mode1">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Show normal options</property>
<property name="label" translatable="yes">Show normal options</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="activate" handler="on_set_option_mode1_activate"/>
</widget>
</child>
<child>
<widget class="GtkRadioMenuItem" id="set_option_mode2">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Show all options</property>
<property name="label" translatable="yes">Show all _options</property>
<property name="use_underline">True</property>
<property name="active">False</property>
<signal name="activate" handler="on_show_all_options1_activate"/>
<property name="group">set_option_mode1</property>
<signal name="activate" handler="on_set_option_mode2_activate"/>
</widget>
</child>
<child>
<widget class="GtkCheckMenuItem" id="show_debug_info1">
<widget class="GtkRadioMenuItem" id="set_option_mode3">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Show masked options</property>
<property name="label" translatable="yes">Show _debug info</property>
<property name="tooltip" translatable="yes">Show all options with prompts</property>
<property name="label" translatable="yes">Show all prompt options</property>
<property name="use_underline">True</property>
<property name="active">False</property>
<signal name="activate" handler="on_show_debug_info1_activate"/>
<property name="group">set_option_mode1</property>
<signal name="activate" handler="on_set_option_mode3_activate"/>
</widget>
</child>
</widget>
</child>
</widget>
......
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include "lkc.h"
#define P(name,type,arg) type (*name ## _p) arg
#include "lkc_proto.h"
#undef P
void kconfig_load(void)
{
void *handle;
char *error;
handle = dlopen("./libkconfig.so", RTLD_LAZY);
if (!handle) {
handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
}
#define P(name,type,arg) \
{ \
name ## _p = dlsym(handle, #name); \
if ((error = dlerror())) { \
fprintf(stderr, "%s\n", error); \
exit(1); \
} \
}
#include "lkc_proto.h"
#undef P
}
......@@ -7,7 +7,6 @@
#include <stdlib.h>
#include <string.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
static char *escape(const char* text, char *bf, int len)
......@@ -63,11 +62,11 @@ next:
struct file_line {
struct file_line *next;
char* file;
int lineno;
const char *file;
int lineno;
};
static struct file_line *file_line__new(char *file, int lineno)
static struct file_line *file_line__new(const char *file, int lineno)
{
struct file_line *self = malloc(sizeof(*self));
......@@ -90,7 +89,8 @@ struct message {
static struct message *message__list;
static struct message *message__new(const char *msg, char *option, char *file, int lineno)
static struct message *message__new(const char *msg, char *option,
const char *file, int lineno)
{
struct message *self = malloc(sizeof(*self));
......@@ -130,7 +130,8 @@ static struct message *mesage__find(const char *msg)
return m;
}
static int message__add_file_line(struct message *self, char *file, int lineno)
static int message__add_file_line(struct message *self, const char *file,
int lineno)
{
int rc = -1;
struct file_line *fl = file_line__new(file, lineno);
......@@ -145,7 +146,8 @@ out:
return rc;
}
static int message__add(const char *msg, char *option, char *file, int lineno)
static int message__add(const char *msg, char *option, const char *file,
int lineno)
{
int rc = 0;
char bf[16384];
......
#ifndef LIST_H
#define LIST_H
/*
* Copied from include/linux/...
*/
#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *_new,
struct list_head *prev,
struct list_head *next)
{
next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *_new, struct list_head *head)
{
__list_add(_new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
#define LIST_POISON1 ((void *) 0x00100100)
#define LIST_POISON2 ((void *) 0x00200200)
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = (struct list_head*)LIST_POISON1;
entry->prev = (struct list_head*)LIST_POISON2;
}
#endif
......@@ -14,29 +14,35 @@
static inline const char *gettext(const char *txt) { return txt; }
static inline void textdomain(const char *domainname) {}
static inline void bindtextdomain(const char *name, const char *dir) {}
static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef LKC_DIRECT_LINK
#define P(name,type,arg) extern type name arg
#else
#include "lkc_defs.h"
#define P(name,type,arg) extern type (*name ## _p) arg
#endif
#include "lkc_proto.h"
#undef P
#define SRCTREE "srctree"
#define PACKAGE "WRS-sw"
#ifndef PACKAGE
#define PACKAGE "linux"
#endif
#define LOCALEDIR "/usr/share/locale"
#define _(text) gettext(text)
#define N_(text) (text)
#ifndef CONFIG_
#define CONFIG_ "CONFIG_"
#endif
static inline const char *CONFIG_prefix(void)
{
return getenv( "CONFIG_" ) ?: CONFIG_;
}
#undef CONFIG_
#define CONFIG_ CONFIG_prefix()
#define TF_COMMAND 0x0001
#define TF_PARAM 0x0002
......@@ -53,6 +59,7 @@ enum conf_def_mode {
#define T_OPT_MODULES 1
#define T_OPT_DEFCONFIG_LIST 2
#define T_OPT_ENV 3
#define T_OPT_ALLNOCONFIG_Y 4
struct kconf_id {
int name;
......@@ -61,16 +68,13 @@ struct kconf_id {
enum symbol_type stype;
};
int zconfparse(void);
void zconfdump(FILE *out);
extern int zconfdebug;
void zconf_starthelp(void);
FILE *zconf_fopen(const char *name);
void zconf_initscan(const char *name);
void zconf_nextfile(const char *name);
int zconf_lineno(void);
char *zconf_curname(void);
const char *zconf_curname(void);
/* confdata.c */
const char *conf_get_configname(void);
......@@ -78,20 +82,27 @@ const char *conf_get_autoconfig_name(void);
char *conf_get_default_confname(void);
void sym_set_change_count(int count);
void sym_add_change_count(int count);
void conf_set_all_new_symbols(enum conf_def_mode mode);
bool conf_set_all_new_symbols(enum conf_def_mode mode);
void set_all_choice_values(struct symbol *csym);
/* kconfig_load.c */
void kconfig_load(void);
/* confdata.c and expr.c */
static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
{
assert(len != 0);
if (fwrite(str, len, count, out) != count)
fprintf(stderr, "Error in writing or end of file.\n");
}
/* menu.c */
void menu_init(void);
void _menu_init(void);
void menu_warn(struct menu *menu, const char *fmt, ...);
struct menu *menu_add_menu(void);
void menu_end_menu(void);
void menu_add_entry(struct symbol *sym);
void menu_end_entry(void);
void menu_add_dep(struct expr *dep);
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
void menu_add_visibility(struct expr *dep);
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
......@@ -102,13 +113,19 @@ void menu_set_type(int type);
/* util.c */
struct file *file_lookup(const char *name);
int file_write_dep(const char *name);
void *xmalloc(size_t size);
void *xcalloc(size_t nmemb, size_t size);
struct gstr {
size_t len;
char *s;
/*
* when max_width is not zero long lines in string s (if any) get
* wrapped not to exceed the max_width value
*/
int max_width;
};
struct gstr str_new(void);
struct gstr str_assign(const char *s);
void str_free(struct gstr *gs);
void str_append(struct gstr *gs, const char *s);
void str_printf(struct gstr *gs, const char *fmt, ...);
......@@ -119,8 +136,8 @@ extern struct expr *sym_env_list;
void sym_init(void);
void sym_clear_all_valid(void);
void sym_set_all_changed(void);
void sym_set_changed(struct symbol *sym);
struct symbol *sym_choice_default(struct symbol *sym);
const char *sym_get_string_default(struct symbol *sym);
struct symbol *sym_check_deps(struct symbol *sym);
struct property *prop_alloc(enum prop_type type, struct symbol *sym);
struct symbol *prop_get_symbol(struct property *prop);
......
#include <stdarg.h>
/* confdata.c */
P(conf_parse,void,(const char *name));
P(conf_read,int,(const char *name));
P(conf_read_simple,int,(const char *name, int));
P(conf_write,int,(const char *name));
P(conf_write_autoconf,int,(void));
P(conf_get_changed,bool,(void));
P(conf_set_changed_callback, void,(void (*fn)(void)));
void conf_parse(const char *name);
int conf_read(const char *name);
int conf_read_simple(const char *name, int);
int conf_write_defconfig(const char *name);
int conf_write(const char *name);
int conf_write_autoconf(void);
bool conf_get_changed(void);
void conf_set_changed_callback(void (*fn)(void));
void conf_set_message_callback(void (*fn)(const char *fmt, va_list ap));
/* menu.c */
P(rootmenu,struct menu,);
extern struct menu rootmenu;
P(menu_is_visible,bool,(struct menu *menu));
P(menu_get_prompt,const char *,(struct menu *menu));
P(menu_get_root_menu,struct menu *,(struct menu *menu));
P(menu_get_parent_menu,struct menu *,(struct menu *menu));
P(menu_has_help,bool,(struct menu *menu));
P(menu_get_help,const char *,(struct menu *menu));
P(get_symbol_str,void,(struct gstr *r, struct symbol *sym));
P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
bool menu_is_empty(struct menu *menu);
bool menu_is_visible(struct menu *menu);
bool menu_has_prompt(struct menu *menu);
const char * menu_get_prompt(struct menu *menu);
struct menu * menu_get_root_menu(struct menu *menu);
struct menu * menu_get_parent_menu(struct menu *menu);
bool menu_has_help(struct menu *menu);
const char * menu_get_help(struct menu *menu);
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
void menu_get_ext_help(struct menu *menu, struct gstr *help);
/* symbol.c */
P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
P(sym_lookup,struct symbol *,(const char *name, int flags));
P(sym_find,struct symbol *,(const char *name));
P(sym_re_search,struct symbol **,(const char *pattern));
P(sym_type_name,const char *,(enum symbol_type type));
P(sym_calc_value,void,(struct symbol *sym));
P(sym_get_type,enum symbol_type,(struct symbol *sym));
P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
P(sym_is_changable,bool,(struct symbol *sym));
P(sym_get_choice_prop,struct property *,(struct symbol *sym));
P(sym_get_default_prop,struct property *,(struct symbol *sym));
P(sym_get_string_value,const char *,(struct symbol *sym));
struct symbol * sym_lookup(const char *name, int flags);
struct symbol * sym_find(const char *name);
const char * sym_expand_string_value(const char *in);
const char * sym_escape_string_value(const char *in);
struct symbol ** sym_re_search(const char *pattern);
const char * sym_type_name(enum symbol_type type);
void sym_calc_value(struct symbol *sym);
enum symbol_type sym_get_type(struct symbol *sym);
bool sym_tristate_within_range(struct symbol *sym,tristate tri);
bool sym_set_tristate_value(struct symbol *sym,tristate tri);
tristate sym_toggle_tristate_value(struct symbol *sym);
bool sym_string_valid(struct symbol *sym, const char *newval);
bool sym_string_within_range(struct symbol *sym, const char *str);
bool sym_set_string_value(struct symbol *sym, const char *newval);
bool sym_is_changable(struct symbol *sym);
struct property * sym_get_choice_prop(struct symbol *sym);
const char * sym_get_string_value(struct symbol *sym);
P(prop_get_type_name,const char *,(enum prop_type type));
const char * prop_get_type_name(enum prop_type type);
/* expr.c */
P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken));
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
......@@ -4,7 +4,9 @@
# What library to link
ldflags()
{
for ext in so a dylib ; do
pkg-config --libs ncursesw 2>/dev/null && exit
pkg-config --libs ncurses 2>/dev/null && exit
for ext in so a dll.a dylib ; do
for lib in ncursesw ncurses curses ; do
$cc -print-file-name=lib${lib}.${ext} | grep -q /
if [ $? -eq 0 ]; then
......@@ -19,10 +21,17 @@ ldflags()
# Where is ncurses.h?
ccflags()
{
if [ -f /usr/include/ncurses/ncurses.h ]; then
if pkg-config --cflags ncursesw 2>/dev/null; then
echo '-DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1'
elif pkg-config --cflags ncurses 2>/dev/null; then
echo '-DCURSES_LOC="<ncurses.h>"'
elif [ -f /usr/include/ncursesw/curses.h ]; then
echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"'
echo ' -DNCURSES_WIDECHAR=1'
elif [ -f /usr/include/ncurses/ncurses.h ]; then
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
elif [ -f /usr/include/ncurses/curses.h ]; then
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
echo '-I/usr/include/ncurses -DCURSES_LOC="<curses.h>"'
elif [ -f /usr/include/ncurses.h ]; then
echo '-DCURSES_LOC="<ncurses.h>"'
else
......@@ -36,7 +45,7 @@ trap "rm -f $tmp" 0 1 2 3 15
# Check if we can link to ncurses
check() {
$cc -xc - -o $tmp 2>/dev/null <<'EOF'
$cc -x c - -o $tmp 2>/dev/null <<'EOF'
#include CURSES_LOC
main() {}
EOF
......
......@@ -31,6 +31,10 @@ static int list_width, check_x, item_x;
static void print_item(WINDOW * win, int choice, int selected)
{
int i;
char *list_item = malloc(list_width + 1);
strncpy(list_item, item_str(), list_width - item_x);
list_item[list_width - item_x] = '\0';
/* Clear 'residue' of last item */
wattrset(win, dlg.menubox.atr);
......@@ -45,13 +49,14 @@ static void print_item(WINDOW * win, int choice, int selected)
wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
mvwaddch(win, choice, item_x, item_str()[0]);
mvwaddch(win, choice, item_x, list_item[0]);
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
waddstr(win, (char *)item_str() + 1);
waddstr(win, list_item + 1);
if (selected) {
wmove(win, choice, check_x + 1);
wrefresh(win);
}
free(list_item);
}
/*
......@@ -127,16 +132,16 @@ int dialog_checklist(const char *title, const char *prompt, int height,
}
do_resize:
if (getmaxy(stdscr) < (height + 6))
if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) < (width + 6))
if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL;
max_choice = MIN(list_height, item_count());
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
x = (getmaxx(stdscr) - width) / 2;
y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width);
......@@ -163,18 +168,19 @@ do_resize:
/* create new window for the list */
list = subwin(dialog, list_height, list_width, y + box_y + 1,
x + box_x + 1);
x + box_x + 1);
keypad(list, TRUE);
/* draw a box around the list items */
draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
dlg.menubox_border.atr, dlg.menubox.atr);
dlg.menubox_border.atr, dlg.menubox.atr);
/* Find length of longest item in order to center checklist */
check_x = 0;
item_foreach()
check_x = MAX(check_x, strlen(item_str()) + 4);
check_x = MIN(check_x, list_width);
check_x = (list_width - check_x) / 2;
item_x = check_x + 4;
......@@ -204,12 +210,7 @@ do_resize:
for (i = 0; i < max_choice; i++) {
item_set(i + scroll);
/*
* uClibc's function toupper asserts for items outside <0,255>
* Let's ignore these keys, they're not in strings anyway.
*/
if ((key >= 0) && (key <= 255) && (toupper(key) == toupper(item_str()[0])))
if (toupper(key) == toupper(item_str()[0]))
break;
}
......
......@@ -106,8 +106,14 @@ struct dialog_color {
int hl; /* highlight this item */
};
struct subtitle_list {
struct subtitle_list *next;
const char *text;
};
struct dialog_info {
const char *backtitle;
struct subtitle_list *subtitles;
struct dialog_color screen;
struct dialog_color shadow;
struct dialog_color dialog;
......@@ -144,6 +150,7 @@ struct dialog_info {
*/
extern struct dialog_info dlg;
extern char dialog_input_result[];
extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */
/*
* Function prototypes
......@@ -163,7 +170,7 @@ char item_tag(void);
/* item list manipulation for lxdialog use */
#define MAXITEMSTR 200
struct dialog_item {
char str[MAXITEMSTR]; /* promtp displayed */
char str[MAXITEMSTR]; /* prompt displayed */
char tag;
void *data; /* pointer to menu item - used by menubox+checklist */
int selected; /* Set to 1 by dialog_*() function if selected. */
......@@ -193,8 +200,23 @@ int item_is_tag(char tag);
int on_key_esc(WINDOW *win);
int on_key_resize(void);
/* minimum (re)size values */
#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */
#define CHECKLIST_WIDTH_MIN 6
#define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */
#define INPUTBOX_WIDTH_MIN 2
#define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */
#define MENUBOX_WIDTH_MIN 65
#define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */
#define TEXTBOX_WIDTH_MIN 8
#define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */
#define YESNO_WIDTH_MIN 4
#define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */
#define WINDOW_WIDTH_MIN 80
int init_dialog(const char *backtitle);
void set_dialog_backtitle(const char *backtitle);
void set_dialog_subtitles(struct subtitle_list *subtitles);
void end_dialog(int x, int y);
void attr_clear(WINDOW * win, int height, int width, chtype attr);
void dialog_clear(void);
......@@ -209,12 +231,17 @@ int first_alpha(const char *string, const char *exempt);
int dialog_yesno(const char *title, const char *prompt, int height, int width);
int dialog_msgbox(const char *title, const char *prompt, int height,
int width, int pause);
int dialog_textbox(const char *title, const char *file, int height, int width);
typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
*_data);
int dialog_textbox(const char *title, char *tbuf, int initial_height,
int initial_width, int *keys, int *_vscroll, int *_hscroll,
update_text_fn update_text, void *data);
int dialog_menu(const char *title, const char *prompt,
const void *selected, int *s_scroll);
int dialog_checklist(const char *title, const char *prompt, int height,
int width, int list_height);
extern char dialog_input_result[];
int dialog_inputbox(const char *title, const char *prompt, int height,
int width, const char *init);
......
......@@ -42,10 +42,11 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
* Display a dialog box for inputing a string
*/
int dialog_inputbox(const char *title, const char *prompt, int height, int width,
const char *init)
const char *init)
{
int i, x, y, box_y, box_x, box_width;
int input_x = 0, scroll = 0, key = 0, button = -1;
int input_x = 0, key = 0, button = -1;
int show_x, len, pos;
char *instr = dialog_input_result;
WINDOW *dialog;
......@@ -55,14 +56,14 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
strcpy(instr, init);
do_resize:
if (getmaxy(stdscr) <= (height - 2))
if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) <= (width - 2))
if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
x = (getmaxx(stdscr) - width) / 2;
y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width);
......@@ -97,14 +98,17 @@ do_resize:
wmove(dialog, box_y, box_x);
wattrset(dialog, dlg.inputbox.atr);
input_x = strlen(instr);
len = strlen(instr);
pos = len;
if (input_x >= box_width) {
scroll = input_x - box_width + 1;
if (len >= box_width) {
show_x = len - box_width + 1;
input_x = box_width - 1;
for (i = 0; i < box_width - 1; i++)
waddch(dialog, instr[scroll + i]);
waddch(dialog, instr[show_x + i]);
} else {
show_x = 0;
input_x = len;
waddstr(dialog, instr);
}
......@@ -121,45 +125,104 @@ do_resize:
case KEY_UP:
case KEY_DOWN:
break;
case KEY_LEFT:
continue;
case KEY_RIGHT:
continue;
case KEY_BACKSPACE:
case 127:
if (input_x || scroll) {
if (pos) {
wattrset(dialog, dlg.inputbox.atr);
if (!input_x) {
scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1);
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++)
waddch(dialog,
instr[scroll + input_x + i] ?
instr[scroll + input_x + i] : ' ');
input_x = strlen(instr) - scroll;
if (input_x == 0) {
show_x--;
} else
input_x--;
instr[scroll + input_x] = '\0';
mvwaddch(dialog, box_y, input_x + box_x, ' ');
if (pos < len) {
for (i = pos - 1; i < len; i++) {
instr[i] = instr[i+1];
}
}
pos--;
len--;
instr[len] = '\0';
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
wrefresh(dialog);
}
continue;
case KEY_LEFT:
if (pos > 0) {
if (input_x > 0) {
wmove(dialog, box_y, --input_x + box_x);
} else if (input_x == 0) {
show_x--;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, box_x);
}
pos--;
}
continue;
case KEY_RIGHT:
if (pos < len) {
if (input_x < box_width - 1) {
wmove(dialog, box_y, ++input_x + box_x);
} else if (input_x == box_width - 1) {
show_x++;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
}
pos++;
}
continue;
default:
if (key < 0x100 && isprint(key)) {
if (scroll + input_x < MAX_LEN) {
if (len < MAX_LEN) {
wattrset(dialog, dlg.inputbox.atr);
instr[scroll + input_x] = key;
instr[scroll + input_x + 1] = '\0';
if (pos < len) {
for (i = len; i > pos; i--)
instr[i] = instr[i-1];
instr[pos] = key;
} else {
instr[len] = key;
}
pos++;
len++;
instr[len] = '\0';
if (input_x == box_width - 1) {
scroll++;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width - 1; i++)
waddch(dialog, instr [scroll + i]);
show_x++;
} else {
wmove(dialog, box_y, input_x++ + box_x);
waddch(dialog, key);
input_x++;
}
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
wrefresh(dialog);
} else
flash(); /* Alarm user about overflow */
......@@ -180,7 +243,7 @@ do_resize:
case KEY_LEFT:
switch (button) {
case -1:
button = 1; /* Indicates "Cancel" button is selected */
button = 1; /* Indicates "Help" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 0:
......@@ -204,7 +267,7 @@ do_resize:
print_buttons(dialog, height, width, 0);
break;
case 0:
button = 1; /* Indicates "Cancel" button is selected */
button = 1; /* Indicates "Help" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 1:
......
......@@ -26,7 +26,7 @@
*
* *) A bugfix for the Page-Down problem
*
* *) Formerly when I used Page Down and Page Up, the cursor would be set
* *) Formerly when I used Page Down and Page Up, the cursor would be set
* to the first position in the menu box. Now lxdialog is a bit
* smarter and works more like other menu systems (just have a look at
* it).
......@@ -64,7 +64,7 @@ static int menu_width, item_x;
* Print menu item
*/
static void do_print_item(WINDOW * win, const char *item, int line_y,
int selected, int hotkey)
int selected, int hotkey)
{
int j;
char *menu_item = malloc(menu_width + 1);
......@@ -154,12 +154,14 @@ static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
*/
static void print_buttons(WINDOW * win, int height, int width, int selected)
{
int x = width / 2 - 16;
int x = width / 2 - 28;
int y = height - 2;
print_button(win, gettext("Select"), y, x, selected == 0);
print_button(win, gettext(" Exit "), y, x + 12, selected == 1);
print_button(win, gettext(" Help "), y, x + 24, selected == 2);
print_button(win, gettext(" Save "), y, x + 36, selected == 3);
print_button(win, gettext(" Load "), y, x + 48, selected == 4);
wmove(win, y, x + 1 + 12 * selected);
wrefresh(win);
......@@ -180,7 +182,7 @@ static void do_scroll(WINDOW *win, int *scroll, int n)
* Display a menu for choosing among a number of options
*/
int dialog_menu(const char *title, const char *prompt,
const void *selected, int *s_scroll)
const void *selected, int *s_scroll)
{
int i, j, x, y, box_x, box_y;
int height, width, menu_height;
......@@ -191,7 +193,7 @@ int dialog_menu(const char *title, const char *prompt,
do_resize:
height = getmaxy(stdscr);
width = getmaxx(stdscr);
if (height < 15 || width < 65)
if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN)
return -ERRDISPLAYTOOSMALL;
height -= 4;
......@@ -201,8 +203,8 @@ do_resize:
max_choice = MIN(menu_height, item_count());
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
x = (getmaxx(stdscr) - width) / 2;
y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width);
......@@ -301,10 +303,11 @@ do_resize:
}
}
if (i < max_choice ||
key == KEY_UP || key == KEY_DOWN ||
key == '-' || key == '+' ||
key == KEY_PPAGE || key == KEY_NPAGE) {
if (item_count() != 0 &&
(i < max_choice ||
key == KEY_UP || key == KEY_DOWN ||
key == '-' || key == '+' ||
key == KEY_PPAGE || key == KEY_NPAGE)) {
/* Remove highligt of current item */
print_item(scroll + choice, choice, FALSE);
......@@ -372,7 +375,7 @@ do_resize:
case TAB:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 2 : (button > 2 ? 0 : button);
? 4 : (button > 4 ? 0 : button);
print_buttons(dialog, height, width, button);
wrefresh(menu);
......@@ -383,6 +386,10 @@ do_resize:
case 'n':
case 'm':
case '/':
case 'h':
case '?':
case 'z':
case '\n':
/* save scroll info */
*s_scroll = scroll;
delwin(menu);
......@@ -390,30 +397,26 @@ do_resize:
item_set(scroll + choice);
item_set_selected(1);
switch (key) {
case 'h':
case '?':
return 2;
case 's':
return 3;
case 'y':
return 3;
return 5;
case 'n':
return 4;
return 6;
case 'm':
return 5;
return 7;
case ' ':
return 6;
return 8;
case '/':
return 7;
return 9;
case 'z':
return 10;
case '\n':
return button;
}
return 0;
case 'h':
case '?':
button = 2;
case '\n':
*s_scroll = scroll;
delwin(menu);
delwin(dialog);
item_set(scroll + choice);
item_set_selected(1);
return button;
case 'e':
case 'x':
key = KEY_ESC;
......
......@@ -22,23 +22,25 @@
#include "dialog.h"
static void back_lines(int n);
static void print_page(WINDOW * win, int height, int width);
static void print_line(WINDOW * win, int row, int width);
static void print_page(WINDOW *win, int height, int width, update_text_fn
update_text, void *data);
static void print_line(WINDOW *win, int row, int width);
static char *get_line(void);
static void print_position(WINDOW * win);
static int hscroll;
static int begin_reached, end_reached, page_length;
static const char *buf;
static const char *page;
static char *buf;
static char *page;
/*
* refresh window content
*/
static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
int cur_y, int cur_x)
int cur_y, int cur_x, update_text_fn update_text,
void *data)
{
print_page(box, boxh, boxw);
print_page(box, boxh, boxw, update_text, data);
print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
......@@ -47,14 +49,18 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
/*
* Display text from a file in a dialog box.
*
* keys is a null-terminated array
* update_text() may not add or remove any '\n' or '\0' in tbuf
*/
int dialog_textbox(const char *title, const char *tbuf,
int initial_height, int initial_width)
int dialog_textbox(const char *title, char *tbuf, int initial_height,
int initial_width, int *keys, int *_vscroll, int *_hscroll,
update_text_fn update_text, void *data)
{
int i, x, y, cur_x, cur_y, key = 0;
int height, width, boxh, boxw;
int passed_end;
WINDOW *dialog, *box;
bool done = false;
begin_reached = 1;
end_reached = 0;
......@@ -63,9 +69,18 @@ int dialog_textbox(const char *title, const char *tbuf,
buf = tbuf;
page = buf; /* page is pointer to start of page to be displayed */
if (_vscroll && *_vscroll) {
begin_reached = 0;
for (i = 0; i < *_vscroll; i++)
get_line();
}
if (_hscroll)
hscroll = *_hscroll;
do_resize:
getmaxyx(stdscr, height, width);
if (height < 8 || width < 8)
if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN)
return -ERRDISPLAYTOOSMALL;
if (initial_height != 0)
height = initial_height;
......@@ -83,8 +98,8 @@ do_resize:
width = 0;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
x = (getmaxx(stdscr) - width) / 2;
y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width);
......@@ -120,25 +135,28 @@ do_resize:
/* Print first page of text */
attr_clear(box, boxh, boxw, dlg.dialog.atr);
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
data);
while ((key != KEY_ESC) && (key != '\n')) {
while (!done) {
key = wgetch(dialog);
switch (key) {
case 'E': /* Exit */
case 'e':
case 'X':
case 'x':
delwin(box);
delwin(dialog);
return 0;
case 'q':
case '\n':
done = true;
break;
case 'g': /* First page */
case KEY_HOME:
if (!begin_reached) {
begin_reached = 1;
page = buf;
refresh_text_box(dialog, box, boxh, boxw,
cur_y, cur_x);
cur_y, cur_x, update_text,
data);
}
break;
case 'G': /* Last page */
......@@ -148,78 +166,48 @@ do_resize:
/* point to last char in buf */
page = buf + strlen(buf);
back_lines(boxh);
refresh_text_box(dialog, box, boxh, boxw,
cur_y, cur_x);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case 'K': /* Previous line */
case 'k':
case KEY_UP:
if (!begin_reached) {
back_lines(page_length + 1);
/* We don't call print_page() here but use
* scrolling to ensure faster screen update.
* However, 'end_reached' and 'page_length'
* should still be updated, and 'page' should
* point to start of next page. This is done
* by calling get_line() in the following
* 'for' loop. */
scrollok(box, TRUE);
wscrl(box, -1); /* Scroll box region down one line */
scrollok(box, FALSE);
page_length = 0;
passed_end = 0;
for (i = 0; i < boxh; i++) {
if (!i) {
/* print first line of page */
print_line(box, 0, boxw);
wnoutrefresh(box);
} else
/* Called to update 'end_reached' and 'page' */
get_line();
if (!passed_end)
page_length++;
if (end_reached && !passed_end)
passed_end = 1;
}
if (begin_reached)
break;
print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
}
back_lines(page_length + 1);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case 'B': /* Previous page */
case 'b':
case 'u':
case KEY_PPAGE:
if (begin_reached)
break;
back_lines(page_length + boxh);
refresh_text_box(dialog, box, boxh, boxw,
cur_y, cur_x);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case 'J': /* Next line */
case 'j':
case KEY_DOWN:
if (!end_reached) {
begin_reached = 0;
scrollok(box, TRUE);
scroll(box); /* Scroll box region up one line */
scrollok(box, FALSE);
print_line(box, boxh - 1, boxw);
wnoutrefresh(box);
print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
}
if (end_reached)
break;
back_lines(page_length - 1);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case KEY_NPAGE: /* Next page */
case ' ':
case 'd':
if (end_reached)
break;
begin_reached = 0;
refresh_text_box(dialog, box, boxh, boxw,
cur_y, cur_x);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case '0': /* Beginning of line */
case 'H': /* Scroll left */
......@@ -234,8 +222,8 @@ do_resize:
hscroll--;
/* Reprint current page to scroll horizontally */
back_lines(page_length);
refresh_text_box(dialog, box, boxh, boxw,
cur_y, cur_x);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case 'L': /* Scroll right */
case 'l':
......@@ -245,11 +233,12 @@ do_resize:
hscroll++;
/* Reprint current page to scroll horizontally */
back_lines(page_length);
refresh_text_box(dialog, box, boxh, boxw,
cur_y, cur_x);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case KEY_ESC:
key = on_key_esc(dialog);
if (on_key_esc(dialog) == KEY_ESC)
done = true;
break;
case KEY_RESIZE:
back_lines(height);
......@@ -257,11 +246,31 @@ do_resize:
delwin(dialog);
on_key_resize();
goto do_resize;
default:
for (i = 0; keys[i]; i++) {
if (key == keys[i]) {
done = true;
break;
}
}
}
}
delwin(box);
delwin(dialog);
return key; /* ESC pressed */
if (_vscroll) {
const char *s;
s = buf;
*_vscroll = 0;
back_lines(page_length);
while (s < page && (s = strchr(s, '\n'))) {
(*_vscroll)++;
s++;
}
}
if (_hscroll)
*_hscroll = hscroll;
return key;
}
/*
......@@ -298,12 +307,23 @@ static void back_lines(int n)
}
/*
* Print a new page of text. Called by dialog_textbox().
* Print a new page of text.
*/
static void print_page(WINDOW * win, int height, int width)
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);
......@@ -316,11 +336,10 @@ static void print_page(WINDOW * win, int height, int width)
}
/*
* Print a new line of text. Called by dialog_textbox() and print_page().
* Print a new line of text.
*/
static void print_line(WINDOW * win, int row, int width)
{
int y, x;
char *line;
line = get_line();
......@@ -329,10 +348,10 @@ static void print_line(WINDOW * win, int row, int width)
waddch(win, ' ');
waddnstr(win, line, MIN(strlen(line), width - 2));
getyx(win, y, x);
/* Clear 'residue' of previous line */
#if OLD_NCURSES
{
int x = getcurx(win);
int i;
for (i = 0; i < width - x; i++)
waddch(win, ' ');
......@@ -355,10 +374,8 @@ static char *get_line(void)
end_reached = 0;
while (*page != '\n') {
if (*page == '\0') {
if (!end_reached) {
end_reached = 1;
break;
}
end_reached = 1;
break;
} else if (i < MAX_LEN)
line[i++] = *(page++);
else {
......@@ -371,7 +388,7 @@ static char *get_line(void)
if (i <= MAX_LEN)
line[i] = '\0';
if (!end_reached)
page++; /* move pass '\n' */
page++; /* move past '\n' */
return line;
}
......
......@@ -23,6 +23,9 @@
#include "dialog.h"
/* Needed in signal handler in mconf.c */
int saved_x, saved_y;
struct dialog_info dlg;
static void set_mono_theme(void)
......@@ -251,15 +254,56 @@ void attr_clear(WINDOW * win, int height, int width, chtype attr)
void dialog_clear(void)
{
attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
int lines, columns;
lines = getmaxy(stdscr);
columns = getmaxx(stdscr);
attr_clear(stdscr, lines, columns, dlg.screen.atr);
/* Display background title if it exists ... - SLH */
if (dlg.backtitle != NULL) {
int i;
int i, len = 0, skip = 0;
struct subtitle_list *pos;
wattrset(stdscr, dlg.screen.atr);
mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
/* 3 is for the arrow and spaces */
len += strlen(pos->text) + 3;
}
wmove(stdscr, 1, 1);
for (i = 1; i < COLS - 1; i++)
if (len > columns - 2) {
const char *ellipsis = "[...] ";
waddstr(stdscr, ellipsis);
skip = len - (columns - 2 - strlen(ellipsis));
}
for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
if (skip == 0)
waddch(stdscr, ACS_RARROW);
else
skip--;
if (skip == 0)
waddch(stdscr, ' ');
else
skip--;
if (skip < strlen(pos->text)) {
waddstr(stdscr, pos->text + skip);
skip = 0;
} else
skip -= strlen(pos->text);
if (skip == 0)
waddch(stdscr, ' ');
else
skip--;
}
for (i = len + 1; i < columns - 1; i++)
waddch(stdscr, ACS_HLINE);
}
wnoutrefresh(stdscr);
......@@ -273,8 +317,12 @@ int init_dialog(const char *backtitle)
int height, width;
initscr(); /* Init curses */
/* Get current cursor position for signal handler in mconf.c */
getyx(stdscr, saved_y, saved_x);
getmaxyx(stdscr, height, width);
if (height < 19 || width < 80) {
if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) {
endwin();
return -ERRDISPLAYTOOSMALL;
}
......@@ -295,6 +343,11 @@ void set_dialog_backtitle(const char *backtitle)
dlg.backtitle = backtitle;
}
void set_dialog_subtitles(struct subtitle_list *subtitles)
{
dlg.subtitles = subtitles;
}
/*
* End using dialog functions.
*/
......@@ -323,27 +376,19 @@ void print_title(WINDOW *dialog, const char *title, int width)
/*
* Print a string of text in a window, automatically wrap around to the
* next line if the string is too long to fit on one line. Newline
* characters '\n' are replaced by spaces. We start on a new line
* characters '\n' are propperly processed. We start on a new line
* if there is no room for at least 4 nonblanks following a double-space.
*/
void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
{
int newl, cur_x, cur_y;
int i, prompt_len, room, wlen;
char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
int prompt_len, room, wlen;
char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0;
strcpy(tempstr, prompt);
prompt_len = strlen(tempstr);
/*
* Remove newlines
*/
for (i = 0; i < prompt_len; i++) {
if (tempstr[i] == '\n')
tempstr[i] = ' ';
}
if (prompt_len <= width - x * 2) { /* If prompt is short */
wmove(win, y, (width - prompt_len) / 2);
waddstr(win, tempstr);
......@@ -353,7 +398,10 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
newl = 1;
word = tempstr;
while (word && *word) {
sp = strchr(word, ' ');
sp = strpbrk(word, "\n ");
if (sp && *sp == '\n')
newline_separator = sp;
if (sp)
*sp++ = 0;
......@@ -365,7 +413,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
if (wlen > room ||
(newl && wlen < 4 && sp
&& wlen + 1 + strlen(sp) > room
&& (!(sp2 = strchr(sp, ' '))
&& (!(sp2 = strpbrk(sp, "\n "))
|| wlen + 1 + (sp2 - sp) > room))) {
cur_y++;
cur_x = x;
......@@ -373,7 +421,15 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
wmove(win, cur_y, cur_x);
waddstr(win, word);
getyx(win, cur_y, cur_x);
cur_x++;
/* Move to the next line if the word separator was a newline */
if (newline_separator) {
cur_y++;
cur_x = x;
newline_separator = 0;
} else
cur_x++;
if (sp && *sp == ' ') {
cur_x++; /* double space */
while (*++sp == ' ') ;
......@@ -567,7 +623,7 @@ void item_make(const char *fmt, ...)
void item_add_str(const char *fmt, ...)
{
va_list ap;
size_t avail;
size_t avail;
avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
......
......@@ -45,14 +45,14 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
WINDOW *dialog;
do_resize:
if (getmaxy(stdscr) < (height + 4))
if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) < (width + 4))
if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
x = (getmaxx(stdscr) - width) / 2;
y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width);
......
......@@ -15,21 +15,19 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <locale.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
#include "lxdialog/dialog.h"
static const char mconf_readme[] = N_(
"Overview (from Linux Kernel, not WRS-sw-specific)\n"
"Overview\n"
"--------\n"
"Some kernel features may be built directly into the kernel.\n"
"Some may be made into loadable runtime modules. Some features\n"
"may be completely removed altogether. There are also certain\n"
"kernel parameters which are not really features, but must be\n"
"entered in as decimal or hexadecimal numbers or possibly text.\n"
"This interface lets you select features and parameters for the build.\n"
"Features can either be built-in, modularized, or ignored. Parameters\n"
"must be entered in as decimal or hexadecimal numbers or text.\n"
"\n"
"Menu items beginning with following braces represent features that\n"
" [ ] can be built in or removed\n"
......@@ -41,16 +39,16 @@ static const char mconf_readme[] = N_(
"\n"
"To change any of these features, highlight it with the cursor\n"
"keys and press <Y> to build it in, <M> to make it a module or\n"
"<N> to removed it. You may also press the <Space Bar> to cycle\n"
"through the available options (ie. Y->N->M->Y).\n"
"<N> to remove it. You may also press the <Space Bar> to cycle\n"
"through the available options (i.e. Y->N->M->Y).\n"
"\n"
"Some additional keyboard hints:\n"
"\n"
"Menus\n"
"----------\n"
"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
" you wish to change or submenu wish to select and press <Enter>.\n"
" Submenus are designated by \"--->\".\n"
"o Use the Up/Down arrow keys (cursor keys) to highlight the item you\n"
" wish to change or the submenu you wish to select and press <Enter>.\n"
" Submenus are designated by \"--->\", empty ones by \"----\".\n"
"\n"
" Shortcut: Press the option's highlighted letter (hotkey).\n"
" Pressing a hotkey more than once will sequence\n"
......@@ -67,13 +65,15 @@ static const char mconf_readme[] = N_(
" there is a delayed response which you may find annoying.\n"
"\n"
" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
" <Exit> and <Help>\n"
" <Exit>, <Help>, <Save>, and <Load>.\n"
"\n"
"o To get help with an item, use the cursor keys to highlight <Help>\n"
" and Press <ENTER>.\n"
" and press <ENTER>.\n"
"\n"
" Shortcut: Press <H> or <?>.\n"
"\n"
"o To toggle the display of hidden options, press <Z>.\n"
"\n"
"\n"
"Radiolists (Choice lists)\n"
"-----------\n"
......@@ -105,35 +105,33 @@ static const char mconf_readme[] = N_(
"Text Box (Help Window)\n"
"--------\n"
"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
" who are familiar with less and lynx.\n"
" keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for\n"
" those who are familiar with less and lynx.\n"
"\n"
"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
"o Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n"
"\n"
"\n"
"Alternate Configuration Files\n"
"-----------------------------\n"
"Menuconfig supports the use of alternate configuration files for\n"
"those who, for various reasons, find it necessary to switch\n"
"between different kernel configurations.\n"
"between different configurations.\n"
"\n"
"At the end of the main menu you will find two options. One is\n"
"for saving the current configuration to a file of your choosing.\n"
"The other option is for loading a previously saved alternate\n"
"configuration.\n"
"The <Save> button will let you save the current configuration to\n"
"a file of your choosing. Use the <Load> button to load a previously\n"
"saved alternate configuration.\n"
"\n"
"Even if you don't use alternate configuration files, but you\n"
"find during a Menuconfig session that you have completely messed\n"
"up your settings, you may use the \"Load Alternate...\" option to\n"
"restore your previously saved settings from \".config\" without\n"
"restarting Menuconfig.\n"
"Even if you don't use alternate configuration files, but you find\n"
"during a Menuconfig session that you have completely messed up your\n"
"settings, you may use the <Load> button to restore your previously\n"
"saved settings from \".config\" without restarting Menuconfig.\n"
"\n"
"Other information\n"
"-----------------\n"
"If you use Menuconfig in an XTERM window make sure you have your\n"
"$TERM variable set to point to a xterm definition which supports color.\n"
"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
"display correctly in a RXVT window because rxvt displays only one\n"
"If you use Menuconfig in an XTERM window, make sure you have your\n"
"$TERM variable set to point to an xterm definition which supports\n"
"color. Otherwise, Menuconfig will look rather bad. Menuconfig will\n"
"not display correctly in an RXVT window because rxvt displays only one\n"
"intensity of color, bright.\n"
"\n"
"Menuconfig will display larger menus on screens or xterms which are\n"
......@@ -148,9 +146,9 @@ static const char mconf_readme[] = N_(
"\n"
"Optional personality available\n"
"------------------------------\n"
"If you prefer to have all of the kernel options listed in a single\n"
"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
"If you prefer to have all of the options listed in a single menu,\n"
"rather than the default multimenu hierarchy, run the menuconfig with\n"
"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
"\n"
"make MENUCONFIG_MODE=single_menu menuconfig\n"
"\n"
......@@ -172,11 +170,11 @@ static const char mconf_readme[] = N_(
" mono => selects colors suitable for monochrome displays\n"
" blackbg => selects a color scheme with black background\n"
" classic => theme with blue background. The classic look\n"
" bluetitle => a LCD friendly version of classic. (default)\n"
" bluetitle => an LCD friendly version of classic. (default)\n"
"\n"),
menu_instructions[] = N_(
"Arrow keys navigate the menu. "
"<Enter> selects submenus --->. "
"<Enter> selects submenus ---> (or empty submenus ----). "
"Highlighted letters are hotkeys. "
"Pressing <Y> includes, <N> excludes, <M> modularizes features. "
"Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
......@@ -205,12 +203,12 @@ load_config_text[] = N_(
"last retrieved. Leave blank to abort."),
load_config_help[] = N_(
"\n"
"For various reasons, one may wish to keep several different kernel\n"
"For various reasons, one may wish to keep several different\n"
"configurations available on a single machine.\n"
"\n"
"If you have saved a previous configuration in a file other than the\n"
"kernel's default, entering the name of the file here will allow you\n"
"to modify that configuration.\n"
"default one, entering its name here will allow you to modify that\n"
"configuration.\n"
"\n"
"If you are uncertain, then you have probably never used alternate\n"
"configuration files. You should therefore leave this blank to abort.\n"),
......@@ -219,8 +217,8 @@ save_config_text[] = N_(
"as an alternate. Leave blank to abort."),
save_config_help[] = N_(
"\n"
"For various reasons, one may wish to keep different kernel\n"
"configurations available on a single machine.\n"
"For various reasons, one may wish to keep different configurations\n"
"available on a single machine.\n"
"\n"
"Entering a file name here will allow you to later retrieve, modify\n"
"and use the current configuration as an alternate to whatever\n"
......@@ -230,83 +228,79 @@ save_config_help[] = N_(
"leave this blank.\n"),
search_help[] = N_(
"\n"
"Search for CONFIG_ symbols and display their relations.\n"
"Search for symbols and display their relations.\n"
"Regular expressions are allowed.\n"
"Example: search for \"^FOO\"\n"
"Result:\n"
"-----------------------------------------------------------------\n"
"Symbol: FOO [=m]\n"
"Type : tristate\n"
"Prompt: Foo bus is used to drive the bar HW\n"
"Defined at drivers/pci/Kconfig:47\n"
"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
"Location:\n"
" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
" -> PCI support (PCI [=y])\n"
" -> PCI access mode (<choice> [=y])\n"
"Selects: LIBCRC32\n"
"Selected by: BAR\n"
" Location:\n"
" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
" -> PCI support (PCI [=y])\n"
"(1) -> PCI access mode (<choice> [=y])\n"
" Defined at drivers/pci/Kconfig:47\n"
" Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
" Selects: LIBCRC32\n"
" Selected by: BAR [=n]\n"
"-----------------------------------------------------------------\n"
"o The line 'Type:' shows the type of the configuration option for\n"
" this symbol (boolean, tristate, string, ...)\n"
"o The line 'Prompt:' shows the text used in the menu structure for\n"
" this CONFIG_ symbol\n"
"o The 'Defined at' line tell at what file / line number the symbol\n"
" this symbol\n"
"o The 'Defined at' line tells at what file / line number the symbol\n"
" is defined\n"
"o The 'Depends on:' line tell what symbols needs to be defined for\n"
"o The 'Depends on:' line tells what symbols need to be defined for\n"
" this symbol to be visible in the menu (selectable)\n"
"o The 'Location:' lines tell where in the menu structure this symbol\n"
"o The 'Location:' lines tells where in the menu structure this symbol\n"
" is located\n"
" A location followed by a [=y] indicate that this is a selectable\n"
" menu item - and current value is displayed inside brackets.\n"
"o The 'Selects:' line tell what symbol will be automatically\n"
" A location followed by a [=y] indicates that this is a\n"
" selectable menu item - and the current value is displayed inside\n"
" brackets.\n"
" Press the key in the (#) prefix to jump directly to that\n"
" location. You will be returned to the current search results\n"
" after exiting this new menu.\n"
"o The 'Selects:' line tells what symbols will be automatically\n"
" selected if this symbol is selected (y or m)\n"
"o The 'Selected by' line tell what symbol has selected this symbol\n"
"o The 'Selected by' line tells what symbol has selected this symbol\n"
"\n"
"Only relevant lines are shown.\n"
"\n\n"
"Search examples:\n"
"Examples: USB => find all CONFIG_ symbols containing USB\n"
" ^USB => find all CONFIG_ symbols starting with USB\n"
" USB$ => find all CONFIG_ symbols ending with USB\n"
"Examples: USB => find all symbols containing USB\n"
" ^USB => find all symbols starting with USB\n"
" USB$ => find all symbols ending with USB\n"
"\n");
static int indent;
static struct menu *current_menu;
static int child_count;
static int single_menu_mode;
static int show_all_options;
static int save_and_exit;
static int silent;
static void conf(struct menu *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 struct gstr get_relations_str(struct symbol **sym_arr)
{
struct symbol *sym;
struct gstr res = str_new();
int i;
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
get_symbol_str(&res, sym);
if (!i)
str_append(&res, _("No matches found.\n"));
return res;
}
static char filename[PATH_MAX+1];
static void set_config_filename(const char *config_filename)
{
static char menu_backtitle[PATH_MAX+128];
int size;
struct symbol *sym;
sym = sym_lookup("KERNELVERSION", 0);
sym_calc_value(sym);
size = snprintf(menu_backtitle, sizeof(menu_backtitle),
_("%s - WRS-sw v%s Configuration"),
config_filename, sym_get_string_value(sym));
"%s - %s", config_filename, rootmenu.prompt->text);
if (size >= sizeof(menu_backtitle))
menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
set_dialog_backtitle(menu_backtitle);
......@@ -316,18 +310,103 @@ static void set_config_filename(const char *config_filename)
filename[sizeof(filename)-1] = '\0';
}
struct subtitle_part {
struct list_head entries;
const char *text;
};
static LIST_HEAD(trail);
static struct subtitle_list *subtitles;
static void set_subtitle(void)
{
struct subtitle_part *sp;
struct subtitle_list *pos, *tmp;
for (pos = subtitles; pos != NULL; pos = tmp) {
tmp = pos->next;
free(pos);
}
subtitles = NULL;
list_for_each_entry(sp, &trail, entries) {
if (sp->text) {
if (pos) {
pos->next = xcalloc(1, sizeof(*pos));
pos = pos->next;
} else {
subtitles = pos = xcalloc(1, sizeof(*pos));
}
pos->text = sp->text;
}
}
set_dialog_subtitles(subtitles);
}
static void reset_subtitle(void)
{
struct subtitle_list *pos, *tmp;
for (pos = subtitles; pos != NULL; pos = tmp) {
tmp = pos->next;
free(pos);
}
subtitles = NULL;
set_dialog_subtitles(subtitles);
}
struct search_data {
struct list_head *head;
struct menu **targets;
int *keys;
};
static void update_text(char *buf, size_t start, size_t end, void *_data)
{
struct search_data *data = _data;
struct jump_key *pos;
int k = 0;
list_for_each_entry(pos, data->head, entries) {
if (pos->offset >= start && pos->offset < end) {
char header[4];
if (k < JUMP_NB) {
int key = '0' + (pos->index % JUMP_NB) + 1;
sprintf(header, "(%c)", key);
data->keys[k] = key;
data->targets[k] = pos->target;
k++;
} else {
sprintf(header, " ");
}
memcpy(buf + pos->offset, header, sizeof(header) - 1);
}
}
data->keys[k] = 0;
}
static void search_conf(void)
{
struct symbol **sym_arr;
struct gstr res;
struct gstr title;
char *dialog_input;
int dres;
int dres, vscroll = 0, hscroll = 0;
bool again;
struct gstr sttext;
struct subtitle_part stpart;
title = str_new();
str_printf( &title, _("Enter (sub)string or regexp to search for "
"(with or without \"%s\")"), CONFIG_);
again:
dialog_clear();
dres = dialog_inputbox(_("Search Configuration Parameter"),
_("Enter CONFIG_ (sub)string to search for "
"(with or without \"CONFIG\")"),
str_get(&title),
10, 75, "");
switch (dres) {
case 0:
......@@ -336,19 +415,52 @@ again:
show_helptext(_("Search Configuration"), search_help);
goto again;
default:
str_free(&title);
return;
}
/* strip CONFIG_ if necessary */
/* strip the prefix if necessary */
dialog_input = dialog_input_result;
if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
dialog_input += 7;
if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
dialog_input += strlen(CONFIG_);
sttext = str_new();
str_printf(&sttext, "Search (%s)", dialog_input_result);
stpart.text = str_get(&sttext);
list_add_tail(&stpart.entries, &trail);
sym_arr = sym_re_search(dialog_input);
res = get_relations_str(sym_arr);
do {
LIST_HEAD(head);
struct menu *targets[JUMP_NB];
int keys[JUMP_NB + 1], i;
struct search_data data = {
.head = &head,
.targets = targets,
.keys = keys,
};
struct jump_key *pos, *tmp;
res = get_relations_str(sym_arr, &head);
set_subtitle();
dres = show_textbox_ext(_("Search Results"), (char *)
str_get(&res), 0, 0, keys, &vscroll,
&hscroll, &update_text, (void *)
&data);
again = false;
for (i = 0; i < JUMP_NB && keys[i]; i++)
if (dres == keys[i]) {
conf(targets[i]->parent, targets[i]);
again = true;
}
str_free(&res);
list_for_each_entry_safe(pos, tmp, &head, entries)
free(pos);
} while (again);
free(sym_arr);
show_textbox(_("Search Results"), str_get(&res), 0, 0);
str_free(&res);
str_free(&title);
list_del(trail.prev);
str_free(&sttext);
}
static void build_conf(struct menu *menu)
......@@ -359,8 +471,16 @@ static void build_conf(struct menu *menu)
int type, tmp, doint = 2;
tristate val;
char ch;
bool visible;
if (!menu_is_visible(menu))
/*
* note: menu_is_visible() has side effect that it will
* recalc the value of the symbol.
*/
visible = menu_is_visible(menu);
if (show_all_options && !menu_has_prompt(menu))
return;
else if (!show_all_options && !visible)
return;
sym = menu->sym;
......@@ -377,8 +497,9 @@ static void build_conf(struct menu *menu)
menu->data ? "-->" : "++>",
indent + 1, ' ', prompt);
} else
item_make(" %*c%s --->", indent + 1, ' ', prompt);
item_make(" %*c%s %s",
indent + 1, ' ', prompt,
menu_is_empty(menu) ? "----" : "--->");
item_set_tag('m');
item_set_data(menu);
if (single_menu_mode && menu->data)
......@@ -509,7 +630,7 @@ static void build_conf(struct menu *menu)
(sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : _(" (NEW)"));
if (menu->prompt->type == P_MENU) {
item_add_str(" --->");
item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
return;
}
}
......@@ -521,40 +642,40 @@ conf_childs:
indent -= doint;
}
static void conf(struct menu *menu)
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;
struct menu *active_menu = NULL;
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;
if (menu == &rootmenu) {
item_make("--- ");
item_set_tag(':');
item_make(_(" Load an Alternate Configuration File"));
item_set_tag('L');
item_make(_(" Save an Alternate Configuration File"));
item_set_tag('S');
}
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_activate_selected())
continue;
if (!item_tag())
continue;
if (item_count() != 0) {
if (!item_activate_selected())
continue;
if (!item_tag())
continue;
}
submenu = item_data();
active_menu = item_data();
if (submenu)
......@@ -569,32 +690,36 @@ static void conf(struct menu *menu)
if (single_menu_mode)
submenu->data = (void *) (long) !submenu->data;
else
conf(submenu);
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);
conf(submenu, NULL);
break;
case 's':
conf_string(submenu);
break;
case 'L':
conf_load();
break;
case 'S':
conf_save();
break;
}
break;
case 2:
if (sym)
show_help(submenu);
else
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;
......@@ -602,31 +727,45 @@ static void conf(struct menu *menu)
show_textbox(NULL, setmod_text, 6, 74);
}
break;
case 4:
case 6:
if (item_is_tag('t'))
sym_set_tristate_value(sym, no);
break;
case 5:
case 7:
if (item_is_tag('t'))
sym_set_tristate_value(sym, mod);
break;
case 6:
case 8:
if (item_is_tag('t'))
sym_toggle_tristate_value(sym);
else if (item_is_tag('m'))
conf(submenu);
conf(submenu, NULL);
break;
case 7:
case 9:
search_conf();
break;
case 10:
show_all_options = !show_all_options;
break;
}
}
list_del(trail.prev);
}
static void show_textbox(const char *title, const char *text, int r, int c)
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();
dialog_textbox(title, text, r, c);
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)
......@@ -634,10 +773,24 @@ static void show_helptext(const char *title, const char *text)
show_textbox(title, text, 0, 0);
}
static void conf_message_callback(const char *fmt, va_list ap)
{
char buf[PATH_MAX+1];
vsnprintf(buf, sizeof(buf), fmt, ap);
if (save_and_exit) {
if (!silent)
printf("%s", buf);
} else {
show_textbox(NULL, buf, 6, 60);
}
}
static void show_help(struct menu *menu)
{
struct gstr help = str_new();
help.max_width = getmaxx(stdscr) - 10;
menu_get_ext_help(menu, &help);
show_helptext(_(menu_get_prompt(menu)), str_get(&help));
......@@ -675,7 +828,9 @@ static void conf_choice(struct menu *menu)
dialog_clear();
res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
_(radiolist_instructions),
15, 70, 6);
MENUBOX_HEIGTH_MIN,
MENUBOX_WIDTH_MIN,
CHECKLIST_HEIGTH_MIN);
selected = item_activate_selected();
switch (res) {
case 0:
......@@ -797,9 +952,60 @@ static void conf_save(void)
}
}
static int handle_exit(void)
{
int res;
save_and_exit = 1;
reset_subtitle();
dialog_clear();
if (conf_get_changed())
res = dialog_yesno(NULL,
_("Do you wish to save your new configuration?\n"
"(Press <ESC><ESC> to continue kernel configuration.)"),
6, 60);
else
res = -1;
end_dialog(saved_x, saved_y);
switch (res) {
case 0:
if (conf_write(filename)) {
fprintf(stderr, _("\n\n"
"Error while writing of the configuration.\n"
"Your configuration changes were NOT saved."
"\n\n"));
return 1;
}
/* fall through */
case -1:
if (!silent)
printf(_("\n\n"
"*** End of the configuration.\n"
"*** Execute 'make' to start the build or try 'make help'."
"\n\n"));
res = 0;
break;
default:
if (!silent)
fprintf(stderr, _("\n\n"
"Your configuration changes were NOT saved."
"\n\n"));
if (res != KEY_ESC)
res = 0;
}
return res;
}
static void sig_handler(int signo)
{
exit(handle_exit());
}
int main(int ac, char **av)
{
int saved_x, saved_y;
char *mode;
int res;
......@@ -807,6 +1013,14 @@ int main(int ac, char **av)
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
signal(SIGINT, sig_handler);
if (ac > 1 && strcmp(av[1], "-s") == 0) {
silent = 1;
/* Silence conf_read() until the real callback is set up */
conf_set_message_callback(NULL);
av++;
}
conf_parse(av[1]);
conf_read(NULL);
......@@ -816,9 +1030,6 @@ int main(int ac, char **av)
single_menu_mode = 1;
}
initscr();
getyx(stdscr, saved_y, saved_x);
if (init_dialog(NULL)) {
fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
......@@ -826,41 +1037,11 @@ int main(int ac, char **av)
}
set_config_filename(conf_get_configname());
conf_set_message_callback(conf_message_callback);
do {
conf(&rootmenu);
dialog_clear();
if (conf_get_changed())
res = dialog_yesno(NULL,
_("Do you wish to save your "
"new WRS-sw configuration?\n"
"<ESC><ESC> to continue."),
6, 60);
else
res = -1;
conf(&rootmenu, NULL);
res = handle_exit();
} while (res == KEY_ESC);
end_dialog(saved_x, saved_y);
switch (res) {
case 0:
if (conf_write(filename)) {
fprintf(stderr, _("\n\n"
"Error during writing of the WRS-sw configuration.\n"
"Your WRS-sw configuration changes were NOT saved."
"\n\n"));
return 1;
}
case -1:
printf(_("\n\n"
"*** End of WRS-sw configuration.\n"
"*** Execute 'make' to build the binary."
"\n\n"));
break;
default:
fprintf(stderr, _("\n\n"
"Your WRS-sw configuration changes were NOT saved."
"\n\n"));
}
return 0;
return res;
}
......@@ -3,14 +3,14 @@
* Released under the terms of the GNU GPL v2.0.
*/
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
static const char nohelp_text[] = N_(
"There is no help available for this configuration option.\n");
static const char nohelp_text[] = "There is no help available for this option.";
struct menu rootmenu;
static struct menu **last_entry_ptr;
......@@ -38,7 +38,7 @@ static void prop_warn(struct property *prop, const char *fmt, ...)
va_end(ap);
}
void menu_init(void)
void _menu_init(void)
{
current_entry = current_menu = &rootmenu;
last_entry_ptr = &rootmenu.list;
......@@ -48,7 +48,7 @@ void menu_add_entry(struct symbol *sym)
{
struct menu *menu;
menu = malloc(sizeof(*menu));
menu = xmalloc(sizeof(*menu));
memset(menu, 0, sizeof(*menu));
menu->sym = sym;
menu->parent = current_menu;
......@@ -58,6 +58,8 @@ void menu_add_entry(struct symbol *sym)
*last_entry_ptr = menu;
last_entry_ptr = &menu->next;
current_entry = menu;
if (sym)
menu_add_symbol(P_SYMBOL, sym, NULL);
}
void menu_end_entry(void)
......@@ -117,12 +119,13 @@ void menu_set_type(int type)
sym->type = type;
return;
}
menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
sym->name ? sym->name : "<choice>",
sym_type_name(sym->type), sym_type_name(type));
menu_warn(current_entry,
"ignoring type redefinition of '%s' from '%s' to '%s'",
sym->name ? sym->name : "<choice>",
sym_type_name(sym->type), sym_type_name(type));
}
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
static struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
{
struct property *prop = prop_alloc(type, current_entry->sym);
......@@ -136,8 +139,35 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
while (isspace(*prompt))
prompt++;
}
if (current_entry->prompt)
if (current_entry->prompt && current_entry != &rootmenu)
prop_warn(prop, "prompt redefined");
/* Apply all upper menus' visibilities to actual prompts. */
if(type == P_PROMPT) {
struct menu *menu = current_entry;
while ((menu = menu->parent) != NULL) {
struct expr *dup_expr;
if (!menu->visibility)
continue;
/*
* Do not add a reference to the
* menu's visibility expression but
* use a copy of it. Otherwise the
* expression reduction functions
* will modify expressions that have
* multiple references which can
* cause unwanted side effects.
*/
dup_expr = expr_copy(menu->visibility);
prop->visible.expr
= expr_alloc_and(prop->visible.expr,
dup_expr);
}
}
current_entry->prompt = prop;
}
prop->text = prompt;
......@@ -150,6 +180,12 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr
return menu_add_prop(type, prompt, NULL, dep);
}
void menu_add_visibility(struct expr *expr)
{
current_entry->visibility = expr_alloc_and(current_entry->visibility,
expr);
}
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
{
menu_add_prop(type, NULL, expr, dep);
......@@ -162,12 +198,15 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
void menu_add_option(int token, char *arg)
{
struct property *prop;
switch (token) {
case T_OPT_MODULES:
prop = prop_alloc(P_DEFAULT, modules_sym);
prop->expr = expr_alloc_symbol(current_entry->sym);
if (modules_sym)
zconf_error("symbol '%s' redefines option 'modules'"
" already defined by symbol '%s'",
current_entry->sym->name,
modules_sym->name
);
modules_sym = current_entry->sym;
break;
case T_OPT_DEFCONFIG_LIST:
if (!sym_defconfig_list)
......@@ -178,10 +217,13 @@ void menu_add_option(int token, char *arg)
case T_OPT_ENV:
prop_add_env(arg);
break;
case T_OPT_ALLNOCONFIG_Y:
current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
break;
}
}
static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
{
return sym2->type == S_INT || sym2->type == S_HEX ||
(sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
......@@ -197,8 +239,17 @@ static void sym_check_prop(struct symbol *sym)
if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
prop->expr->type != E_SYMBOL)
prop_warn(prop,
"default for config symbol '%'"
"default for config symbol '%s'"
" must be a single symbol", sym->name);
if (prop->expr->type != E_SYMBOL)
break;
sym2 = prop_get_symbol(prop);
if (sym->type == S_HEX || sym->type == S_INT) {
if (!menu_validate_number(sym, sym2))
prop_warn(prop,
"'%s': number is invalid",
sym->name);
}
break;
case P_SELECT:
sym2 = prop_get_symbol(prop);
......@@ -207,8 +258,8 @@ static void sym_check_prop(struct symbol *sym)
"config symbol '%s' uses select, but is "
"not boolean or tristate", sym->name);
else if (sym2->type != S_UNKNOWN &&
sym2->type != S_BOOLEAN &&
sym2->type != S_TRISTATE)
sym2->type != S_BOOLEAN &&
sym2->type != S_TRISTATE)
prop_warn(prop,
"'%s' has wrong type. 'select' only "
"accept arguments of boolean and "
......@@ -217,9 +268,9 @@ static void sym_check_prop(struct symbol *sym)
case P_RANGE:
if (sym->type != S_INT && sym->type != S_HEX)
prop_warn(prop, "range is only allowed "
"for int or hex symbols");
if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
!menu_range_valid_sym(sym, prop->expr->right.sym))
"for int or hex symbols");
if (!menu_validate_number(sym, prop->expr->left.sym) ||
!menu_validate_number(sym, prop->expr->right.sym))
prop_warn(prop, "range is invalid");
break;
default:
......@@ -318,6 +369,8 @@ void menu_finalize(struct menu *parent)
parent->next = last_menu->next;
last_menu->next = NULL;
}
sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
}
for (menu = parent->list; menu; menu = menu->next) {
if (sym && sym_is_choice(sym) &&
......@@ -327,11 +380,9 @@ void menu_finalize(struct menu *parent)
if (!menu->prompt)
menu_warn(menu, "choice value must have a prompt");
for (prop = menu->sym->prop; prop; prop = prop->next) {
#if 0 /* Actually, it works */
if (prop->type == P_DEFAULT)
prop_warn(prop, "defaults for choice "
"values not supported");
#endif
if (prop->menu == menu)
continue;
if (prop->type == P_PROMPT &&
......@@ -392,6 +443,29 @@ void menu_finalize(struct menu *parent)
}
}
bool menu_has_prompt(struct menu *menu)
{
if (!menu->prompt)
return false;
return true;
}
/*
* Determine if a menu is empty.
* A menu is considered empty if it contains no or only
* invisible entries.
*/
bool menu_is_empty(struct menu *menu)
{
struct menu *child;
for (child = menu->list; child; child = child->next) {
if (menu_is_visible(child))
return(false);
}
return(true);
}
bool menu_is_visible(struct menu *menu)
{
struct menu *child;
......@@ -400,6 +474,12 @@ bool menu_is_visible(struct menu *menu)
if (!menu->prompt)
return false;
if (menu->visibility) {
if (expr_calc_value(menu->visibility) == no)
return false;
}
sym = menu->sym;
if (sym) {
sym_calc_value(sym);
......@@ -409,12 +489,18 @@ bool menu_is_visible(struct menu *menu)
if (visible != no)
return true;
if (!sym || sym_get_tristate_value(menu->sym) == no)
return false;
for (child = menu->list; child; child = child->next)
if (menu_is_visible(child))
for (child = menu->list; child; child = child->next) {
if (menu_is_visible(child)) {
if (sym)
sym->flags |= SYMBOL_DEF_USER;
return true;
}
}
return false;
}
......@@ -457,27 +543,53 @@ const char *menu_get_help(struct menu *menu)
return "";
}
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)
{
int i, j;
struct menu *submenu[8], *menu;
struct menu *submenu[8], *menu, *location = NULL;
struct jump_key *jump = NULL;
str_printf(r, _("Prompt: %s\n"), _(prop->text));
str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
prop->menu->lineno);
if (!expr_is_yes(prop->visible.expr)) {
str_append(r, _(" Depends on: "));
expr_gstr_print(prop->visible.expr, r);
str_append(r, "\n");
}
menu = prop->menu->parent;
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
bool accessible = menu_is_visible(menu);
submenu[i++] = menu;
if (location == NULL && accessible)
location = menu;
}
if (head && location) {
jump = xmalloc(sizeof(struct jump_key));
if (menu_is_visible(prop->menu)) {
/*
* There is not enough room to put the hint at the
* beginning of the "Prompt" line. Put the hint on the
* last "Location" line even when it would belong on
* the former.
*/
jump->target = prop->menu;
} else
jump->target = location;
if (list_empty(head))
jump->index = 0;
else
jump->index = list_entry(head->prev, struct jump_key,
entries)->index + 1;
list_add_tail(&jump->entries, head);
}
if (i > 0) {
str_printf(r, _(" Location:\n"));
for (j = 4; --i >= 0; j += 2) {
menu = submenu[i];
str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
if (jump && menu == location)
jump->offset = strlen(r->s);
str_printf(r, "%*c-> %s", j, ' ',
_(menu_get_prompt(menu)));
if (menu->sym) {
str_printf(r, " (%s [=%s])", menu->sym->name ?
menu->sym->name : _("<choice>"),
......@@ -488,16 +600,54 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
}
}
void get_symbol_str(struct gstr *r, struct symbol *sym)
/*
* get property of type P_SYMBOL
*/
static struct property *get_symbol_prop(struct symbol *sym)
{
struct property *prop = NULL;
for_all_properties(sym, prop, P_SYMBOL)
break;
return prop;
}
/*
* head is optional and may be NULL
*/
static void get_symbol_str(struct gstr *r, struct symbol *sym,
struct list_head *head)
{
bool hit;
struct property *prop;
if (sym && sym->name)
if (sym && sym->name) {
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
sym_get_string_value(sym));
str_printf(r, "Type : %s\n", sym_type_name(sym->type));
if (sym->type == S_INT || sym->type == S_HEX) {
prop = sym_get_range_prop(sym);
if (prop) {
str_printf(r, "Range : ");
expr_gstr_print(prop->expr, r);
str_append(r, "\n");
}
}
}
for_all_prompts(sym, prop)
get_prompt_str(r, prop);
get_prompt_str(r, prop, head);
prop = get_symbol_prop(sym);
if (prop) {
str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
prop->menu->lineno);
if (!expr_is_yes(prop->visible.expr)) {
str_append(r, _(" Depends on: "));
expr_gstr_print(prop->visible.expr, r);
str_append(r, "\n");
}
}
hit = false;
for_all_properties(sym, prop, P_SELECT) {
if (!hit) {
......@@ -517,19 +667,31 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
str_append(r, "\n\n");
}
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
{
struct symbol *sym;
struct gstr res = str_new();
int i;
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
get_symbol_str(&res, sym, head);
if (!i)
str_append(&res, _("No matches found.\n"));
return res;
}
void menu_get_ext_help(struct menu *menu, struct gstr *help)
{
struct symbol *sym = menu->sym;
const char *help_text = nohelp_text;
if (menu_has_help(menu)) {
if (sym->name) {
str_printf(help, "CONFIG_%s:\n\n", sym->name);
str_append(help, _(menu_get_help(menu)));
str_append(help, "\n");
}
} else {
str_append(help, nohelp_text);
if (sym->name)
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
help_text = menu_get_help(menu);
}
str_printf(help, "%s\n", _(help_text));
if (sym)
get_symbol_str(help, sym);
get_symbol_str(help, sym, NULL);
}
#!/bin/sh
# merge_config.sh - Takes a list of config fragment values, and merges
# them one by one. Provides warnings on overridden values, and specified
# values that did not make it to the resulting .config file (due to missed
# dependencies or config symbol removal).
#
# Portions reused from kconf_check and generate_cfg:
# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check
# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg
#
# Copyright (c) 2009-2010 Wind River Systems, Inc.
# Copyright 2011 Linaro
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
clean_up() {
rm -f $TMP_FILE
exit
}
trap clean_up HUP INT TERM
usage() {
echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
echo " -h display this help text"
echo " -m only merge the fragments, do not execute the make command"
echo " -n use allnoconfig instead of alldefconfig"
echo " -r list redundant entries when merging fragments"
echo " -O dir to put generated output files. Consider setting \$KCONFIG_CONFIG instead."
}
RUNMAKE=true
ALLTARGET=alldefconfig
WARNREDUN=false
OUTPUT=.
while true; do
case $1 in
"-n")
ALLTARGET=allnoconfig
shift
continue
;;
"-m")
RUNMAKE=false
shift
continue
;;
"-h")
usage
exit
;;
"-r")
WARNREDUN=true
shift
continue
;;
"-O")
if [ -d $2 ];then
OUTPUT=$(echo $2 | sed 's/\/*$//')
else
echo "output directory $2 does not exist" 1>&2
exit 1
fi
shift 2
continue
;;
*)
break
;;
esac
done
if [ "$#" -lt 1 ] ; then
usage
exit
fi
if [ -z "$KCONFIG_CONFIG" ]; then
if [ "$OUTPUT" != . ]; then
KCONFIG_CONFIG=$(readlink -m -- "$OUTPUT/.config")
else
KCONFIG_CONFIG=.config
fi
fi
INITFILE=$1
shift;
if [ ! -r "$INITFILE" ]; then
echo "The base file '$INITFILE' does not exist. Exit." >&2
exit 1
fi
MERGE_LIST=$*
SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p"
TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
echo "Using $INITFILE as base"
cat $INITFILE > $TMP_FILE
# Merge files, printing warnings on overridden values
for MERGE_FILE in $MERGE_LIST ; do
echo "Merging $MERGE_FILE"
if [ ! -r "$MERGE_FILE" ]; then
echo "The merge file '$MERGE_FILE' does not exist. Exit." >&2
exit 1
fi
CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE)
for CFG in $CFG_LIST ; do
grep -q -w $CFG $TMP_FILE || continue
PREV_VAL=$(grep -w $CFG $TMP_FILE)
NEW_VAL=$(grep -w $CFG $MERGE_FILE)
if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
echo Value of $CFG is redefined by fragment $MERGE_FILE:
echo Previous value: $PREV_VAL
echo New value: $NEW_VAL
echo
elif [ "$WARNREDUN" = "true" ]; then
echo Value of $CFG is redundant by fragment $MERGE_FILE:
fi
sed -i "/$CFG[ =]/d" $TMP_FILE
done
cat $MERGE_FILE >> $TMP_FILE
done
if [ "$RUNMAKE" = "false" ]; then
cp -T -- "$TMP_FILE" "$KCONFIG_CONFIG"
echo "#"
echo "# merged configuration written to $KCONFIG_CONFIG (needs make)"
echo "#"
clean_up
exit
fi
# If we have an output dir, setup the O= argument, otherwise leave
# it blank, since O=. will create an unnecessary ./source softlink
OUTPUT_ARG=""
if [ "$OUTPUT" != "." ] ; then
OUTPUT_ARG="O=$OUTPUT"
fi
# Use the merged file as the starting point for:
# alldefconfig: Fills in any missing symbols with Kconfig default
# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set
make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET
# Check all specified config values took (might have missed-dependency issues)
for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do
REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG")
if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
echo "Value requested for $CFG not in final .config"
echo "Requested value: $REQUESTED_VAL"
echo "Actual value: $ACTUAL_VAL"
echo ""
fi
done
clean_up
/*
* Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
* Released under the terms of the GNU GPL v2.0.
*
* Derived from menuconfig.
*
*/
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include "lkc.h"
#include "nconf.h"
#include <ctype.h>
static const char nconf_global_help[] = N_(
"Help windows\n"
"------------\n"
"o Global help: Unless in a data entry window, pressing <F1> will give \n"
" you the global help window, which you are just reading.\n"
"\n"
"o A short version of the global help is available by pressing <F3>.\n"
"\n"
"o Local help: To get help related to the current menu entry, use any\n"
" of <?> <h>, or if in a data entry window then press <F1>.\n"
"\n"
"\n"
"Menu entries\n"
"------------\n"
"This interface lets you select features and parameters for the kernel\n"
"build. Kernel features can either be built-in, modularized, or removed.\n"
"Parameters must be entered as text or decimal or hexadecimal numbers.\n"
"\n"
"Menu entries beginning with following braces represent features that\n"
" [ ] can be built in or removed\n"
" < > can be built in, modularized or removed\n"
" { } can be built in or modularized, are selected by another feature\n"
" - - are selected by another feature\n"
" XXX cannot be selected. Symbol Info <F2> tells you why.\n"
"*, M or whitespace inside braces means to build in, build as a module\n"
"or to exclude the feature respectively.\n"
"\n"
"To change any of these features, highlight it with the movement keys\n"
"listed below and press <y> to build it in, <m> to make it a module or\n"
"<n> to remove it. You may press the <Space> key to cycle through the\n"
"available options.\n"
"\n"
"A trailing \"--->\" designates a submenu, a trailing \"----\" an\n"
"empty submenu.\n"
"\n"
"Menu navigation keys\n"
"----------------------------------------------------------------------\n"
"Linewise up <Up>\n"
"Linewise down <Down>\n"
"Pagewise up <Page Up>\n"
"Pagewise down <Page Down>\n"
"First entry <Home>\n"
"Last entry <End>\n"
"Enter a submenu <Right> <Enter>\n"
"Go back to parent menu <Left> <Esc> <F5>\n"
"Close a help window <Enter> <Esc> <F5>\n"
"Close entry window, apply <Enter>\n"
"Close entry window, forget <Esc> <F5>\n"
"Start incremental, case-insensitive search for STRING in menu entries,\n"
" no regex support, STRING is displayed in upper left corner\n"
" </>STRING\n"
" Remove last character <Backspace>\n"
" Jump to next hit <Down>\n"
" Jump to previous hit <Up>\n"
"Exit menu search mode </> <Esc>\n"
"Search for configuration variables with or without leading CONFIG_\n"
" <F8>RegExpr<Enter>\n"
"Verbose search help <F8><F1>\n"
"----------------------------------------------------------------------\n"
"\n"
"Unless in a data entry window, key <1> may be used instead of <F1>,\n"
"<2> instead of <F2>, etc.\n"
"\n"
"\n"
"Radiolist (Choice list)\n"
"-----------------------\n"
"Use the movement keys listed above to select the option you wish to set\n"
"and press <Space>.\n"
"\n"
"\n"
"Data entry\n"
"----------\n"
"Enter the requested information and press <Enter>. Hexadecimal values\n"
"may be entered without the \"0x\" prefix.\n"
"\n"
"\n"
"Text Box (Help Window)\n"
"----------------------\n"
"Use movement keys as listed in table above.\n"
"\n"
"Press any of <Enter> <Esc> <q> <F5> <F9> to exit.\n"
"\n"
"\n"
"Alternate configuration files\n"
"-----------------------------\n"
"nconfig supports switching between different configurations.\n"
"Press <F6> to save your current configuration. Press <F7> and enter\n"
"a file name to load a previously saved configuration.\n"
"\n"
"\n"
"Terminal configuration\n"
"----------------------\n"
"If you use nconfig in a xterm window, make sure your TERM environment\n"
"variable specifies a terminal configuration which supports at least\n"
"16 colors. Otherwise nconfig will look rather bad.\n"
"\n"
"If the \"stty size\" command reports the current terminalsize correctly,\n"
"nconfig will adapt to sizes larger than the traditional 80x25 \"standard\"\n"
"and display longer menus properly.\n"
"\n"
"\n"
"Single menu mode\n"
"----------------\n"
"If you prefer to have all of the menu entries listed in a single menu,\n"
"rather than the default multimenu hierarchy, run nconfig with\n"
"NCONFIG_MODE environment variable set to single_menu. Example:\n"
"\n"
"make NCONFIG_MODE=single_menu nconfig\n"
"\n"
"<Enter> will then unfold the appropriate category, or fold it if it\n"
"is already unfolded. Folded menu entries will be designated by a\n"
"leading \"++>\" and unfolded entries by a leading \"-->\".\n"
"\n"
"Note that this mode can eventually be a little more CPU expensive than\n"
"the default mode, especially with a larger number of unfolded submenus.\n"
"\n"),
menu_no_f_instructions[] = N_(
"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
"\n"
"Use the following keys to navigate the menus:\n"
"Move up or down with <Up> and <Down>.\n"
"Enter a submenu with <Enter> or <Right>.\n"
"Exit a submenu to its parent menu with <Esc> or <Left>.\n"
"Pressing <y> includes, <n> excludes, <m> modularizes features.\n"
"Pressing <Space> cycles through the available options.\n"
"To search for menu entries press </>.\n"
"<Esc> always leaves the current window.\n"
"\n"
"You do not have function keys support.\n"
"Press <1> instead of <F1>, <2> instead of <F2>, etc.\n"
"For verbose global help use key <1>.\n"
"For help related to the current menu entry press <?> or <h>.\n"),
menu_instructions[] = N_(
"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
"\n"
"Use the following keys to navigate the menus:\n"
"Move up or down with <Up> or <Down>.\n"
"Enter a submenu with <Enter> or <Right>.\n"
"Exit a submenu to its parent menu with <Esc> or <Left>.\n"
"Pressing <y> includes, <n> excludes, <m> modularizes features.\n"
"Pressing <Space> cycles through the available options.\n"
"To search for menu entries press </>.\n"
"<Esc> always leaves the current window.\n"
"\n"
"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n"
"For verbose global help press <F1>.\n"
"For help related to the current menu entry press <?> or <h>.\n"),
radiolist_instructions[] = N_(
"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n"
"with <Space>.\n"
"For help related to the current entry press <?> or <h>.\n"
"For global help press <F1>.\n"),
inputbox_instructions_int[] = N_(
"Please enter a decimal value.\n"
"Fractions will not be accepted.\n"
"Press <Enter> to apply, <Esc> to cancel."),
inputbox_instructions_hex[] = N_(
"Please enter a hexadecimal value.\n"
"Press <Enter> to apply, <Esc> to cancel."),
inputbox_instructions_string[] = N_(
"Please enter a string value.\n"
"Press <Enter> to apply, <Esc> to cancel."),
setmod_text[] = N_(
"This feature depends on another feature which has been configured as a\n"
"module. As a result, the current feature will be built as a module too."),
load_config_text[] = N_(
"Enter the name of the configuration file you wish to load.\n"
"Accept the name shown to restore the configuration you last\n"
"retrieved. Leave empty to abort."),
load_config_help[] = N_(
"For various reasons, one may wish to keep several different\n"
"configurations available on a single machine.\n"
"\n"
"If you have saved a previous configuration in a file other than the\n"
"default one, entering its name here will allow you to load and modify\n"
"that configuration.\n"
"\n"
"Leave empty to abort.\n"),
save_config_text[] = N_(
"Enter a filename to which this configuration should be saved\n"
"as an alternate. Leave empty to abort."),
save_config_help[] = N_(
"For various reasons, one may wish to keep several different\n"
"configurations available on a single machine.\n"
"\n"
"Entering a file name here will allow you to later retrieve, modify\n"
"and use the current configuration as an alternate to whatever\n"
"configuration options you have selected at that time.\n"
"\n"
"Leave empty to abort.\n"),
search_help[] = N_(
"Search for symbols (configuration variable names CONFIG_*) and display\n"
"their relations. Regular expressions are supported.\n"
"Example: Search for \"^FOO\".\n"
"Result:\n"
"-----------------------------------------------------------------\n"
"Symbol: FOO [ = m]\n"
"Prompt: Foo bus is used to drive the bar HW\n"
"Defined at drivers/pci/Kconfig:47\n"
"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
"Location:\n"
" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
" -> PCI support (PCI [ = y])\n"
" -> PCI access mode (<choice> [ = y])\n"
"Selects: LIBCRC32\n"
"Selected by: BAR\n"
"-----------------------------------------------------------------\n"
"o The line 'Prompt:' shows the text displayed for this symbol in\n"
" the menu hierarchy.\n"
"o The 'Defined at' line tells at what file / line number the symbol is\n"
" defined.\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"
"o The 'Location:' lines tell, where in the menu structure this symbol\n"
" is located. A location followed by a [ = y] indicates that this is\n"
" a selectable menu item, and the current value is displayed inside\n"
" brackets.\n"
"o The 'Selects:' line tells, what symbol will be automatically selected\n"
" if this symbol is selected (y or m).\n"
"o The 'Selected by' line tells what symbol has selected this symbol.\n"
"\n"
"Only relevant lines are shown.\n"
"\n\n"
"Search examples:\n"
"USB => find all symbols containing USB\n"
"^USB => find all symbols starting with USB\n"
"USB$ => find all symbols ending with USB\n"
"\n");
struct mitem {
char str[256];
char tag;
void *usrptr;
int is_visible;
};
#define MAX_MENU_ITEMS 4096
static int show_all_items;
static int indent;
static struct menu *current_menu;
static int child_count;
static int single_menu_mode;
/* the window in which all information appears */
static WINDOW *main_window;
/* the largest size of the menu window */
static int mwin_max_lines;
static int mwin_max_cols;
/* the window in which we show option buttons */
static MENU *curses_menu;
static ITEM *curses_menu_items[MAX_MENU_ITEMS];
static struct mitem k_menu_items[MAX_MENU_ITEMS];
static int items_num;
static int global_exit;
/* the currently selected button */
const char *current_instructions = menu_instructions;
static char *dialog_input_result;
static int dialog_input_result_len;
static void conf(struct menu *menu);
static void conf_choice(struct menu *menu);
static void conf_string(struct menu *menu);
static void conf_load(void);
static void conf_save(void);
static void show_help(struct menu *menu);
static int do_exit(void);
static void setup_windows(void);
static void search_conf(void);
typedef void (*function_key_handler_t)(int *key, struct menu *menu);
static void handle_f1(int *key, struct menu *current_item);
static void handle_f2(int *key, struct menu *current_item);
static void handle_f3(int *key, struct menu *current_item);
static void handle_f4(int *key, struct menu *current_item);
static void handle_f5(int *key, struct menu *current_item);
static void handle_f6(int *key, struct menu *current_item);
static void handle_f7(int *key, struct menu *current_item);
static void handle_f8(int *key, struct menu *current_item);
static void handle_f9(int *key, struct menu *current_item);
struct function_keys {
const char *key_str;
const char *func;
function_key key;
function_key_handler_t handler;
};
static const int function_keys_num = 9;
struct function_keys function_keys[] = {
{
.key_str = "F1",
.func = "Help",
.key = F_HELP,
.handler = handle_f1,
},
{
.key_str = "F2",
.func = "SymInfo",
.key = F_SYMBOL,
.handler = handle_f2,
},
{
.key_str = "F3",
.func = "Help 2",
.key = F_INSTS,
.handler = handle_f3,
},
{
.key_str = "F4",
.func = "ShowAll",
.key = F_CONF,
.handler = handle_f4,
},
{
.key_str = "F5",
.func = "Back",
.key = F_BACK,
.handler = handle_f5,
},
{
.key_str = "F6",
.func = "Save",
.key = F_SAVE,
.handler = handle_f6,
},
{
.key_str = "F7",
.func = "Load",
.key = F_LOAD,
.handler = handle_f7,
},
{
.key_str = "F8",
.func = "SymSearch",
.key = F_SEARCH,
.handler = handle_f8,
},
{
.key_str = "F9",
.func = "Exit",
.key = F_EXIT,
.handler = handle_f9,
},
};
static void print_function_line(void)
{
int i;
int offset = 1;
const int skip = 1;
int lines = getmaxy(stdscr);
for (i = 0; i < function_keys_num; i++) {
(void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
mvwprintw(main_window, lines-3, offset,
"%s",
function_keys[i].key_str);
(void) wattrset(main_window, attributes[FUNCTION_TEXT]);
offset += strlen(function_keys[i].key_str);
mvwprintw(main_window, lines-3,
offset, "%s",
function_keys[i].func);
offset += strlen(function_keys[i].func) + skip;
}
(void) wattrset(main_window, attributes[NORMAL]);
}
/* help */
static void handle_f1(int *key, struct menu *current_item)
{
show_scroll_win(main_window,
_("Global help"), _(nconf_global_help));
return;
}
/* symbole help */
static void handle_f2(int *key, struct menu *current_item)
{
show_help(current_item);
return;
}
/* instructions */
static void handle_f3(int *key, struct menu *current_item)
{
show_scroll_win(main_window,
_("Short help"),
_(current_instructions));
return;
}
/* config */
static void handle_f4(int *key, struct menu *current_item)
{
int res = btn_dialog(main_window,
_("Show all symbols?"),
2,
" <Show All> ",
"<Don't show all>");
if (res == 0)
show_all_items = 1;
else if (res == 1)
show_all_items = 0;
return;
}
/* back */
static void handle_f5(int *key, struct menu *current_item)
{
*key = KEY_LEFT;
return;
}
/* save */
static void handle_f6(int *key, struct menu *current_item)
{
conf_save();
return;
}
/* load */
static void handle_f7(int *key, struct menu *current_item)
{
conf_load();
return;
}
/* search */
static void handle_f8(int *key, struct menu *current_item)
{
search_conf();
return;
}
/* exit */
static void handle_f9(int *key, struct menu *current_item)
{
do_exit();
return;
}
/* return != 0 to indicate the key was handles */
static int process_special_keys(int *key, struct menu *menu)
{
int i;
if (*key == KEY_RESIZE) {
setup_windows();
return 1;
}
for (i = 0; i < function_keys_num; i++) {
if (*key == KEY_F(function_keys[i].key) ||
*key == '0' + function_keys[i].key){
function_keys[i].handler(key, menu);
return 1;
}
}
return 0;
}
static void clean_items(void)
{
int i;
for (i = 0; curses_menu_items[i]; i++)
free_item(curses_menu_items[i]);
bzero(curses_menu_items, sizeof(curses_menu_items));
bzero(k_menu_items, sizeof(k_menu_items));
items_num = 0;
}
typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
/* return the index of the matched item, or -1 if no such item exists */
static int get_mext_match(const char *match_str, match_f flag)
{
int match_start = item_index(current_item(curses_menu));
int index;
if (flag == FIND_NEXT_MATCH_DOWN)
++match_start;
else if (flag == FIND_NEXT_MATCH_UP)
--match_start;
index = match_start;
index = (index + items_num) % items_num;
while (true) {
char *str = k_menu_items[index].str;
if (strcasestr(str, match_str) != 0)
return index;
if (flag == FIND_NEXT_MATCH_UP ||
flag == MATCH_TINKER_PATTERN_UP)
--index;
else
++index;
index = (index + items_num) % items_num;
if (index == match_start)
return -1;
}
}
/* Make a new item. */
static void item_make(struct menu *menu, char tag, const char *fmt, ...)
{
va_list ap;
if (items_num > MAX_MENU_ITEMS-1)
return;
bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
k_menu_items[items_num].tag = tag;
k_menu_items[items_num].usrptr = menu;
if (menu != NULL)
k_menu_items[items_num].is_visible =
menu_is_visible(menu);
else
k_menu_items[items_num].is_visible = 1;
va_start(ap, fmt);
vsnprintf(k_menu_items[items_num].str,
sizeof(k_menu_items[items_num].str),
fmt, ap);
va_end(ap);
if (!k_menu_items[items_num].is_visible)
memcpy(k_menu_items[items_num].str, "XXX", 3);
curses_menu_items[items_num] = new_item(
k_menu_items[items_num].str,
k_menu_items[items_num].str);
set_item_userptr(curses_menu_items[items_num],
&k_menu_items[items_num]);
/*
if (!k_menu_items[items_num].is_visible)
item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
*/
items_num++;
curses_menu_items[items_num] = NULL;
}
/* very hackish. adds a string to the last item added */
static void item_add_str(const char *fmt, ...)
{
va_list ap;
int index = items_num-1;
char new_str[256];
char tmp_str[256];
if (index < 0)
return;
va_start(ap, fmt);
vsnprintf(new_str, sizeof(new_str), fmt, ap);
va_end(ap);
snprintf(tmp_str, sizeof(tmp_str), "%s%s",
k_menu_items[index].str, new_str);
strncpy(k_menu_items[index].str,
tmp_str,
sizeof(k_menu_items[index].str));
free_item(curses_menu_items[index]);
curses_menu_items[index] = new_item(
k_menu_items[index].str,
k_menu_items[index].str);
set_item_userptr(curses_menu_items[index],
&k_menu_items[index]);
}
/* get the tag of the currently selected item */
static char item_tag(void)
{
ITEM *cur;
struct mitem *mcur;
cur = current_item(curses_menu);
if (cur == NULL)
return 0;
mcur = (struct mitem *) item_userptr(cur);
return mcur->tag;
}
static int curses_item_index(void)
{
return item_index(current_item(curses_menu));
}
static void *item_data(void)
{
ITEM *cur;
struct mitem *mcur;
cur = current_item(curses_menu);
if (!cur)
return NULL;
mcur = (struct mitem *) item_userptr(cur);
return mcur->usrptr;
}
static int item_is_tag(char tag)
{
return item_tag() == tag;
}
static char filename[PATH_MAX+1];
static char menu_backtitle[PATH_MAX+128];
static const char *set_config_filename(const char *config_filename)
{
int size;
size = snprintf(menu_backtitle, sizeof(menu_backtitle),
"%s - %s", config_filename, rootmenu.prompt->text);
if (size >= sizeof(menu_backtitle))
menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
size = snprintf(filename, sizeof(filename), "%s", config_filename);
if (size >= sizeof(filename))
filename[sizeof(filename)-1] = '\0';
return menu_backtitle;
}
/* return = 0 means we are successful.
* -1 means go on doing what you were doing
*/
static int do_exit(void)
{
int res;
if (!conf_get_changed()) {
global_exit = 1;
return 0;
}
res = btn_dialog(main_window,
_("Do you wish to save your new configuration?\n"
"<ESC> to cancel and resume nconfig."),
2,
" <save> ",
"<don't save>");
if (res == KEY_EXIT) {
global_exit = 0;
return -1;
}
/* if we got here, the user really wants to exit */
switch (res) {
case 0:
res = conf_write(filename);
if (res)
btn_dialog(
main_window,
_("Error during writing of configuration.\n"
"Your configuration changes were NOT saved."),
1,
"<OK>");
break;
default:
btn_dialog(
main_window,
_("Your configuration changes were NOT saved."),
1,
"<OK>");
break;
}
global_exit = 1;
return 0;
}
static void search_conf(void)
{
struct symbol **sym_arr;
struct gstr res;
struct gstr title;
char *dialog_input;
int dres;
title = str_new();
str_printf( &title, _("Enter (sub)string or regexp to search for "
"(with or without \"%s\")"), CONFIG_);
again:
dres = dialog_inputbox(main_window,
_("Search Configuration Parameter"),
str_get(&title),
"", &dialog_input_result, &dialog_input_result_len);
switch (dres) {
case 0:
break;
case 1:
show_scroll_win(main_window,
_("Search Configuration"), search_help);
goto again;
default:
str_free(&title);
return;
}
/* strip the prefix if necessary */
dialog_input = dialog_input_result;
if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
dialog_input += strlen(CONFIG_);
sym_arr = sym_re_search(dialog_input);
res = get_relations_str(sym_arr, NULL);
free(sym_arr);
show_scroll_win(main_window,
_("Search Results"), str_get(&res));
str_free(&res);
str_free(&title);
}
static void build_conf(struct menu *menu)
{
struct symbol *sym;
struct property *prop;
struct menu *child;
int type, tmp, doint = 2;
tristate val;
char ch;
if (!menu || (!show_all_items && !menu_is_visible(menu)))
return;
sym = menu->sym;
prop = menu->prompt;
if (!sym) {
if (prop && menu != current_menu) {
const char *prompt = menu_get_prompt(menu);
enum prop_type ptype;
ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
switch (ptype) {
case P_MENU:
child_count++;
prompt = _(prompt);
if (single_menu_mode) {
item_make(menu, 'm',
"%s%*c%s",
menu->data ? "-->" : "++>",
indent + 1, ' ', prompt);
} else
item_make(menu, 'm',
" %*c%s %s",
indent + 1, ' ', prompt,
menu_is_empty(menu) ? "----" : "--->");
if (single_menu_mode && menu->data)
goto conf_childs;
return;
case P_COMMENT:
if (prompt) {
child_count++;
item_make(menu, ':',
" %*c*** %s ***",
indent + 1, ' ',
_(prompt));
}
break;
default:
if (prompt) {
child_count++;
item_make(menu, ':', "---%*c%s",
indent + 1, ' ',
_(prompt));
}
}
} else
doint = 0;
goto conf_childs;
}
type = sym_get_type(sym);
if (sym_is_choice(sym)) {
struct symbol *def_sym = sym_get_choice_value(sym);
struct menu *def_menu = NULL;
child_count++;
for (child = menu->list; child; child = child->next) {
if (menu_is_visible(child) && child->sym == def_sym)
def_menu = child;
}
val = sym_get_tristate_value(sym);
if (sym_is_changable(sym)) {
switch (type) {
case S_BOOLEAN:
item_make(menu, 't', "[%c]",
val == no ? ' ' : '*');
break;
case S_TRISTATE:
switch (val) {
case yes:
ch = '*';
break;
case mod:
ch = 'M';
break;
default:
ch = ' ';
break;
}
item_make(menu, 't', "<%c>", ch);
break;
}
} else {
item_make(menu, def_menu ? 't' : ':', " ");
}
item_add_str("%*c%s", indent + 1,
' ', _(menu_get_prompt(menu)));
if (val == yes) {
if (def_menu) {
item_add_str(" (%s)",
_(menu_get_prompt(def_menu)));
item_add_str(" --->");
if (def_menu->list) {
indent += 2;
build_conf(def_menu);
indent -= 2;
}
}
return;
}
} else {
if (menu == current_menu) {
item_make(menu, ':',
"---%*c%s", indent + 1,
' ', _(menu_get_prompt(menu)));
goto conf_childs;
}
child_count++;
val = sym_get_tristate_value(sym);
if (sym_is_choice_value(sym) && val == yes) {
item_make(menu, ':', " ");
} else {
switch (type) {
case S_BOOLEAN:
if (sym_is_changable(sym))
item_make(menu, 't', "[%c]",
val == no ? ' ' : '*');
else
item_make(menu, 't', "-%c-",
val == no ? ' ' : '*');
break;
case S_TRISTATE:
switch (val) {
case yes:
ch = '*';
break;
case mod:
ch = 'M';
break;
default:
ch = ' ';
break;
}
if (sym_is_changable(sym)) {
if (sym->rev_dep.tri == mod)
item_make(menu,
't', "{%c}", ch);
else
item_make(menu,
't', "<%c>", ch);
} else
item_make(menu, 't', "-%c-", ch);
break;
default:
tmp = 2 + strlen(sym_get_string_value(sym));
item_make(menu, 's', " (%s)",
sym_get_string_value(sym));
tmp = indent - tmp + 4;
if (tmp < 0)
tmp = 0;
item_add_str("%*c%s%s", tmp, ' ',
_(menu_get_prompt(menu)),
(sym_has_value(sym) ||
!sym_is_changable(sym)) ? "" :
_(" (NEW)"));
goto conf_childs;
}
}
item_add_str("%*c%s%s", indent + 1, ' ',
_(menu_get_prompt(menu)),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : _(" (NEW)"));
if (menu->prompt && menu->prompt->type == P_MENU) {
item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
return;
}
}
conf_childs:
indent += doint;
for (child = menu->list; child; child = child->next)
build_conf(child);
indent -= doint;
}
static void reset_menu(void)
{
unpost_menu(curses_menu);
clean_items();
}
/* adjust the menu to show this item.
* prefer not to scroll the menu if possible*/
static void center_item(int selected_index, int *last_top_row)
{
int toprow;
set_top_row(curses_menu, *last_top_row);
toprow = top_row(curses_menu);
if (selected_index < toprow ||
selected_index >= toprow+mwin_max_lines) {
toprow = max(selected_index-mwin_max_lines/2, 0);
if (toprow >= item_count(curses_menu)-mwin_max_lines)
toprow = item_count(curses_menu)-mwin_max_lines;
set_top_row(curses_menu, toprow);
}
set_current_item(curses_menu,
curses_menu_items[selected_index]);
*last_top_row = toprow;
post_menu(curses_menu);
refresh_all_windows(main_window);
}
/* this function assumes reset_menu has been called before */
static void show_menu(const char *prompt, const char *instructions,
int selected_index, int *last_top_row)
{
int maxx, maxy;
WINDOW *menu_window;
current_instructions = instructions;
clear();
(void) wattrset(main_window, attributes[NORMAL]);
print_in_middle(stdscr, 1, 0, getmaxx(stdscr),
menu_backtitle,
attributes[MAIN_HEADING]);
(void) wattrset(main_window, attributes[MAIN_MENU_BOX]);
box(main_window, 0, 0);
(void) wattrset(main_window, attributes[MAIN_MENU_HEADING]);
mvwprintw(main_window, 0, 3, " %s ", prompt);
(void) wattrset(main_window, attributes[NORMAL]);
set_menu_items(curses_menu, curses_menu_items);
/* position the menu at the middle of the screen */
scale_menu(curses_menu, &maxy, &maxx);
maxx = min(maxx, mwin_max_cols-2);
maxy = mwin_max_lines;
menu_window = derwin(main_window,
maxy,
maxx,
2,
(mwin_max_cols-maxx)/2);
keypad(menu_window, TRUE);
set_menu_win(curses_menu, menu_window);
set_menu_sub(curses_menu, menu_window);
/* must reassert this after changing items, otherwise returns to a
* default of 16
*/
set_menu_format(curses_menu, maxy, 1);
center_item(selected_index, last_top_row);
set_menu_format(curses_menu, maxy, 1);
print_function_line();
/* Post the menu */
post_menu(curses_menu);
refresh_all_windows(main_window);
}
static void adj_match_dir(match_f *match_direction)
{
if (*match_direction == FIND_NEXT_MATCH_DOWN)
*match_direction =
MATCH_TINKER_PATTERN_DOWN;
else if (*match_direction == FIND_NEXT_MATCH_UP)
*match_direction =
MATCH_TINKER_PATTERN_UP;
/* else, do no change.. */
}
struct match_state
{
int in_search;
match_f match_direction;
char pattern[256];
};
/* Return 0 means I have handled the key. In such a case, ans should hold the
* item to center, or -1 otherwise.
* Else return -1 .
*/
static int do_match(int key, struct match_state *state, int *ans)
{
char c = (char) key;
int terminate_search = 0;
*ans = -1;
if (key == '/' || (state->in_search && key == 27)) {
move(0, 0);
refresh();
clrtoeol();
state->in_search = 1-state->in_search;
bzero(state->pattern, sizeof(state->pattern));
state->match_direction = MATCH_TINKER_PATTERN_DOWN;
return 0;
} else if (!state->in_search)
return 1;
if (isalnum(c) || isgraph(c) || c == ' ') {
state->pattern[strlen(state->pattern)] = c;
state->pattern[strlen(state->pattern)] = '\0';
adj_match_dir(&state->match_direction);
*ans = get_mext_match(state->pattern,
state->match_direction);
} else if (key == KEY_DOWN) {
state->match_direction = FIND_NEXT_MATCH_DOWN;
*ans = get_mext_match(state->pattern,
state->match_direction);
} else if (key == KEY_UP) {
state->match_direction = FIND_NEXT_MATCH_UP;
*ans = get_mext_match(state->pattern,
state->match_direction);
} else if (key == KEY_BACKSPACE || key == 127) {
state->pattern[strlen(state->pattern)-1] = '\0';
adj_match_dir(&state->match_direction);
} else
terminate_search = 1;
if (terminate_search) {
state->in_search = 0;
bzero(state->pattern, sizeof(state->pattern));
move(0, 0);
refresh();
clrtoeol();
return -1;
}
return 0;
}
static void conf(struct menu *menu)
{
struct menu *submenu = 0;
const char *prompt = menu_get_prompt(menu);
struct symbol *sym;
int res;
int current_index = 0;
int last_top_row = 0;
struct match_state match_state = {
.in_search = 0,
.match_direction = MATCH_TINKER_PATTERN_DOWN,
.pattern = "",
};
while (!global_exit) {
reset_menu();
current_menu = menu;
build_conf(menu);
if (!child_count)
break;
show_menu(prompt ? _(prompt) : _("Main Menu"),
_(menu_instructions),
current_index, &last_top_row);
keypad((menu_win(curses_menu)), TRUE);
while (!global_exit) {
if (match_state.in_search) {
mvprintw(0, 0,
"searching: %s", match_state.pattern);
clrtoeol();
}
refresh_all_windows(main_window);
res = wgetch(menu_win(curses_menu));
if (!res)
break;
if (do_match(res, &match_state, &current_index) == 0) {
if (current_index != -1)
center_item(current_index,
&last_top_row);
continue;
}
if (process_special_keys(&res,
(struct menu *) item_data()))
break;
switch (res) {
case KEY_DOWN:
menu_driver(curses_menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(curses_menu, REQ_UP_ITEM);
break;
case KEY_NPAGE:
menu_driver(curses_menu, REQ_SCR_DPAGE);
break;
case KEY_PPAGE:
menu_driver(curses_menu, REQ_SCR_UPAGE);
break;
case KEY_HOME:
menu_driver(curses_menu, REQ_FIRST_ITEM);
break;
case KEY_END:
menu_driver(curses_menu, REQ_LAST_ITEM);
break;
case 'h':
case '?':
show_help((struct menu *) item_data());
break;
}
if (res == 10 || res == 27 ||
res == 32 || res == 'n' || res == 'y' ||
res == KEY_LEFT || res == KEY_RIGHT ||
res == 'm')
break;
refresh_all_windows(main_window);
}
refresh_all_windows(main_window);
/* if ESC or left*/
if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
break;
/* remember location in the menu */
last_top_row = top_row(curses_menu);
current_index = curses_item_index();
if (!item_tag())
continue;
submenu = (struct menu *) item_data();
if (!submenu || !menu_is_visible(submenu))
continue;
sym = submenu->sym;
switch (res) {
case ' ':
if (item_is_tag('t'))
sym_toggle_tristate_value(sym);
else if (item_is_tag('m'))
conf(submenu);
break;
case KEY_RIGHT:
case 10: /* ENTER WAS PRESSED */
switch (item_tag()) {
case 'm':
if (single_menu_mode)
submenu->data =
(void *) (long) !submenu->data;
else
conf(submenu);
break;
case 't':
if (sym_is_choice(sym) &&
sym_get_tristate_value(sym) == yes)
conf_choice(submenu);
else if (submenu->prompt &&
submenu->prompt->type == P_MENU)
conf(submenu);
else if (res == 10)
sym_toggle_tristate_value(sym);
break;
case 's':
conf_string(submenu);
break;
}
break;
case 'y':
if (item_is_tag('t')) {
if (sym_set_tristate_value(sym, yes))
break;
if (sym_set_tristate_value(sym, mod))
btn_dialog(main_window, setmod_text, 0);
}
break;
case 'n':
if (item_is_tag('t'))
sym_set_tristate_value(sym, no);
break;
case 'm':
if (item_is_tag('t'))
sym_set_tristate_value(sym, mod);
break;
}
}
}
static void conf_message_callback(const char *fmt, va_list ap)
{
char buf[1024];
vsnprintf(buf, sizeof(buf), fmt, ap);
btn_dialog(main_window, buf, 1, "<OK>");
}
static void show_help(struct menu *menu)
{
struct gstr help;
if (!menu)
return;
help = str_new();
menu_get_ext_help(menu, &help);
show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
str_free(&help);
}
static void conf_choice(struct menu *menu)
{
const char *prompt = _(menu_get_prompt(menu));
struct menu *child = 0;
struct symbol *active;
int selected_index = 0;
int last_top_row = 0;
int res, i = 0;
struct match_state match_state = {
.in_search = 0,
.match_direction = MATCH_TINKER_PATTERN_DOWN,
.pattern = "",
};
active = sym_get_choice_value(menu->sym);
/* this is mostly duplicated from the conf() function. */
while (!global_exit) {
reset_menu();
for (i = 0, child = menu->list; child; child = child->next) {
if (!show_all_items && !menu_is_visible(child))
continue;
if (child->sym == sym_get_choice_value(menu->sym))
item_make(child, ':', "<X> %s",
_(menu_get_prompt(child)));
else if (child->sym)
item_make(child, ':', " %s",
_(menu_get_prompt(child)));
else
item_make(child, ':', "*** %s ***",
_(menu_get_prompt(child)));
if (child->sym == active){
last_top_row = top_row(curses_menu);
selected_index = i;
}
i++;
}
show_menu(prompt ? _(prompt) : _("Choice Menu"),
_(radiolist_instructions),
selected_index,
&last_top_row);
while (!global_exit) {
if (match_state.in_search) {
mvprintw(0, 0, "searching: %s",
match_state.pattern);
clrtoeol();
}
refresh_all_windows(main_window);
res = wgetch(menu_win(curses_menu));
if (!res)
break;
if (do_match(res, &match_state, &selected_index) == 0) {
if (selected_index != -1)
center_item(selected_index,
&last_top_row);
continue;
}
if (process_special_keys(
&res,
(struct menu *) item_data()))
break;
switch (res) {
case KEY_DOWN:
menu_driver(curses_menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(curses_menu, REQ_UP_ITEM);
break;
case KEY_NPAGE:
menu_driver(curses_menu, REQ_SCR_DPAGE);
break;
case KEY_PPAGE:
menu_driver(curses_menu, REQ_SCR_UPAGE);
break;
case KEY_HOME:
menu_driver(curses_menu, REQ_FIRST_ITEM);
break;
case KEY_END:
menu_driver(curses_menu, REQ_LAST_ITEM);
break;
case 'h':
case '?':
show_help((struct menu *) item_data());
break;
}
if (res == 10 || res == 27 || res == ' ' ||
res == KEY_LEFT){
break;
}
refresh_all_windows(main_window);
}
/* if ESC or left */
if (res == 27 || res == KEY_LEFT)
break;
child = item_data();
if (!child || !menu_is_visible(child) || !child->sym)
continue;
switch (res) {
case ' ':
case 10:
case KEY_RIGHT:
sym_set_tristate_value(child->sym, yes);
return;
case 'h':
case '?':
show_help(child);
active = child->sym;
break;
case KEY_EXIT:
return;
}
}
}
static void conf_string(struct menu *menu)
{
const char *prompt = menu_get_prompt(menu);
while (1) {
int res;
const char *heading;
switch (sym_get_type(menu->sym)) {
case S_INT:
heading = _(inputbox_instructions_int);
break;
case S_HEX:
heading = _(inputbox_instructions_hex);
break;
case S_STRING:
heading = _(inputbox_instructions_string);
break;
default:
heading = _("Internal nconf error!");
}
res = dialog_inputbox(main_window,
prompt ? _(prompt) : _("Main Menu"),
heading,
sym_get_string_value(menu->sym),
&dialog_input_result,
&dialog_input_result_len);
switch (res) {
case 0:
if (sym_set_string_value(menu->sym,
dialog_input_result))
return;
btn_dialog(main_window,
_("You have made an invalid entry."), 0);
break;
case 1:
show_help(menu);
break;
case KEY_EXIT:
return;
}
}
}
static void conf_load(void)
{
while (1) {
int res;
res = dialog_inputbox(main_window,
NULL, load_config_text,
filename,
&dialog_input_result,
&dialog_input_result_len);
switch (res) {
case 0:
if (!dialog_input_result[0])
return;
if (!conf_read(dialog_input_result)) {
set_config_filename(dialog_input_result);
sym_set_change_count(1);
return;
}
btn_dialog(main_window, _("File does not exist!"), 0);
break;
case 1:
show_scroll_win(main_window,
_("Load Alternate Configuration"),
load_config_help);
break;
case KEY_EXIT:
return;
}
}
}
static void conf_save(void)
{
while (1) {
int res;
res = dialog_inputbox(main_window,
NULL, save_config_text,
filename,
&dialog_input_result,
&dialog_input_result_len);
switch (res) {
case 0:
if (!dialog_input_result[0])
return;
res = conf_write(dialog_input_result);
if (!res) {
set_config_filename(dialog_input_result);
return;
}
btn_dialog(main_window, _("Can't create file! "
"Probably a nonexistent directory."),
1, "<OK>");
break;
case 1:
show_scroll_win(main_window,
_("Save Alternate Configuration"),
save_config_help);
break;
case KEY_EXIT:
return;
}
}
}
void setup_windows(void)
{
int lines, columns;
getmaxyx(stdscr, lines, columns);
if (main_window != NULL)
delwin(main_window);
/* set up the menu and menu window */
main_window = newwin(lines-2, columns-2, 2, 1);
keypad(main_window, TRUE);
mwin_max_lines = lines-7;
mwin_max_cols = columns-6;
/* panels order is from bottom to top */
new_panel(main_window);
}
int main(int ac, char **av)
{
int lines, columns;
char *mode;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
if (ac > 1 && strcmp(av[1], "-s") == 0) {
/* Silence conf_read() until the real callback is set up */
conf_set_message_callback(NULL);
av++;
}
conf_parse(av[1]);
conf_read(NULL);
mode = getenv("NCONFIG_MODE");
if (mode) {
if (!strcasecmp(mode, "single_menu"))
single_menu_mode = 1;
}
/* Initialize curses */
initscr();
/* set color theme */
set_colors();
cbreak();
noecho();
keypad(stdscr, TRUE);
curs_set(0);
getmaxyx(stdscr, lines, columns);
if (columns < 75 || lines < 20) {
endwin();
printf("Your terminal should have at "
"least 20 lines and 75 columns\n");
return 1;
}
notimeout(stdscr, FALSE);
#if NCURSES_REENTRANT
set_escdelay(1);
#else
ESCDELAY = 1;
#endif
/* set btns menu */
curses_menu = new_menu(curses_menu_items);
menu_opts_off(curses_menu, O_SHOWDESC);
menu_opts_on(curses_menu, O_SHOWMATCH);
menu_opts_on(curses_menu, O_ONEVALUE);
menu_opts_on(curses_menu, O_NONCYCLIC);
menu_opts_on(curses_menu, O_IGNORECASE);
set_menu_mark(curses_menu, " ");
set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);
set_config_filename(conf_get_configname());
setup_windows();
/* check for KEY_FUNC(1) */
if (has_key(KEY_F(1)) == FALSE) {
show_scroll_win(main_window,
_("Instructions"),
_(menu_no_f_instructions));
}
conf_set_message_callback(conf_message_callback);
/* do the work */
while (!global_exit) {
conf(&rootmenu);
if (!global_exit && do_exit() == 0)
break;
}
/* ok, we are done */
unpost_menu(curses_menu);
free_menu(curses_menu);
delwin(main_window);
clear();
refresh();
endwin();
return 0;
}
/*
* Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
* Released under the terms of the GNU GPL v2.0.
*
* Derived from menuconfig.
*
*/
#include "nconf.h"
/* a list of all the different widgets we use */
attributes_t attributes[ATTR_MAX+1] = {0};
/* available colors:
COLOR_BLACK 0
COLOR_RED 1
COLOR_GREEN 2
COLOR_YELLOW 3
COLOR_BLUE 4
COLOR_MAGENTA 5
COLOR_CYAN 6
COLOR_WHITE 7
*/
static void set_normal_colors(void)
{
init_pair(NORMAL, -1, -1);
init_pair(MAIN_HEADING, COLOR_MAGENTA, -1);
/* FORE is for the selected item */
init_pair(MAIN_MENU_FORE, -1, -1);
/* BACK for all the rest */
init_pair(MAIN_MENU_BACK, -1, -1);
init_pair(MAIN_MENU_GREY, -1, -1);
init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);
init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);
init_pair(SCROLLWIN_TEXT, -1, -1);
init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);
init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);
init_pair(DIALOG_TEXT, -1, -1);
init_pair(DIALOG_BOX, COLOR_YELLOW, -1);
init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);
init_pair(DIALOG_MENU_FORE, COLOR_RED, -1);
init_pair(INPUT_BOX, COLOR_YELLOW, -1);
init_pair(INPUT_HEADING, COLOR_GREEN, -1);
init_pair(INPUT_TEXT, -1, -1);
init_pair(INPUT_FIELD, -1, -1);
init_pair(FUNCTION_HIGHLIGHT, -1, -1);
init_pair(FUNCTION_TEXT, COLOR_YELLOW, -1);
}
/* available attributes:
A_NORMAL Normal display (no highlight)
A_STANDOUT Best highlighting mode of the terminal.
A_UNDERLINE Underlining
A_REVERSE Reverse video
A_BLINK Blinking
A_DIM Half bright
A_BOLD Extra bright or bold
A_PROTECT Protected mode
A_INVIS Invisible or blank mode
A_ALTCHARSET Alternate character set
A_CHARTEXT Bit-mask to extract a character
COLOR_PAIR(n) Color-pair number n
*/
static void normal_color_theme(void)
{
/* automatically add color... */
#define mkattr(name, attr) do { \
attributes[name] = attr | COLOR_PAIR(name); } while (0)
mkattr(NORMAL, NORMAL);
mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);
mkattr(MAIN_MENU_FORE, A_REVERSE);
mkattr(MAIN_MENU_BACK, A_NORMAL);
mkattr(MAIN_MENU_GREY, A_NORMAL);
mkattr(MAIN_MENU_HEADING, A_BOLD);
mkattr(MAIN_MENU_BOX, A_NORMAL);
mkattr(SCROLLWIN_TEXT, A_NORMAL);
mkattr(SCROLLWIN_HEADING, A_BOLD);
mkattr(SCROLLWIN_BOX, A_BOLD);
mkattr(DIALOG_TEXT, A_BOLD);
mkattr(DIALOG_BOX, A_BOLD);
mkattr(DIALOG_MENU_FORE, A_STANDOUT);
mkattr(DIALOG_MENU_BACK, A_NORMAL);
mkattr(INPUT_BOX, A_NORMAL);
mkattr(INPUT_HEADING, A_BOLD);
mkattr(INPUT_TEXT, A_NORMAL);
mkattr(INPUT_FIELD, A_UNDERLINE);
mkattr(FUNCTION_HIGHLIGHT, A_BOLD);
mkattr(FUNCTION_TEXT, A_REVERSE);
}
static void no_colors_theme(void)
{
/* automatically add highlight, no color */
#define mkattrn(name, attr) { attributes[name] = attr; }
mkattrn(NORMAL, NORMAL);
mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);
mkattrn(MAIN_MENU_FORE, A_STANDOUT);
mkattrn(MAIN_MENU_BACK, A_NORMAL);
mkattrn(MAIN_MENU_GREY, A_NORMAL);
mkattrn(MAIN_MENU_HEADING, A_BOLD);
mkattrn(MAIN_MENU_BOX, A_NORMAL);
mkattrn(SCROLLWIN_TEXT, A_NORMAL);
mkattrn(SCROLLWIN_HEADING, A_BOLD);
mkattrn(SCROLLWIN_BOX, A_BOLD);
mkattrn(DIALOG_TEXT, A_NORMAL);
mkattrn(DIALOG_BOX, A_BOLD);
mkattrn(DIALOG_MENU_FORE, A_STANDOUT);
mkattrn(DIALOG_MENU_BACK, A_NORMAL);
mkattrn(INPUT_BOX, A_BOLD);
mkattrn(INPUT_HEADING, A_BOLD);
mkattrn(INPUT_TEXT, A_NORMAL);
mkattrn(INPUT_FIELD, A_UNDERLINE);
mkattrn(FUNCTION_HIGHLIGHT, A_BOLD);
mkattrn(FUNCTION_TEXT, A_REVERSE);
}
void set_colors()
{
start_color();
use_default_colors();
set_normal_colors();
if (has_colors()) {
normal_color_theme();
} else {
/* give defaults */
no_colors_theme();
}
}
/* this changes the windows attributes !!! */
void print_in_middle(WINDOW *win,
int starty,
int startx,
int width,
const char *string,
chtype color)
{ int length, x, y;
float temp;
if (win == NULL)
win = stdscr;
getyx(win, y, x);
if (startx != 0)
x = startx;
if (starty != 0)
y = starty;
if (width == 0)
width = 80;
length = strlen(string);
temp = (width - length) / 2;
x = startx + (int)temp;
(void) wattrset(win, color);
mvwprintw(win, y, x, "%s", string);
refresh();
}
int get_line_no(const char *text)
{
int i;
int total = 1;
if (!text)
return 0;
for (i = 0; text[i] != '\0'; i++)
if (text[i] == '\n')
total++;
return total;
}
const char *get_line(const char *text, int line_no)
{
int i;
int lines = 0;
if (!text)
return 0;
for (i = 0; text[i] != '\0' && lines < line_no; i++)
if (text[i] == '\n')
lines++;
return text+i;
}
int get_line_length(const char *line)
{
int res = 0;
while (*line != '\0' && *line != '\n') {
line++;
res++;
}
return res;
}
/* print all lines to the window. */
void fill_window(WINDOW *win, const char *text)
{
int x, y;
int total_lines = get_line_no(text);
int i;
getmaxyx(win, y, x);
/* do not go over end of line */
total_lines = min(total_lines, y);
for (i = 0; i < total_lines; i++) {
char tmp[x+10];
const char *line = get_line(text, i);
int len = get_line_length(line);
strncpy(tmp, line, min(len, x));
tmp[len] = '\0';
mvwprintw(win, i, 0, "%s", tmp);
}
}
/* get the message, and buttons.
* each button must be a char*
* return the selected button
*
* this dialog is used for 2 different things:
* 1) show a text box, no buttons.
* 2) show a dialog, with horizontal buttons
*/
int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
{
va_list ap;
char *btn;
int btns_width = 0;
int msg_lines = 0;
int msg_width = 0;
int total_width;
int win_rows = 0;
WINDOW *win;
WINDOW *msg_win;
WINDOW *menu_win;
MENU *menu;
ITEM *btns[btn_num+1];
int i, x, y;
int res = -1;
va_start(ap, btn_num);
for (i = 0; i < btn_num; i++) {
btn = va_arg(ap, char *);
btns[i] = new_item(btn, "");
btns_width += strlen(btn)+1;
}
va_end(ap);
btns[btn_num] = NULL;
/* find the widest line of msg: */
msg_lines = get_line_no(msg);
for (i = 0; i < msg_lines; i++) {
const char *line = get_line(msg, i);
int len = get_line_length(line);
if (msg_width < len)
msg_width = len;
}
total_width = max(msg_width, btns_width);
/* place dialog in middle of screen */
y = (getmaxy(stdscr)-(msg_lines+4))/2;
x = (getmaxx(stdscr)-(total_width+4))/2;
/* create the windows */
if (btn_num > 0)
win_rows = msg_lines+4;
else
win_rows = msg_lines+2;
win = newwin(win_rows, total_width+4, y, x);
keypad(win, TRUE);
menu_win = derwin(win, 1, btns_width, win_rows-2,
1+(total_width+2-btns_width)/2);
menu = new_menu(btns);
msg_win = derwin(win, win_rows-2, msg_width, 1,
1+(total_width+2-msg_width)/2);
set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
(void) wattrset(win, attributes[DIALOG_BOX]);
box(win, 0, 0);
/* print message */
(void) wattrset(msg_win, attributes[DIALOG_TEXT]);
fill_window(msg_win, msg);
set_menu_win(menu, win);
set_menu_sub(menu, menu_win);
set_menu_format(menu, 1, btn_num);
menu_opts_off(menu, O_SHOWDESC);
menu_opts_off(menu, O_SHOWMATCH);
menu_opts_on(menu, O_ONEVALUE);
menu_opts_on(menu, O_NONCYCLIC);
set_menu_mark(menu, "");
post_menu(menu);
touchwin(win);
refresh_all_windows(main_window);
while ((res = wgetch(win))) {
switch (res) {
case KEY_LEFT:
menu_driver(menu, REQ_LEFT_ITEM);
break;
case KEY_RIGHT:
menu_driver(menu, REQ_RIGHT_ITEM);
break;
case 10: /* ENTER */
case 27: /* ESCAPE */
case ' ':
case KEY_F(F_BACK):
case KEY_F(F_EXIT):
break;
}
touchwin(win);
refresh_all_windows(main_window);
if (res == 10 || res == ' ') {
res = item_index(current_item(menu));
break;
} else if (res == 27 || res == KEY_F(F_BACK) ||
res == KEY_F(F_EXIT)) {
res = KEY_EXIT;
break;
}
}
unpost_menu(menu);
free_menu(menu);
for (i = 0; i < btn_num; i++)
free_item(btns[i]);
delwin(win);
return res;
}
int dialog_inputbox(WINDOW *main_window,
const char *title, const char *prompt,
const char *init, char **resultp, int *result_len)
{
int prompt_lines = 0;
int prompt_width = 0;
WINDOW *win;
WINDOW *prompt_win;
WINDOW *form_win;
PANEL *panel;
int i, x, y;
int res = -1;
int cursor_position = strlen(init);
int cursor_form_win;
char *result = *resultp;
if (strlen(init)+1 > *result_len) {
*result_len = strlen(init)+1;
*resultp = result = realloc(result, *result_len);
}
/* find the widest line of msg: */
prompt_lines = get_line_no(prompt);
for (i = 0; i < prompt_lines; i++) {
const char *line = get_line(prompt, i);
int len = get_line_length(line);
prompt_width = max(prompt_width, len);
}
if (title)
prompt_width = max(prompt_width, strlen(title));
/* place dialog in middle of screen */
y = (getmaxy(stdscr)-(prompt_lines+4))/2;
x = (getmaxx(stdscr)-(prompt_width+4))/2;
strncpy(result, init, *result_len);
/* create the windows */
win = newwin(prompt_lines+6, prompt_width+7, y, x);
prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
keypad(form_win, TRUE);
(void) wattrset(form_win, attributes[INPUT_FIELD]);
(void) wattrset(win, attributes[INPUT_BOX]);
box(win, 0, 0);
(void) wattrset(win, attributes[INPUT_HEADING]);
if (title)
mvwprintw(win, 0, 3, "%s", title);
/* print message */
(void) wattrset(prompt_win, attributes[INPUT_TEXT]);
fill_window(prompt_win, prompt);
mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
cursor_form_win = min(cursor_position, prompt_width-1);
mvwprintw(form_win, 0, 0, "%s",
result + cursor_position-cursor_form_win);
/* create panels */
panel = new_panel(win);
/* show the cursor */
curs_set(1);
touchwin(win);
refresh_all_windows(main_window);
while ((res = wgetch(form_win))) {
int len = strlen(result);
switch (res) {
case 10: /* ENTER */
case 27: /* ESCAPE */
case KEY_F(F_HELP):
case KEY_F(F_EXIT):
case KEY_F(F_BACK):
break;
case 127:
case KEY_BACKSPACE:
if (cursor_position > 0) {
memmove(&result[cursor_position-1],
&result[cursor_position],
len-cursor_position+1);
cursor_position--;
cursor_form_win--;
len--;
}
break;
case KEY_DC:
if (cursor_position >= 0 && cursor_position < len) {
memmove(&result[cursor_position],
&result[cursor_position+1],
len-cursor_position+1);
len--;
}
break;
case KEY_UP:
case KEY_RIGHT:
if (cursor_position < len) {
cursor_position++;
cursor_form_win++;
}
break;
case KEY_DOWN:
case KEY_LEFT:
if (cursor_position > 0) {
cursor_position--;
cursor_form_win--;
}
break;
case KEY_HOME:
cursor_position = 0;
cursor_form_win = 0;
break;
case KEY_END:
cursor_position = len;
cursor_form_win = min(cursor_position, prompt_width-1);
break;
default:
if ((isgraph(res) || isspace(res))) {
/* one for new char, one for '\0' */
if (len+2 > *result_len) {
*result_len = len+2;
*resultp = result = realloc(result,
*result_len);
}
/* insert the char at the proper position */
memmove(&result[cursor_position+1],
&result[cursor_position],
len-cursor_position+1);
result[cursor_position] = res;
cursor_position++;
cursor_form_win++;
len++;
} else {
mvprintw(0, 0, "unknown key: %d\n", res);
}
break;
}
if (cursor_form_win < 0)
cursor_form_win = 0;
else if (cursor_form_win > prompt_width-1)
cursor_form_win = prompt_width-1;
wmove(form_win, 0, 0);
wclrtoeol(form_win);
mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
mvwprintw(form_win, 0, 0, "%s",
result + cursor_position-cursor_form_win);
wmove(form_win, 0, cursor_form_win);
touchwin(win);
refresh_all_windows(main_window);
if (res == 10) {
res = 0;
break;
} else if (res == 27 || res == KEY_F(F_BACK) ||
res == KEY_F(F_EXIT)) {
res = KEY_EXIT;
break;
} else if (res == KEY_F(F_HELP)) {
res = 1;
break;
}
}
/* hide the cursor */
curs_set(0);
del_panel(panel);
delwin(prompt_win);
delwin(form_win);
delwin(win);
return res;
}
/* refresh all windows in the correct order */
void refresh_all_windows(WINDOW *main_window)
{
update_panels();
touchwin(main_window);
refresh();
}
/* layman's scrollable window... */
void show_scroll_win(WINDOW *main_window,
const char *title,
const char *text)
{
int res;
int total_lines = get_line_no(text);
int x, y, lines, columns;
int start_x = 0, start_y = 0;
int text_lines = 0, text_cols = 0;
int total_cols = 0;
int win_cols = 0;
int win_lines = 0;
int i = 0;
WINDOW *win;
WINDOW *pad;
PANEL *panel;
getmaxyx(stdscr, lines, columns);
/* find the widest line of msg: */
total_lines = get_line_no(text);
for (i = 0; i < total_lines; i++) {
const char *line = get_line(text, i);
int len = get_line_length(line);
total_cols = max(total_cols, len+2);
}
/* create the pad */
pad = newpad(total_lines+10, total_cols+10);
(void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
fill_window(pad, text);
win_lines = min(total_lines+4, lines-2);
win_cols = min(total_cols+2, columns-2);
text_lines = max(win_lines-4, 0);
text_cols = max(win_cols-2, 0);
/* place window in middle of screen */
y = (lines-win_lines)/2;
x = (columns-win_cols)/2;
win = newwin(win_lines, win_cols, y, x);
keypad(win, TRUE);
/* show the help in the help window, and show the help panel */
(void) wattrset(win, attributes[SCROLLWIN_BOX]);
box(win, 0, 0);
(void) wattrset(win, attributes[SCROLLWIN_HEADING]);
mvwprintw(win, 0, 3, " %s ", title);
panel = new_panel(win);
/* handle scrolling */
do {
copywin(pad, win, start_y, start_x, 2, 2, text_lines,
text_cols, 0);
print_in_middle(win,
text_lines+2,
0,
text_cols,
"<OK>",
attributes[DIALOG_MENU_FORE]);
wrefresh(win);
res = wgetch(win);
switch (res) {
case KEY_NPAGE:
case ' ':
case 'd':
start_y += text_lines-2;
break;
case KEY_PPAGE:
case 'u':
start_y -= text_lines+2;
break;
case KEY_HOME:
start_y = 0;
break;
case KEY_END:
start_y = total_lines-text_lines;
break;
case KEY_DOWN:
case 'j':
start_y++;
break;
case KEY_UP:
case 'k':
start_y--;
break;
case KEY_LEFT:
case 'h':
start_x--;
break;
case KEY_RIGHT:
case 'l':
start_x++;
break;
}
if (res == 10 || res == 27 || res == 'q' ||
res == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||
res == KEY_F(F_EXIT))
break;
if (start_y < 0)
start_y = 0;
if (start_y >= total_lines-text_lines)
start_y = total_lines-text_lines;
if (start_x < 0)
start_x = 0;
if (start_x >= total_cols-text_cols)
start_x = total_cols-text_cols;
} while (res);
del_panel(panel);
delwin(win);
refresh_all_windows(main_window);
}
/*
* Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
* Released under the terms of the GNU GPL v2.0.
*
* Derived from menuconfig.
*
*/
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <locale.h>
#include <curses.h>
#include <menu.h>
#include <panel.h>
#include <form.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "ncurses.h"
#define max(a, b) ({\
typeof(a) _a = a;\
typeof(b) _b = b;\
_a > _b ? _a : _b; })
#define min(a, b) ({\
typeof(a) _a = a;\
typeof(b) _b = b;\
_a < _b ? _a : _b; })
typedef enum {
NORMAL = 1,
MAIN_HEADING,
MAIN_MENU_BOX,
MAIN_MENU_FORE,
MAIN_MENU_BACK,
MAIN_MENU_GREY,
MAIN_MENU_HEADING,
SCROLLWIN_TEXT,
SCROLLWIN_HEADING,
SCROLLWIN_BOX,
DIALOG_TEXT,
DIALOG_MENU_FORE,
DIALOG_MENU_BACK,
DIALOG_BOX,
INPUT_BOX,
INPUT_HEADING,
INPUT_TEXT,
INPUT_FIELD,
FUNCTION_TEXT,
FUNCTION_HIGHLIGHT,
ATTR_MAX
} attributes_t;
extern attributes_t attributes[];
typedef enum {
F_HELP = 1,
F_SYMBOL = 2,
F_INSTS = 3,
F_CONF = 4,
F_BACK = 5,
F_SAVE = 6,
F_LOAD = 7,
F_SEARCH = 8,
F_EXIT = 9,
} function_key;
void set_colors(void);
/* this changes the windows attributes !!! */
void print_in_middle(WINDOW *win,
int starty,
int startx,
int width,
const char *string,
chtype color);
int get_line_length(const char *line);
int get_line_no(const char *text);
const char *get_line(const char *text, int line_no);
void fill_window(WINDOW *win, const char *text);
int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...);
int dialog_inputbox(WINDOW *main_window,
const char *title, const char *prompt,
const char *init, char **resultp, int *result_len);
void refresh_all_windows(WINDOW *main_window);
void show_scroll_win(WINDOW *main_window,
const char *title,
const char *text);
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>
* Released under the terms of the GNU GPL v2.0.
*/
#include <qglobal.h>
#include <QMainWindow>
#include <QList>
#include <qtextbrowser.h>
#include <QAction>
#include <QFileDialog>
#include <QMenu>
#include <qapplication.h>
#include <qmainwindow.h>
#include <qdesktopwidget.h>
#include <qtoolbar.h>
#include <qlayout.h>
#include <qvbox.h>
#include <qsplitter.h>
#include <qlistview.h>
#include <qtextbrowser.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qmenubar.h>
#include <qmessagebox.h>
#include <qaction.h>
#include <qheader.h>
#include <qfiledialog.h>
#include <qdragobject.h>
#include <qregexp.h>
#include <qevent.h>
#include <stdlib.h>
......@@ -48,21 +51,25 @@ static inline QString qgettext(const char* str)
static inline QString qgettext(const QString& str)
{
return QString::fromLocal8Bit(gettext(str.latin1()));
return QString::fromLocal8Bit(gettext(str.toLatin1()));
}
ConfigSettings::ConfigSettings()
: QSettings("kernel.org", "qconf")
{
}
/**
* Reads a list of integer values from the application settings.
*/
QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
{
QValueList<int> result;
QStringList entryList = readListEntry(key, ok);
if (ok) {
QStringList::Iterator it;
for (it = entryList.begin(); it != entryList.end(); ++it)
result.push_back((*it).toInt());
}
QList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
{
QList<int> result;
QStringList entryList = value(key).toStringList();
QStringList::Iterator it;
for (it = entryList.begin(); it != entryList.end(); ++it)
result.push_back((*it).toInt());
return result;
}
......@@ -70,29 +77,26 @@ QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
/**
* Writes a list of integer values to the application settings.
*/
bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value)
{
QStringList stringList;
QValueList<int>::ConstIterator it;
QList<int>::ConstIterator it;
for (it = value.begin(); it != value.end(); ++it)
stringList.push_back(QString::number(*it));
return writeEntry(key, stringList);
setValue(key, stringList);
return true;
}
#if QT_VERSION >= 300
/*
* set the new data
* TODO check the value
*/
void ConfigItem::okRename(int col)
{
Parent::okRename(col);
sym_set_string_value(menu->sym, text(dataColIdx).latin1());
listView()->updateList(this);
}
#endif
/*
* update the displayed of a menu entry
......@@ -129,11 +133,11 @@ void ConfigItem::updateMenu(void)
} else {
if (sym)
break;
setPixmap(promptColIdx, 0);
setPixmap(promptColIdx, QIcon());
}
goto set_prompt;
case P_COMMENT:
setPixmap(promptColIdx, 0);
setPixmap(promptColIdx, QIcon());
goto set_prompt;
default:
;
......@@ -149,8 +153,8 @@ void ConfigItem::updateMenu(void)
case S_TRISTATE:
char ch;
if (!sym_is_changable(sym) && !list->showAll) {
setPixmap(promptColIdx, 0);
if (!sym_is_changable(sym) && list->optMode == normalOpt) {
setPixmap(promptColIdx, QIcon());
setText(noColIdx, QString::null);
setText(modColIdx, QString::null);
setText(yesColIdx, QString::null);
......@@ -196,11 +200,6 @@ void ConfigItem::updateMenu(void)
data = sym_get_string_value(sym);
#if QT_VERSION >= 300
int i = list->mapIdx(dataColIdx);
if (i >= 0)
setRenameEnabled(i, TRUE);
#endif
setText(dataColIdx, data);
if (type == S_STRING)
prompt = QString("%1: %2").arg(prompt).arg(data);
......@@ -232,18 +231,6 @@ void ConfigItem::testUpdateMenu(bool v)
updateMenu();
}
void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
{
ConfigList* list = listView();
if (visible) {
if (isSelected() && !list->hasFocus() && list->mode == menuMode)
Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
else
Parent::paintCell(p, cg, column, width, align);
} else
Parent::paintCell(p, list->disabledColorGroup, column, width, align);
}
/*
* construct a menu entry
......@@ -256,7 +243,7 @@ void ConfigItem::init(void)
menu->data = this;
if (list->mode != fullMode)
setOpen(TRUE);
setExpanded(true);
sym_calc_value(menu->sym);
}
updateMenu();
......@@ -281,7 +268,7 @@ ConfigItem::~ConfigItem(void)
ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
: Parent(parent)
{
connect(this, SIGNAL(lostFocus()), SLOT(hide()));
connect(this, SIGNAL(editingFinished()), SLOT(hide()));
}
void ConfigLineEdit::show(ConfigItem* i)
......@@ -302,7 +289,7 @@ void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
break;
case Qt::Key_Return:
case Qt::Key_Enter:
sym_set_string_value(item->menu->sym, text().latin1());
sym_set_string_value(item->menu->sym, text().toLatin1());
parent()->updateList(item);
break;
default:
......@@ -315,43 +302,54 @@ void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
}
ConfigList::ConfigList(ConfigView* p, const char *name)
: Parent(p, name),
: Parent(p),
updateAll(false),
symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
showAll(false), showName(false), showRange(false), showData(false),
showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt),
rootEntry(0), headerPopup(0)
{
int i;
setSorting(-1);
setRootIsDecorated(TRUE);
disabledColorGroup = palette().active();
disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
inactivedColorGroup = palette().active();
inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
setObjectName(name);
setSortingEnabled(false);
setRootIsDecorated(true);
connect(this, SIGNAL(selectionChanged(void)),
setVerticalScrollMode(ScrollPerPixel);
setHorizontalScrollMode(ScrollPerPixel);
setHeaderLabels(QStringList() << _("Option") << _("Name") << "N" << "M" << "Y" << _("Value"));
connect(this, SIGNAL(itemSelectionChanged(void)),
SLOT(updateSelection(void)));
if (name) {
configSettings->beginGroup(name);
showAll = configSettings->readBoolEntry("/showAll", false);
showName = configSettings->readBoolEntry("/showName", false);
showRange = configSettings->readBoolEntry("/showRange", false);
showData = configSettings->readBoolEntry("/showData", false);
showName = configSettings->value("/showName", false).toBool();
showRange = configSettings->value("/showRange", false).toBool();
showData = configSettings->value("/showData", false).toBool();
optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt();
configSettings->endGroup();
connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
}
for (i = 0; i < colNr; i++)
colMap[i] = colRevMap[i] = -1;
addColumn(promptColIdx, _("Option"));
addColumn(promptColIdx);
reinit();
}
bool ConfigList::menuSkip(struct menu *menu)
{
if (optMode == normalOpt && menu_is_visible(menu))
return false;
if (optMode == promptOpt && menu_has_prompt(menu))
return false;
if (optMode == allOpt)
return false;
return true;
}
void ConfigList::reinit(void)
{
removeColumn(dataColIdx);
......@@ -361,26 +359,26 @@ void ConfigList::reinit(void)
removeColumn(nameColIdx);
if (showName)
addColumn(nameColIdx, _("Name"));
addColumn(nameColIdx);
if (showRange) {
addColumn(noColIdx, "N");
addColumn(modColIdx, "M");
addColumn(yesColIdx, "Y");
addColumn(noColIdx);
addColumn(modColIdx);
addColumn(yesColIdx);
}
if (showData)
addColumn(dataColIdx, _("Value"));
addColumn(dataColIdx);
updateListAll();
}
void ConfigList::saveSettings(void)
{
if (name()) {
configSettings->beginGroup(name());
configSettings->writeEntry("/showName", showName);
configSettings->writeEntry("/showRange", showRange);
configSettings->writeEntry("/showData", showData);
configSettings->writeEntry("/showAll", showAll);
if (!objectName().isEmpty()) {
configSettings->beginGroup(objectName());
configSettings->setValue("/showName", showName);
configSettings->setValue("/showRange", showRange);
configSettings->setValue("/showData", showData);
configSettings->setValue("/optionMode", (int)optMode);
configSettings->endGroup();
}
}
......@@ -402,7 +400,10 @@ void ConfigList::updateSelection(void)
struct menu *menu;
enum prop_type type;
ConfigItem* item = (ConfigItem*)selectedItem();
if (selectedItems().count() == 0)
return;
ConfigItem* item = (ConfigItem*)selectedItems().first();
if (!item)
return;
......@@ -422,21 +423,23 @@ void ConfigList::updateList(ConfigItem* item)
if (!rootEntry) {
if (mode != listMode)
goto update;
QListViewItemIterator it(this);
QTreeWidgetItemIterator it(this);
ConfigItem* item;
for (; it.current(); ++it) {
item = (ConfigItem*)it.current();
while (*it) {
item = (ConfigItem*)(*it);
if (!item->menu)
continue;
item->testUpdateMenu(menu_is_visible(item->menu));
++it;
}
return;
}
if (rootEntry != &rootmenu && (mode == singleMode ||
(mode == symbolMode && rootEntry->parent != &rootmenu))) {
item = firstChild();
item = (ConfigItem *)topLevelItem(0);
if (!item)
item = new ConfigItem(this, 0, true);
last = item;
......@@ -450,12 +453,14 @@ void ConfigList::updateList(ConfigItem* item)
item->testUpdateMenu(true);
updateMenuList(item, rootEntry);
triggerUpdate();
update();
resizeColumnToContents(0);
return;
}
update:
updateMenuList(this, rootEntry);
triggerUpdate();
update();
resizeColumnToContents(0);
}
void ConfigList::setValue(ConfigItem* item, tristate val)
......@@ -477,7 +482,7 @@ void ConfigList::setValue(ConfigItem* item, tristate val)
if (!sym_set_tristate_value(sym, val))
return;
if (oldval == no && item->menu->list)
item->setOpen(TRUE);
item->setExpanded(true);
parent()->updateList(item);
break;
}
......@@ -495,7 +500,7 @@ void ConfigList::changeValue(ConfigItem* item)
sym = menu->sym;
if (!sym) {
if (item->menu->list)
item->setOpen(!item->isOpen());
item->setExpanded(!item->isExpanded());
return;
}
......@@ -507,9 +512,9 @@ void ConfigList::changeValue(ConfigItem* item)
newexpr = sym_toggle_tristate_value(sym);
if (item->menu->list) {
if (oldexpr == newexpr)
item->setOpen(!item->isOpen());
item->setExpanded(!item->isExpanded());
else if (oldexpr == no)
item->setOpen(TRUE);
item->setExpanded(true);
}
if (oldexpr != newexpr)
parent()->updateList(item);
......@@ -517,12 +522,7 @@ void ConfigList::changeValue(ConfigItem* item)
case S_INT:
case S_HEX:
case S_STRING:
#if QT_VERSION >= 300
if (colMap[dataColIdx] >= 0)
item->startRename(colMap[dataColIdx]);
else
#endif
parent()->lineEdit->show(item);
parent()->lineEdit->show(item);
break;
}
}
......@@ -539,8 +539,10 @@ void ConfigList::setRootMenu(struct menu *menu)
updateMenuList(this, 0);
rootEntry = menu;
updateListAll();
setSelected(currentItem(), hasFocus());
ensureItemVisible(currentItem());
if (currentItem()) {
currentItem()->setSelected(hasFocus());
scrollToItem(currentItem());
}
}
void ConfigList::setParentMenu(void)
......@@ -553,13 +555,16 @@ void ConfigList::setParentMenu(void)
return;
setRootMenu(menu_get_parent_menu(rootEntry->parent));
QListViewItemIterator it(this);
for (; (item = (ConfigItem*)it.current()); it++) {
QTreeWidgetItemIterator it(this);
while (*it) {
item = (ConfigItem *)(*it);
if (item->menu == oldroot) {
setCurrentItem(item);
ensureItemVisible(item);
scrollToItem(item);
break;
}
++it;
}
}
......@@ -570,8 +575,7 @@ void ConfigList::setParentMenu(void)
* parent: either the menu list widget or a menu entry widget
* menu: entry to be updated
*/
template <class P>
void ConfigList::updateMenuList(P* parent, struct menu* menu)
void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
{
struct menu* child;
ConfigItem* item;
......@@ -580,8 +584,11 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
enum prop_type type;
if (!menu) {
while ((item = parent->firstChild()))
delete item;
while (parent->childCount() > 0)
{
delete parent->takeChild(0);
}
return;
}
......@@ -606,7 +613,7 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
}
visible = menu_is_visible(child);
if (showAll || visible) {
if (!menuSkip(child)) {
if (!child->sym && !child->list && !child->prompt)
continue;
if (!item || item->menu != child)
......@@ -633,9 +640,74 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
}
}
void ConfigList::updateMenuList(ConfigList *parent, struct menu* menu)
{
struct menu* child;
ConfigItem* item;
ConfigItem* last;
bool visible;
enum prop_type type;
if (!menu) {
while (parent->topLevelItemCount() > 0)
{
delete parent->takeTopLevelItem(0);
}
return;
}
last = (ConfigItem*)parent->topLevelItem(0);
if (last && !last->goParent)
last = 0;
for (child = menu->list; child; child = child->next) {
item = last ? last->nextSibling() : (ConfigItem*)parent->topLevelItem(0);
type = child->prompt ? child->prompt->type : P_UNKNOWN;
switch (mode) {
case menuMode:
if (!(child->flags & MENU_ROOT))
goto hide;
break;
case symbolMode:
if (child->flags & MENU_ROOT)
goto hide;
break;
default:
break;
}
visible = menu_is_visible(child);
if (!menuSkip(child)) {
if (!child->sym && !child->list && !child->prompt)
continue;
if (!item || item->menu != child)
item = new ConfigItem(parent, last, child, visible);
else
item->testUpdateMenu(visible);
if (mode == fullMode || mode == menuMode || type != P_MENU)
updateMenuList(item, child);
else
updateMenuList(item, 0);
last = item;
continue;
}
hide:
if (item && item->menu == child) {
last = (ConfigItem*)parent->topLevelItem(0);
if (last == item)
last = 0;
else while (last->nextSibling() != item)
last = last->nextSibling();
delete item;
}
}
}
void ConfigList::keyPressEvent(QKeyEvent* ev)
{
QListViewItem* i = currentItem();
QTreeWidgetItem* i = currentItem();
ConfigItem* item;
struct menu *menu;
enum prop_type type;
......@@ -687,20 +759,20 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
ev->accept();
}
void ConfigList::contentsMousePressEvent(QMouseEvent* e)
void ConfigList::mousePressEvent(QMouseEvent* e)
{
//QPoint p(contentsToViewport(e->pos()));
//printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
Parent::contentsMousePressEvent(e);
Parent::mousePressEvent(e);
}
void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
void ConfigList::mouseReleaseEvent(QMouseEvent* e)
{
QPoint p(contentsToViewport(e->pos()));
QPoint p = e->pos();
ConfigItem* item = (ConfigItem*)itemAt(p);
struct menu *menu;
enum prop_type ptype;
const QPixmap* pm;
QIcon icon;
int idx, x;
if (!item)
......@@ -708,14 +780,13 @@ void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
menu = item->menu;
x = header()->offset() + p.x();
idx = colRevMap[header()->sectionAt(x)];
idx = header()->logicalIndexAt(x);
switch (idx) {
case promptColIdx:
pm = item->pixmap(promptColIdx);
if (pm) {
int off = header()->sectionPos(0) + itemMargin() +
treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
if (x >= off && x < off + pm->width()) {
icon = item->pixmap(promptColIdx);
if (!icon.isNull()) {
int off = header()->sectionPosition(0) + visualRect(indexAt(p)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly.
if (x >= off && x < off + icon.availableSizes().first().width()) {
if (item->goParent) {
emit parentSelected();
break;
......@@ -746,19 +817,19 @@ void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
skip:
//printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
Parent::contentsMouseReleaseEvent(e);
Parent::mouseReleaseEvent(e);
}
void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
void ConfigList::mouseMoveEvent(QMouseEvent* e)
{
//QPoint p(contentsToViewport(e->pos()));
//printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
Parent::contentsMouseMoveEvent(e);
Parent::mouseMoveEvent(e);
}
void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
{
QPoint p(contentsToViewport(e->pos()));
QPoint p = e->pos(); // TODO: Check if this works(was contentsToViewport).
ConfigItem* item = (ConfigItem*)itemAt(p);
struct menu *menu;
enum prop_type ptype;
......@@ -780,7 +851,7 @@ void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
skip:
//printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
Parent::contentsMouseDoubleClickEvent(e);
Parent::mouseDoubleClickEvent(e);
}
void ConfigList::focusInEvent(QFocusEvent *e)
......@@ -791,7 +862,7 @@ void ConfigList::focusInEvent(QFocusEvent *e)
ConfigItem* item = (ConfigItem *)currentItem();
if (item) {
setSelected(item, TRUE);
item->setSelected(true);
menu = item->menu;
}
emit gotFocus(menu);
......@@ -803,31 +874,31 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
if (!headerPopup) {
QAction *action;
headerPopup = new QPopupMenu(this);
action = new QAction(NULL, _("Show Name"), 0, this);
action->setToggleAction(TRUE);
headerPopup = new QMenu(this);
action = new QAction(_("Show Name"), this);
action->setCheckable(true);
connect(action, SIGNAL(toggled(bool)),
parent(), SLOT(setShowName(bool)));
connect(parent(), SIGNAL(showNameChanged(bool)),
action, SLOT(setOn(bool)));
action->setOn(showName);
action->addTo(headerPopup);
action = new QAction(NULL, _("Show Range"), 0, this);
action->setToggleAction(TRUE);
action->setChecked(showName);
headerPopup->addAction(action);
action = new QAction(_("Show Range"), this);
action->setCheckable(true);
connect(action, SIGNAL(toggled(bool)),
parent(), SLOT(setShowRange(bool)));
connect(parent(), SIGNAL(showRangeChanged(bool)),
action, SLOT(setOn(bool)));
action->setOn(showRange);
action->addTo(headerPopup);
action = new QAction(NULL, _("Show Data"), 0, this);
action->setToggleAction(TRUE);
action->setChecked(showRange);
headerPopup->addAction(action);
action = new QAction(_("Show Data"), this);
action->setCheckable(true);
connect(action, SIGNAL(toggled(bool)),
parent(), SLOT(setShowData(bool)));
connect(parent(), SIGNAL(showDataChanged(bool)),
action, SLOT(setOn(bool)));
action->setOn(showData);
action->addTo(headerPopup);
action->setChecked(showData);
headerPopup->addAction(action);
}
headerPopup->exec(e->globalPos());
e->accept();
......@@ -835,14 +906,23 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
e->ignore();
}
ConfigView* ConfigView::viewList;
ConfigView*ConfigView::viewList;
QAction *ConfigView::showNormalAction;
QAction *ConfigView::showAllAction;
QAction *ConfigView::showPromptAction;
ConfigView::ConfigView(QWidget* parent, const char *name)
: Parent(parent, name)
: Parent(parent)
{
list = new ConfigList(this, name);
setObjectName(name);
QVBoxLayout *verticalLayout = new QVBoxLayout(this);
verticalLayout->setContentsMargins(0, 0, 0, 0);
list = new ConfigList(this);
verticalLayout->addWidget(list);
lineEdit = new ConfigLineEdit(this);
lineEdit->hide();
verticalLayout->addWidget(lineEdit);
this->nextView = viewList;
viewList = this;
......@@ -860,13 +940,16 @@ ConfigView::~ConfigView(void)
}
}
void ConfigView::setShowAll(bool b)
void ConfigView::setOptionMode(QAction *act)
{
if (list->showAll != b) {
list->showAll = b;
list->updateListAll();
emit showAllChanged(b);
}
if (act == showNormalAction)
list->optMode = normalOpt;
else if (act == showAllAction)
list->optMode = allOpt;
else
list->optMode = promptOpt;
list->updateListAll();
}
void ConfigView::setShowName(bool b)
......@@ -898,10 +981,13 @@ void ConfigView::setShowData(bool b)
void ConfigList::setAllOpen(bool open)
{
QListViewItemIterator it(this);
QTreeWidgetItemIterator it(this);
for (; it.current(); it++)
it.current()->setOpen(open);
while (*it) {
(*it)->setExpanded(open);
++it;
}
}
void ConfigView::updateList(ConfigItem* item)
......@@ -921,11 +1007,14 @@ void ConfigView::updateListAll(void)
}
ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
: Parent(parent, name), sym(0), menu(0)
: Parent(parent), sym(0), _menu(0)
{
if (name) {
configSettings->beginGroup(name);
_showDebug = configSettings->readBoolEntry("/showDebug", false);
setObjectName(name);
if (!objectName().isEmpty()) {
configSettings->beginGroup(objectName());
_showDebug = configSettings->value("/showDebug", false).toBool();
configSettings->endGroup();
connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
}
......@@ -933,9 +1022,9 @@ ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
void ConfigInfoView::saveSettings(void)
{
if (name()) {
configSettings->beginGroup(name());
configSettings->writeEntry("/showDebug", showDebug());
if (!objectName().isEmpty()) {
configSettings->beginGroup(objectName());
configSettings->setValue("/showDebug", showDebug());
configSettings->endGroup();
}
}
......@@ -944,7 +1033,7 @@ void ConfigInfoView::setShowDebug(bool b)
{
if (_showDebug != b) {
_showDebug = b;
if (menu)
if (_menu)
menuInfo();
else if (sym)
symbolInfo();
......@@ -954,44 +1043,16 @@ void ConfigInfoView::setShowDebug(bool b)
void ConfigInfoView::setInfo(struct menu *m)
{
if (menu == m)
if (_menu == m)
return;
menu = m;
_menu = m;
sym = NULL;
if (!menu)
if (!_menu)
clear();
else
menuInfo();
}
void ConfigInfoView::setSource(const QString& name)
{
const char *p = name.latin1();
menu = NULL;
sym = NULL;
switch (p[0]) {
case 'm':
struct menu *m;
if (sscanf(p, "m%p", &m) == 1 && menu != m) {
menu = m;
menuInfo();
emit menuSelected(menu);
}
break;
case 's':
struct symbol *s;
if (sscanf(p, "s%p", &s) == 1 && sym != s) {
sym = s;
symbolInfo();
}
break;
}
}
void ConfigInfoView::symbolInfo(void)
{
QString str;
......@@ -1013,11 +1074,11 @@ void ConfigInfoView::menuInfo(void)
struct symbol* sym;
QString head, debug, help;
sym = menu->sym;
sym = _menu->sym;
if (sym) {
if (menu->prompt) {
if (_menu->prompt) {
head += "<big><b>";
head += print_filter(_(menu->prompt->text));
head += print_filter(_(_menu->prompt->text));
head += "</b></big>";
if (sym->name) {
head += " (";
......@@ -1043,23 +1104,23 @@ void ConfigInfoView::menuInfo(void)
debug = debug_info(sym);
struct gstr help_gstr = str_new();
menu_get_ext_help(menu, &help_gstr);
menu_get_ext_help(_menu, &help_gstr);
help = print_filter(str_get(&help_gstr));
str_free(&help_gstr);
} else if (menu->prompt) {
} else if (_menu->prompt) {
head += "<big><b>";
head += print_filter(_(menu->prompt->text));
head += print_filter(_(_menu->prompt->text));
head += "</b></big><br><br>";
if (showDebug()) {
if (menu->prompt->visible.expr) {
if (_menu->prompt->visible.expr) {
debug += "&nbsp;&nbsp;dep: ";
expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
debug += "<br><br>";
}
}
}
if (showDebug())
debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
setText(head + debug + help);
}
......@@ -1122,8 +1183,8 @@ QString ConfigInfoView::print_filter(const QString &str)
{
QRegExp re("[<>&\"\\n]");
QString res = str;
for (int i = 0; (i = res.find(re, i)) >= 0;) {
switch (res[i].latin1()) {
for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
switch (res[i].toLatin1()) {
case '<':
res.replace(i, 1, "&lt;");
i += 4;
......@@ -1162,37 +1223,42 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
*text += str2;
}
QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
{
QPopupMenu* popup = Parent::createPopupMenu(pos);
QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup);
action->setToggleAction(TRUE);
QMenu* popup = Parent::createStandardContextMenu(pos);
QAction* action = new QAction(_("Show Debug Info"), popup);
action->setCheckable(true);
connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
action->setOn(showDebug());
popup->insertSeparator();
action->addTo(popup);
action->setChecked(showDebug());
popup->addSeparator();
popup->addAction(action);
return popup;
}
void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e)
{
Parent::contentsContextMenuEvent(e);
Parent::contextMenuEvent(e);
}
ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
: Parent(parent, name), result(NULL)
: Parent(parent), result(NULL)
{
setCaption("Search Config");
setObjectName(name);
setWindowTitle("Search Config");
QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
QVBoxLayout* layout1 = new QVBoxLayout(this);
layout1->setContentsMargins(11, 11, 11, 11);
layout1->setSpacing(6);
QHBoxLayout* layout2 = new QHBoxLayout(0);
layout2->setContentsMargins(0, 0, 0, 0);
layout2->setSpacing(6);
layout2->addWidget(new QLabel(_("Find:"), this));
editField = new QLineEdit(this);
connect(editField, SIGNAL(returnPressed()), SLOT(search()));
layout2->addWidget(editField);
searchButton = new QPushButton(_("Search"), this);
searchButton->setAutoDefault(FALSE);
searchButton->setAutoDefault(false);
connect(searchButton, SIGNAL(clicked()), SLOT(search()));
layout2->addWidget(searchButton);
layout1->addLayout(layout2);
......@@ -1210,19 +1276,19 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
layout1->addWidget(split);
if (name) {
int x, y, width, height;
QVariant x, y;
int width, height;
bool ok;
configSettings->beginGroup(name);
width = configSettings->readNumEntry("/window width", parent->width() / 2);
height = configSettings->readNumEntry("/window height", parent->height() / 2);
width = configSettings->value("/window width", parent->width() / 2).toInt();
height = configSettings->value("/window height", parent->height() / 2).toInt();
resize(width, height);
x = configSettings->readNumEntry("/window x", 0, &ok);
if (ok)
y = configSettings->readNumEntry("/window y", 0, &ok);
if (ok)
move(x, y);
QValueList<int> sizes = configSettings->readSizes("/split", &ok);
x = configSettings->value("/window x");
y = configSettings->value("/window y");
if ((x.isValid())&&(y.isValid()))
move(x.toInt(), y.toInt());
QList<int> sizes = configSettings->readSizes("/split", &ok);
if (ok)
split->setSizes(sizes);
configSettings->endGroup();
......@@ -1232,12 +1298,12 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
void ConfigSearchWindow::saveSettings(void)
{
if (name()) {
configSettings->beginGroup(name());
configSettings->writeEntry("/window x", pos().x());
configSettings->writeEntry("/window y", pos().y());
configSettings->writeEntry("/window width", size().width());
configSettings->writeEntry("/window height", size().height());
if (!objectName().isEmpty()) {
configSettings->beginGroup(objectName());
configSettings->setValue("/window x", pos().x());
configSettings->setValue("/window y", pos().y());
configSettings->setValue("/window width", size().width());
configSettings->setValue("/window height", size().height());
configSettings->writeSizes("/split", split->sizes());
configSettings->endGroup();
}
......@@ -1253,7 +1319,7 @@ void ConfigSearchWindow::search(void)
list->list->clear();
info->clear();
result = sym_re_search(editField->text().latin1());
result = sym_re_search(editField->text().toLatin1());
if (!result)
return;
for (p = result; *p; p++) {
......@@ -1270,23 +1336,25 @@ ConfigMainWindow::ConfigMainWindow(void)
: searchWindow(0)
{
QMenuBar* menu;
bool ok;
int x, y, width, height;
bool ok = true;
QVariant x, y;
int width, height;
char title[256];
QDesktopWidget *d = configApp->desktop();
snprintf(title, sizeof(title), _("WRS-sw v%s Configuration"),
getenv("KERNELVERSION"));
setCaption(title);
width = configSettings->readNumEntry("/window width", d->width() - 64);
height = configSettings->readNumEntry("/window height", d->height() - 64);
snprintf(title, sizeof(title), "%s%s",
rootmenu.prompt->text,
""
);
setWindowTitle(title);
width = configSettings->value("/window width", d->width() - 64).toInt();
height = configSettings->value("/window height", d->height() - 64).toInt();
resize(width, height);
x = configSettings->readNumEntry("/window x", 0, &ok);
if (ok)
y = configSettings->readNumEntry("/window y", 0, &ok);
if (ok)
move(x, y);
x = configSettings->value("/window x");
y = configSettings->value("/window y");
if ((x.isValid())&&(y.isValid()))
move(x.toInt(), y.toInt());
split1 = new QSplitter(this);
split1->setOrientation(Qt::Horizontal);
......@@ -1303,108 +1371,115 @@ ConfigMainWindow::ConfigMainWindow(void)
configList = configView->list;
helpText = new ConfigInfoView(split2, "help");
helpText->setTextFormat(Qt::RichText);
setTabOrder(configList, helpText);
configList->setFocus();
menu = menuBar();
toolBar = new QToolBar("Tools", this);
backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this);
connect(backAction, SIGNAL(activated()), SLOT(goBack()));
backAction->setEnabled(FALSE);
QAction *quitAction = new QAction("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
connect(quitAction, SIGNAL(activated()), SLOT(close()));
QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
addToolBar(toolBar);
backAction = new QAction(QPixmap(xpm_back), _("Back"), this);
connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
backAction->setEnabled(false);
QAction *quitAction = new QAction(_("&Quit"), this);
quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
QAction *loadAction = new QAction(QPixmap(xpm_load), _("&Load"), this);
loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
saveAction = new QAction(QPixmap(xpm_save), _("&Save"), this);
saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
conf_set_changed_callback(conf_changed);
// Set saveAction's initial state
conf_changed();
QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this);
connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
QAction *searchAction = new QAction("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this);
showNameAction->setToggleAction(TRUE);
QAction *saveAsAction = new QAction(_("Save &As..."), this);
connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
QAction *searchAction = new QAction(_("&Find"), this);
searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
singleViewAction = new QAction(QPixmap(xpm_single_view), _("Single View"), this);
singleViewAction->setCheckable(true);
connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
splitViewAction = new QAction(QPixmap(xpm_split_view), _("Split View"), this);
splitViewAction->setCheckable(true);
connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
fullViewAction = new QAction(QPixmap(xpm_tree_view), _("Full View"), this);
fullViewAction->setCheckable(true);
connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
QAction *showNameAction = new QAction(_("Show Name"), this);
showNameAction->setCheckable(true);
connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
showNameAction->setOn(configView->showName());
QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this);
showRangeAction->setToggleAction(TRUE);
showNameAction->setChecked(configView->showName());
QAction *showRangeAction = new QAction(_("Show Range"), this);
showRangeAction->setCheckable(true);
connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
showRangeAction->setOn(configList->showRange);
QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this);
showDataAction->setToggleAction(TRUE);
QAction *showDataAction = new QAction(_("Show Data"), this);
showDataAction->setCheckable(true);
connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
showDataAction->setOn(configList->showData);
QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this);
showAllAction->setToggleAction(TRUE);
connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool)));
connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool)));
showAllAction->setOn(configList->showAll);
QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this);
showDebugAction->setToggleAction(TRUE);
QActionGroup *optGroup = new QActionGroup(this);
optGroup->setExclusive(true);
connect(optGroup, SIGNAL(triggered(QAction*)), configView,
SLOT(setOptionMode(QAction *)));
connect(optGroup, SIGNAL(triggered(QAction *)), menuView,
SLOT(setOptionMode(QAction *)));
configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup);
configView->showAllAction = new QAction(_("Show All Options"), optGroup);
configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup);
configView->showNormalAction->setCheckable(true);
configView->showAllAction->setCheckable(true);
configView->showPromptAction->setCheckable(true);
QAction *showDebugAction = new QAction( _("Show Debug Info"), this);
showDebugAction->setCheckable(true);
connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
showDebugAction->setOn(helpText->showDebug());
showDebugAction->setChecked(helpText->showDebug());
QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this);
connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
QAction *showAboutAction = new QAction(NULL, _("About"), 0, this);
connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
QAction *showIntroAction = new QAction( _("Introduction"), this);
connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
QAction *showAboutAction = new QAction( _("About"), this);
connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
// init tool bar
backAction->addTo(toolBar);
toolBar->addAction(backAction);
toolBar->addSeparator();
loadAction->addTo(toolBar);
saveAction->addTo(toolBar);
toolBar->addAction(loadAction);
toolBar->addAction(saveAction);
toolBar->addSeparator();
singleViewAction->addTo(toolBar);
splitViewAction->addTo(toolBar);
fullViewAction->addTo(toolBar);
toolBar->addAction(singleViewAction);
toolBar->addAction(splitViewAction);
toolBar->addAction(fullViewAction);
// create config menu
QPopupMenu* config = new QPopupMenu(this);
menu->insertItem(_("&File"), config);
loadAction->addTo(config);
saveAction->addTo(config);
saveAsAction->addTo(config);
config->insertSeparator();
quitAction->addTo(config);
QMenu* config = menu->addMenu(_("&File"));
config->addAction(loadAction);
config->addAction(saveAction);
config->addAction(saveAsAction);
config->addSeparator();
config->addAction(quitAction);
// create edit menu
QPopupMenu* editMenu = new QPopupMenu(this);
menu->insertItem(_("&Edit"), editMenu);
searchAction->addTo(editMenu);
QMenu* editMenu = menu->addMenu(_("&Edit"));
editMenu->addAction(searchAction);
// create options menu
QPopupMenu* optionMenu = new QPopupMenu(this);
menu->insertItem(_("&Option"), optionMenu);
showNameAction->addTo(optionMenu);
showRangeAction->addTo(optionMenu);
showDataAction->addTo(optionMenu);
optionMenu->insertSeparator();
showAllAction->addTo(optionMenu);
showDebugAction->addTo(optionMenu);
QMenu* optionMenu = menu->addMenu(_("&Option"));
optionMenu->addAction(showNameAction);
optionMenu->addAction(showRangeAction);
optionMenu->addAction(showDataAction);
optionMenu->addSeparator();
optionMenu->addActions(optGroup->actions());
optionMenu->addSeparator();
// create help menu
QPopupMenu* helpMenu = new QPopupMenu(this);
menu->insertSeparator();
menu->insertItem(_("&Help"), helpMenu);
showIntroAction->addTo(helpMenu);
showAboutAction->addTo(helpMenu);
menu->addSeparator();
QMenu* helpMenu = menu->addMenu(_("&Help"));
helpMenu->addAction(showIntroAction);
helpMenu->addAction(showAboutAction);
connect(configList, SIGNAL(menuChanged(struct menu *)),
helpText, SLOT(setInfo(struct menu *)));
......@@ -1426,7 +1501,7 @@ ConfigMainWindow::ConfigMainWindow(void)
connect(helpText, SIGNAL(menuSelected(struct menu *)),
SLOT(setMenuLink(struct menu *)));
QString listMode = configSettings->readEntry("/listMode", "symbol");
QString listMode = configSettings->value("/listMode", "symbol").toString();
if (listMode == "single")
showSingleView();
else if (listMode == "full")
......@@ -1435,7 +1510,7 @@ ConfigMainWindow::ConfigMainWindow(void)
showSplitView();
// UI setup done, restore splitter positions
QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
QList<int> sizes = configSettings->readSizes("/split1", &ok);
if (ok)
split1->setSizes(sizes);
......@@ -1446,7 +1521,7 @@ ConfigMainWindow::ConfigMainWindow(void)
void ConfigMainWindow::loadConfig(void)
{
QString s = QFileDialog::getOpenFileName(conf_get_configname(), NULL, this);
QString s = QFileDialog::getOpenFileName(this, "", conf_get_configname());
if (s.isNull())
return;
if (conf_read(QFile::encodeName(s)))
......@@ -1454,19 +1529,21 @@ void ConfigMainWindow::loadConfig(void)
ConfigView::updateListAll();
}
void ConfigMainWindow::saveConfig(void)
bool ConfigMainWindow::saveConfig(void)
{
if (conf_write(NULL))
if (conf_write(NULL)) {
QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
return false;
}
return true;
}
void ConfigMainWindow::saveConfigAs(void)
{
QString s = QFileDialog::getSaveFileName(conf_get_configname(), NULL, this);
QString s = QFileDialog::getSaveFileName(this, "", conf_get_configname());
if (s.isNull())
return;
if (conf_write(QFile::encodeName(s)))
QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
saveConfig();
}
void ConfigMainWindow::searchConfig(void)
......@@ -1480,9 +1557,9 @@ void ConfigMainWindow::changeMenu(struct menu *menu)
{
configList->setRootMenu(menu);
if (configList->rootEntry->parent == &rootmenu)
backAction->setEnabled(FALSE);
backAction->setEnabled(false);
else
backAction->setEnabled(TRUE);
backAction->setEnabled(true);
}
void ConfigMainWindow::setMenuLink(struct menu *menu)
......@@ -1491,7 +1568,7 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
ConfigList* list = NULL;
ConfigItem* item;
if (!menu_is_visible(menu) && !configView->showAll())
if (configList->menuSkip(menu))
return;
switch (configList->mode) {
......@@ -1514,8 +1591,8 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
return;
item = menuList->findConfigItem(parent);
if (item) {
menuList->setSelected(item, TRUE);
menuList->ensureItemVisible(item);
item->setSelected(true);
menuList->scrollToItem(item);
}
list->setRootMenu(parent);
}
......@@ -1530,8 +1607,8 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
if (list) {
item = list->findConfigItem(menu);
if (item) {
list->setSelected(item, TRUE);
list->ensureItemVisible(item);
item->setSelected(true);
list->scrollToItem(item);
list->setFocus();
}
}
......@@ -1545,15 +1622,21 @@ void ConfigMainWindow::listFocusChanged(void)
void ConfigMainWindow::goBack(void)
{
ConfigItem* item;
ConfigItem* item, *oldSelection;
configList->setParentMenu();
if (configList->rootEntry == &rootmenu)
backAction->setEnabled(FALSE);
item = (ConfigItem*)menuList->selectedItem();
backAction->setEnabled(false);
if (menuList->selectedItems().count() == 0)
return;
item = (ConfigItem*)menuList->selectedItems().first();
oldSelection = item;
while (item) {
if (item->menu == configList->rootEntry) {
menuList->setSelected(item, TRUE);
oldSelection->setSelected(false);
item->setSelected(true);
break;
}
item = (ConfigItem*)item->parent();
......@@ -1562,6 +1645,13 @@ void ConfigMainWindow::goBack(void)
void ConfigMainWindow::showSingleView(void)
{
singleViewAction->setEnabled(false);
singleViewAction->setChecked(true);
splitViewAction->setEnabled(true);
splitViewAction->setChecked(false);
fullViewAction->setEnabled(true);
fullViewAction->setChecked(false);
menuView->hide();
menuList->setRootMenu(0);
configList->mode = singleMode;
......@@ -1569,28 +1659,41 @@ void ConfigMainWindow::showSingleView(void)
configList->updateListAll();
else
configList->setRootMenu(&rootmenu);
configList->setAllOpen(TRUE);
configList->setFocus();
}
void ConfigMainWindow::showSplitView(void)
{
singleViewAction->setEnabled(true);
singleViewAction->setChecked(false);
splitViewAction->setEnabled(false);
splitViewAction->setChecked(true);
fullViewAction->setEnabled(true);
fullViewAction->setChecked(false);
configList->mode = symbolMode;
if (configList->rootEntry == &rootmenu)
configList->updateListAll();
else
configList->setRootMenu(&rootmenu);
configList->setAllOpen(TRUE);
configList->setAllOpen(true);
configApp->processEvents();
menuList->mode = menuMode;
menuList->setRootMenu(&rootmenu);
menuList->setAllOpen(TRUE);
menuList->setAllOpen(true);
menuView->show();
menuList->setFocus();
}
void ConfigMainWindow::showFullView(void)
{
singleViewAction->setEnabled(true);
singleViewAction->setChecked(false);
splitViewAction->setEnabled(true);
splitViewAction->setChecked(false);
fullViewAction->setEnabled(false);
fullViewAction->setChecked(true);
menuView->hide();
menuList->setRootMenu(0);
configList->mode = fullMode;
......@@ -1598,7 +1701,6 @@ void ConfigMainWindow::showFullView(void)
configList->updateListAll();
else
configList->setRootMenu(&rootmenu);
configList->setAllOpen(FALSE);
configList->setFocus();
}
......@@ -1619,7 +1721,11 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
switch (mb.exec()) {
case QMessageBox::Yes:
conf_write(NULL);
if (saveConfig())
e->accept();
else
e->ignore();
break;
case QMessageBox::No:
e->accept();
break;
......@@ -1631,7 +1737,7 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
void ConfigMainWindow::showIntro(void)
{
static const QString str = _("Welcome to the qconf graphical kernel configuration tool for WRS-sw.\n\n"
static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
"For each option, a blank box indicates the feature is disabled, a check\n"
"indicates it is enabled, and a dot indicates that it is to be compiled\n"
"as a module. Clicking on the box will cycle through the three states.\n\n"
......@@ -1648,7 +1754,8 @@ void ConfigMainWindow::showIntro(void)
void ConfigMainWindow::showAbout(void)
{
static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
"Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
"Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
QMessageBox::information(this, "qconf", str);
......@@ -1656,10 +1763,10 @@ void ConfigMainWindow::showAbout(void)
void ConfigMainWindow::saveSettings(void)
{
configSettings->writeEntry("/window x", pos().x());
configSettings->writeEntry("/window y", pos().y());
configSettings->writeEntry("/window width", size().width());
configSettings->writeEntry("/window height", size().height());
configSettings->setValue("/window x", pos().x());
configSettings->setValue("/window y", pos().y());
configSettings->setValue("/window width", size().width());
configSettings->setValue("/window height", size().height());
QString entry;
switch(configList->mode) {
......@@ -1678,7 +1785,7 @@ void ConfigMainWindow::saveSettings(void)
default:
break;
}
configSettings->writeEntry("/listMode", entry);
configSettings->setValue("/listMode", entry);
configSettings->writeSizes("/split1", split1->sizes());
configSettings->writeSizes("/split2", split2->sizes());
......@@ -1710,7 +1817,7 @@ static const char *progname;
static void usage(void)
{
printf(_("%s <config>\n"), progname);
printf(_("%s [-s] <config>\n").toLatin1().constData(), progname);
exit(0);
}
......@@ -1722,14 +1829,13 @@ int main(int ac, char** av)
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#ifndef LKC_DIRECT_LINK
kconfig_load();
#endif
progname = av[0];
configApp = new QApplication(ac, av);
if (ac > 1 && av[1][0] == '-') {
switch (av[1][1]) {
case 's':
conf_set_message_callback(NULL);
break;
case 'h':
case '?':
usage();
......@@ -1750,7 +1856,6 @@ int main(int ac, char** av)
v = new ConfigMainWindow();
//zconfdump(stdout);
configApp->setMainWidget(v);
configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
v->show();
......@@ -1758,6 +1863,8 @@ int main(int ac, char** av)
configSettings->endGroup();
delete configSettings;
delete v;
delete configApp;
return 0;
}
......@@ -3,27 +3,18 @@
* Released under the terms of the GNU GPL v2.0.
*/
#include <qlistview.h>
#if QT_VERSION >= 300
#include <QTextBrowser>
#include <QTreeWidget>
#include <QMainWindow>
#include <QHeaderView>
#include <qsettings.h>
#else
class QSettings {
public:
void beginGroup(const QString& group) { }
void endGroup(void) { }
bool readBoolEntry(const QString& key, bool def = FALSE, bool* ok = 0) const
{ if (ok) *ok = FALSE; return def; }
int readNumEntry(const QString& key, int def = 0, bool* ok = 0) const
{ if (ok) *ok = FALSE; return def; }
QString readEntry(const QString& key, const QString& def = QString::null, bool* ok = 0) const
{ if (ok) *ok = FALSE; return def; }
QStringList readListEntry(const QString& key, bool* ok = 0) const
{ if (ok) *ok = FALSE; return QStringList(); }
template <class t>
bool writeEntry(const QString& key, t value)
{ return TRUE; }
};
#endif
#include <QPushButton>
#include <QSettings>
#include <QLineEdit>
#include <QSplitter>
#include <QCheckBox>
#include <QDialog>
#include "expr.h"
class ConfigView;
class ConfigList;
......@@ -31,11 +22,11 @@ class ConfigItem;
class ConfigLineEdit;
class ConfigMainWindow;
class ConfigSettings : public QSettings {
public:
QValueList<int> readSizes(const QString& key, bool *ok);
bool writeSizes(const QString& key, const QValueList<int>& value);
ConfigSettings();
QList<int> readSizes(const QString& key, bool *ok);
bool writeSizes(const QString& key, const QList<int>& value);
};
enum colIdx {
......@@ -44,10 +35,13 @@ enum colIdx {
enum listMode {
singleMode, menuMode, symbolMode, fullMode, listMode
};
enum optionMode {
normalOpt = 0, allOpt, promptOpt
};
class ConfigList : public QListView {
class ConfigList : public QTreeWidget {
Q_OBJECT
typedef class QListView Parent;
typedef class QTreeWidget Parent;
public:
ConfigList(ConfigView* p, const char *name = 0);
void reinit(void);
......@@ -59,10 +53,10 @@ public:
protected:
void keyPressEvent(QKeyEvent *e);
void contentsMousePressEvent(QMouseEvent *e);
void contentsMouseReleaseEvent(QMouseEvent *e);
void contentsMouseMoveEvent(QMouseEvent *e);
void contentsMouseDoubleClickEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseDoubleClickEvent(QMouseEvent *e);
void focusInEvent(QFocusEvent *e);
void contextMenuEvent(QContextMenuEvent *e);
......@@ -93,30 +87,23 @@ public:
}
ConfigItem* firstChild() const
{
return (ConfigItem *)Parent::firstChild();
return (ConfigItem *)children().first();
}
int mapIdx(colIdx idx)
void addColumn(colIdx idx)
{
return colMap[idx];
}
void addColumn(colIdx idx, const QString& label)
{
colMap[idx] = Parent::addColumn(label);
colRevMap[colMap[idx]] = idx;
showColumn(idx);
}
void removeColumn(colIdx idx)
{
int col = colMap[idx];
if (col >= 0) {
Parent::removeColumn(col);
colRevMap[col] = colMap[idx] = -1;
}
hideColumn(idx);
}
void setAllOpen(bool open);
void setParentMenu(void);
template <class P>
void updateMenuList(P*, struct menu*);
bool menuSkip(struct menu *);
void updateMenuList(ConfigItem *parent, struct menu*);
void updateMenuList(ConfigList *parent, struct menu*);
bool updateAll;
......@@ -124,72 +111,77 @@ public:
QPixmap choiceYesPix, choiceNoPix;
QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
bool showAll, showName, showRange, showData;
bool showName, showRange, showData;
enum listMode mode;
enum optionMode optMode;
struct menu *rootEntry;
QColorGroup disabledColorGroup;
QColorGroup inactivedColorGroup;
QPopupMenu* headerPopup;
private:
int colMap[colNr];
int colRevMap[colNr];
QPalette disabledColorGroup;
QPalette inactivedColorGroup;
QMenu* headerPopup;
};
class ConfigItem : public QListViewItem {
typedef class QListViewItem Parent;
class ConfigItem : public QTreeWidgetItem {
typedef class QTreeWidgetItem Parent;
public:
ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v)
: Parent(parent, after), menu(m), visible(v), goParent(false)
ConfigItem(ConfigList *parent, ConfigItem *after, struct menu *m, bool v)
: Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false)
{
init();
}
ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
: Parent(parent, after), menu(m), visible(v), goParent(false)
: Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false)
{
init();
}
ConfigItem(QListView *parent, ConfigItem *after, bool v)
: Parent(parent, after), menu(0), visible(v), goParent(true)
ConfigItem(ConfigList *parent, ConfigItem *after, bool v)
: Parent(parent, after), nextItem(0), menu(0), visible(v), goParent(true)
{
init();
}
~ConfigItem(void);
void init(void);
#if QT_VERSION >= 300
void okRename(int col);
#endif
void updateMenu(void);
void testUpdateMenu(bool v);
ConfigList* listView() const
{
return (ConfigList*)Parent::listView();
return (ConfigList*)Parent::treeWidget();
}
ConfigItem* firstChild() const
{
return (ConfigItem *)Parent::firstChild();
return (ConfigItem *)Parent::child(0);
}
ConfigItem* nextSibling() const
ConfigItem* nextSibling()
{
return (ConfigItem *)Parent::nextSibling();
ConfigItem *ret = NULL;
ConfigItem *_parent = (ConfigItem *)parent();
if(_parent) {
ret = (ConfigItem *)_parent->child(_parent->indexOfChild(this)+1);
} else {
QTreeWidget *_treeWidget = treeWidget();
ret = (ConfigItem *)_treeWidget->topLevelItem(_treeWidget->indexOfTopLevelItem(this)+1);
}
return ret;
}
void setText(colIdx idx, const QString& text)
{
Parent::setText(listView()->mapIdx(idx), text);
Parent::setText(idx, text);
}
QString text(colIdx idx) const
{
return Parent::text(listView()->mapIdx(idx));
return Parent::text(idx);
}
void setPixmap(colIdx idx, const QPixmap& pm)
void setPixmap(colIdx idx, const QIcon &icon)
{
Parent::setPixmap(listView()->mapIdx(idx), pm);
Parent::setIcon(idx, icon);
}
const QPixmap* pixmap(colIdx idx) const
const QIcon pixmap(colIdx idx) const
{
return Parent::pixmap(listView()->mapIdx(idx));
return icon(idx);
}
void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
// TODO: Implement paintCell
ConfigItem* nextItem;
struct menu *menu;
......@@ -213,26 +205,24 @@ public:
ConfigItem *item;
};
class ConfigView : public QVBox {
class ConfigView : public QWidget {
Q_OBJECT
typedef class QVBox Parent;
typedef class QWidget Parent;
public:
ConfigView(QWidget* parent, const char *name = 0);
~ConfigView(void);
static void updateList(ConfigItem* item);
static void updateListAll(void);
bool showAll(void) const { return list->showAll; }
bool showName(void) const { return list->showName; }
bool showRange(void) const { return list->showRange; }
bool showData(void) const { return list->showData; }
public slots:
void setShowAll(bool);
void setShowName(bool);
void setShowRange(bool);
void setShowData(bool);
void setOptionMode(QAction *);
signals:
void showAllChanged(bool);
void showNameChanged(bool);
void showRangeChanged(bool);
void showDataChanged(bool);
......@@ -242,6 +232,10 @@ public:
static ConfigView* viewList;
ConfigView* nextView;
static QAction *showNormalAction;
static QAction *showAllAction;
static QAction *showPromptAction;
};
class ConfigInfoView : public QTextBrowser {
......@@ -254,7 +248,6 @@ public:
public slots:
void setInfo(struct menu *menu);
void saveSettings(void);
void setSource(const QString& name);
void setShowDebug(bool);
signals:
......@@ -267,11 +260,11 @@ protected:
QString debug_info(struct symbol *sym);
static QString print_filter(const QString &str);
static void expr_print_help(void *data, struct symbol *sym, const char *str);
QPopupMenu* createPopupMenu(const QPoint& pos);
void contentsContextMenuEvent(QContextMenuEvent *e);
QMenu *createStandardContextMenu(const QPoint & pos);
void contextMenuEvent(QContextMenuEvent *e);
struct symbol *sym;
struct menu *menu;
struct menu *_menu;
bool _showDebug;
};
......@@ -308,7 +301,7 @@ public slots:
void listFocusChanged(void);
void goBack(void);
void loadConfig(void);
void saveConfig(void);
bool saveConfig(void);
void saveConfigAs(void);
void searchConfig(void);
void showSingleView(void);
......@@ -329,6 +322,9 @@ protected:
ConfigInfoView *helpText;
QToolBar *toolBar;
QAction *backAction;
QSplitter* split1;
QSplitter* split2;
QAction *singleViewAction;
QAction *splitViewAction;
QAction *fullViewAction;
QSplitter *split1;
QSplitter *split2;
};
#!/usr/bin/perl -w
#
# Copywrite 2005-2009 - Steven Rostedt
# Copyright 2005-2009 - Steven Rostedt
# Licensed under the terms of the GNU GPL License version 2
#
# It's simple enough to figure out how this works.
......@@ -42,6 +42,19 @@
# mv config_strip .config
# make oldconfig
#
use strict;
use Getopt::Long;
# set the environment variable LOCALMODCONFIG_DEBUG to get
# debug output.
my $debugprint = 0;
$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG}));
sub dprint {
return if (!$debugprint);
print STDERR @_;
}
my $config = ".config";
my $uname = `uname -r`;
......@@ -87,7 +100,7 @@ my @searchconfigs = (
},
);
sub find_config {
sub read_config {
foreach my $conf (@searchconfigs) {
my $file = $conf->{"file"};
......@@ -102,26 +115,36 @@ sub find_config {
print STDERR "using config: '$file'\n";
open(CIN, "$exec $file |") || die "Failed to run $exec $file";
return;
open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file";
my @x = <$infile>;
close $infile;
return @x;
}
die "No config file found";
}
find_config;
my @config_file = read_config;
# Parse options
my $localmodconfig = 0;
my $localyesconfig = 0;
GetOptions("localmodconfig" => \$localmodconfig,
"localyesconfig" => \$localyesconfig);
# Get the build source and top level Kconfig file (passed in)
my $ksource = $ARGV[0];
my $ksource = ($ARGV[0] ? $ARGV[0] : '.');
my $kconfig = $ARGV[1];
my $lsmod_file = $ARGV[2];
my $lsmod_file = $ENV{'LSMOD'};
my @makefiles = `find $ksource -name Makefile -or -name Kbuild 2>/dev/null`;
chomp @makefiles;
my @makefiles = `find $ksource -name Makefile`;
my %depends;
my %selects;
my %prompts;
my %objects;
my $var;
my $cont = 0;
my $iflevel = 0;
my @ifdeps;
......@@ -133,22 +156,54 @@ sub read_kconfig {
my $state = "NONE";
my $config;
my @kconfigs;
open(KIN, "$ksource/$kconfig") || die "Can't open $kconfig";
while (<KIN>) {
my $cont = 0;
my $line;
my $source = "$ksource/$kconfig";
my $last_source = "";
# Check for any environment variables used
while ($source =~ /\$(\w+)/ && $last_source ne $source) {
my $env = $1;
$last_source = $source;
$source =~ s/\$$env/$ENV{$env}/;
}
open(my $kinfile, '<', $source) || die "Can't open $kconfig";
while (<$kinfile>) {
chomp;
# Make sure that lines ending with \ continue
if ($cont) {
$_ = $line . " " . $_;
}
if (s/\\$//) {
$cont = 1;
$line = $_;
next;
}
$cont = 0;
# collect any Kconfig sources
if (/^source\s*"(.*)"/) {
$kconfigs[$#kconfigs+1] = $1;
if (/^source\s+"?([^"]+)/) {
my $kconfig = $1;
# prevent reading twice.
if (!defined($read_kconfigs{$kconfig})) {
$read_kconfigs{$kconfig} = 1;
read_kconfig($kconfig);
}
next;
}
# configs found
if (/^\s*config\s+(\S+)\s*$/) {
if (/^\s*(menu)?config\s+(\S+)\s*$/) {
$state = "NEW";
$config = $1;
$config = $2;
# Add depends for 'if' nesting
for (my $i = 0; $i < $iflevel; $i++) {
if ($i) {
$depends{$config} .= " " . $ifdeps[$i];
......@@ -164,19 +219,27 @@ sub read_kconfig {
$depends{$config} = $1;
} elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
$depends{$config} .= " " . $1;
} elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
my $dep = $3;
if ($dep !~ /^\s*(y|m|n)\s*$/) {
$dep =~ s/.*\sif\s+//;
$depends{$config} .= " " . $dep;
dprint "Added default depends $dep to $config\n";
}
# Get the configs that select this config
} elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
if (defined($selects{$1})) {
$selects{$1} .= " " . $config;
my $conf = $1;
if (defined($selects{$conf})) {
$selects{$conf} .= " " . $config;
} else {
$selects{$1} = $config;
$selects{$conf} = $config;
}
# configs without prompts must be selected
} elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
} elsif ($state ne "NONE" && /^\s*(tristate\s+\S|prompt\b)/) {
# note if the config has a prompt
$prompt{$config} = 1;
$prompts{$config} = 1;
# Check for if statements
} elsif (/^if\s+(.*\S)\s*$/) {
......@@ -193,56 +256,79 @@ sub read_kconfig {
$iflevel-- if ($iflevel);
# stop on "help"
} elsif (/^\s*help\s*$/) {
# stop on "help" and keywords that end a menu entry
} elsif (/^\s*(---)?help(---)?\s*$/ || /^(comment|choice|menu)\b/) {
$state = "NONE";
}
}
close(KIN);
# read in any configs that were found.
foreach $kconfig (@kconfigs) {
if (!defined($read_kconfigs{$kconfig})) {
$read_kconfigs{$kconfig} = 1;
read_kconfig($kconfig);
}
}
close($kinfile);
}
if ($kconfig) {
read_kconfig($kconfig);
}
# Makefiles can use variables to define their dependencies
sub convert_vars {
my ($line, %vars) = @_;
my $process = "";
while ($line =~ s/^(.*?)(\$\((.*?)\))//) {
my $start = $1;
my $variable = $2;
my $var = $3;
if (defined($vars{$var})) {
$process .= $start . $vars{$var};
} else {
$process .= $start . $variable;
}
}
$process .= $line;
return $process;
}
# Read all Makefiles to map the configs to the objects
foreach my $makefile (@makefiles) {
chomp $makefile;
open(MIN,$makefile) || die "Can't open $makefile";
while (<MIN>) {
my $objs;
my $line = "";
my %make_vars;
# is this a line after a line with a backslash?
if ($cont && /(\S.*)$/) {
$objs = $1;
open(my $infile, '<', $makefile) || die "Can't open $makefile";
while (<$infile>) {
# if this line ends with a backslash, continue
chomp;
if (/^(.*)\\$/) {
$line .= $1;
next;
}
$cont = 0;
$line .= $_;
$_ = $line;
$line = "";
my $objs;
# Convert variables in a line (could define configs)
$_ = convert_vars($_, %make_vars);
# collect objects after obj-$(CONFIG_FOO_BAR)
if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
$var = $1;
$objs = $2;
# check if variables are set
} elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) {
$make_vars{$1} = $2;
}
if (defined($objs)) {
# test if the line ends with a backslash
if ($objs =~ m,(.*)\\$,) {
$objs = $1;
$cont = 1;
}
foreach my $obj (split /\s+/,$objs) {
$obj =~ s/-/_/g;
if ($obj =~ /(.*)\.o$/) {
# Objects may bes enabled by more than one config.
# Objects may be enabled by more than one config.
# Store configs in an array.
my @arr;
......@@ -259,28 +345,30 @@ foreach my $makefile (@makefiles) {
}
}
}
close(MIN);
close($infile);
}
my %modules;
my $linfile;
if (defined($lsmod_file)) {
if ( ! -f $lsmod_file) {
die "$lsmod_file not found";
}
if ( -x $lsmod_file) {
# the file is executable, run it
open(LIN, "$lsmod_file|");
} else {
# Just read the contents
open(LIN, "$lsmod_file");
if ( -f $ENV{'objtree'}."/".$lsmod_file) {
$lsmod_file = $ENV{'objtree'}."/".$lsmod_file;
} else {
die "$lsmod_file not found";
}
}
my $otype = ( -x $lsmod_file) ? '-|' : '<';
open($linfile, $otype, $lsmod_file);
} else {
# see what modules are loaded on this system
my $lsmod;
foreach $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
if ( -x "$dir/lsmod" ) {
$lsmod = "$dir/lsmod";
last;
......@@ -291,25 +379,36 @@ if (defined($lsmod_file)) {
$lsmod = "lsmod";
}
open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod";
open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod";
}
while (<LIN>) {
while (<$linfile>) {
next if (/^Module/); # Skip the first line.
if (/^(\S+)/) {
$modules{$1} = 1;
}
}
close (LIN);
close ($linfile);
# add to the configs hash all configs that are needed to enable
# a loaded module.
# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o
# where we know we need bar.o so we add FOO to the list.
my %configs;
foreach my $module (keys(%modules)) {
if (defined($objects{$module})) {
@arr = @{$objects{$module}};
my @arr = @{$objects{$module}};
foreach my $conf (@arr) {
$configs{$conf} = $module;
dprint "$conf added by direct ($module)\n";
if ($debugprint) {
my $c=$conf;
$c =~ s/^CONFIG_//;
if (defined($depends{$c})) {
dprint " deps = $depends{$c}\n";
} else {
dprint " no deps\n";
}
}
}
} else {
# Most likely, someone has a custom (binary?) module loaded.
......@@ -317,9 +416,24 @@ foreach my $module (keys(%modules)) {
}
}
# Read the current config, and see what is enabled. We want to
# ignore configs that we would not enable anyway.
my %orig_configs;
my $valid = "A-Za-z_0-9";
foreach my $line (@config_file) {
$_ = $line;
if (/(CONFIG_[$valid]*)=(m|y)/) {
$orig_configs{$1} = $2;
}
}
my $repeat = 1;
my $depconfig;
#
# Note, we do not care about operands (like: &&, ||, !) we want to add any
# config that is in the depend list of another config. This script does
......@@ -328,7 +442,7 @@ my $repeat = 1;
# to keep on. If A was on in the original config, B would not have been
# and B would not be turned on by this script.
#
sub parse_config_dep_select
sub parse_config_depends
{
my ($p) = @_;
......@@ -339,10 +453,16 @@ sub parse_config_dep_select
$p =~ s/^[^$valid]*[$valid]+//;
# We only need to process if the depend config is a module
if (!defined($orig_configs{$conf}) || $orig_configs{$conf} eq "y") {
next;
}
if (!defined($configs{$conf})) {
# We must make sure that this config has its
# dependencies met.
$repeat = 1; # do again
dprint "$conf selected by depend $depconfig\n";
$configs{$conf} = 1;
}
} else {
......@@ -351,31 +471,132 @@ sub parse_config_dep_select
}
}
while ($repeat) {
$repeat = 0;
# Select is treated a bit differently than depends. We call this
# when a config has no prompt and requires another config to be
# selected. We use to just select all configs that selected this
# config, but found that that can balloon into enabling hundreds
# of configs that we do not care about.
#
# The idea is we look at all the configs that select it. If one
# is already in our list of configs to enable, then there's nothing
# else to do. If there isn't, we pick the first config that was
# enabled in the orignal config and use that.
sub parse_config_selects
{
my ($config, $p) = @_;
foreach my $config (keys %configs) {
$config =~ s/^CONFIG_//;
my $next_config;
while ($p =~ /[$valid]/) {
if ($p =~ /^[^$valid]*([$valid]+)/) {
my $conf = "CONFIG_" . $1;
if (defined($depends{$config})) {
# This config has dependencies. Make sure they are also included
parse_config_dep_select $depends{$config};
$p =~ s/^[^$valid]*[$valid]+//;
# Make sure that this config exists in the current .config file
if (!defined($orig_configs{$conf})) {
dprint "$conf not set for $config select\n";
next;
}
# Check if something other than a module selects this config
if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") {
dprint "$conf (non module) selects config, we are good\n";
# we are good with this
return;
}
if (defined($configs{$conf})) {
dprint "$conf selects $config so we are good\n";
# A set config selects this config, we are good
return;
}
# Set this config to be selected
if (!defined($next_config)) {
$next_config = $conf;
}
} else {
die "this should never happen";
}
}
if (defined($prompt{$config}) || !defined($selects{$config})) {
next;
# If no possible config selected this, then something happened.
if (!defined($next_config)) {
print STDERR "WARNING: $config is required, but nothing in the\n";
print STDERR " current config selects it.\n";
return;
}
# If we are here, then we found no config that is set and
# selects this config. Repeat.
$repeat = 1;
# Make this config need to be selected
$configs{$next_config} = 1;
dprint "$next_config selected by select $config\n";
}
my %process_selects;
# loop through all configs, select their dependencies.
sub loop_depend {
$repeat = 1;
while ($repeat) {
$repeat = 0;
forloop:
foreach my $config (keys %configs) {
# If this config is not a module, we do not need to process it
if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") {
next forloop;
}
$config =~ s/^CONFIG_//;
$depconfig = $config;
if (defined($depends{$config})) {
# This config has dependencies. Make sure they are also included
parse_config_depends $depends{$config};
}
# If the config has no prompt, then we need to check if a config
# that is enabled selected it. Or if we need to enable one.
if (!defined($prompts{$config}) && defined($selects{$config})) {
$process_selects{$config} = 1;
}
}
}
}
sub loop_select {
foreach my $config (keys %process_selects) {
$config =~ s/^CONFIG_//;
dprint "Process select $config\n";
# config has no prompt and must be selected.
parse_config_dep_select $selects{$config};
parse_config_selects $config, $selects{$config};
}
}
while ($repeat) {
# Get the first set of configs and their dependencies.
loop_depend;
$repeat = 0;
# Now we need to see if we have to check selects;
loop_select;
}
my %setconfigs;
# Finally, read the .config file and turn off any module enabled that
# we could not find a reason to keep enabled.
while(<CIN>) {
foreach my $line (@config_file) {
$_ = $line;
if (/CONFIG_IKCONFIG/) {
if (/# CONFIG_IKCONFIG is not set/) {
......@@ -389,9 +610,49 @@ while(<CIN>) {
next;
}
if (/CONFIG_MODULE_SIG_KEY="(.+)"/) {
my $orig_cert = $1;
my $default_cert = "certs/signing_key.pem";
# Check that the logic in this script still matches the one in Kconfig
if (!defined($depends{"MODULE_SIG_KEY"}) ||
$depends{"MODULE_SIG_KEY"} !~ /"\Q$default_cert\E"/) {
print STDERR "WARNING: MODULE_SIG_KEY assertion failure, ",
"update needed to ", __FILE__, " line ", __LINE__, "\n";
print;
} elsif ($orig_cert ne $default_cert && ! -f $orig_cert) {
print STDERR "Module signature verification enabled but ",
"module signing key \"$orig_cert\" not found. Resetting ",
"signing key to default value.\n";
print "CONFIG_MODULE_SIG_KEY=\"$default_cert\"\n";
} else {
print;
}
next;
}
if (/CONFIG_SYSTEM_TRUSTED_KEYS="(.+)"/) {
my $orig_keys = $1;
if (! -f $orig_keys) {
print STDERR "System keyring enabled but keys \"$orig_keys\" ",
"not found. Resetting keys to default value.\n";
print "CONFIG_SYSTEM_TRUSTED_KEYS=\"\"\n";
} else {
print;
}
next;
}
if (/^(CONFIG.*)=(m|y)/) {
if (defined($configs{$1})) {
$setconfigs{$1} = $2;
if ($localyesconfig) {
$setconfigs{$1} = 'y';
print "$1=y\n";
next;
} else {
$setconfigs{$1} = $2;
}
} elsif ($2 eq "m") {
print "# $1 is not set\n";
next;
......@@ -399,7 +660,6 @@ while(<CIN>) {
}
print;
}
close(CIN);
# Integrity check, make sure all modules that we want enabled do
# indeed have their configs set.
......
......@@ -9,7 +9,6 @@
#include <regex.h>
#include <sys/utsname.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
struct symbol symbol_yes = {
......@@ -113,7 +112,7 @@ struct property *sym_get_env_prop(struct symbol *sym)
return NULL;
}
struct property *sym_get_default_prop(struct symbol *sym)
static struct property *sym_get_default_prop(struct symbol *sym)
{
struct property *prop;
......@@ -137,7 +136,7 @@ static struct property *sym_get_range_prop(struct symbol *sym)
return NULL;
}
static int sym_get_range_val(struct symbol *sym, int base)
static long long sym_get_range_val(struct symbol *sym, int base)
{
sym_calc_value(sym);
switch (sym->type) {
......@@ -150,13 +149,14 @@ static int sym_get_range_val(struct symbol *sym, int base)
default:
break;
}
return strtol(sym->curr.val, NULL, base);
return strtoll(sym->curr.val, NULL, base);
}
static void sym_validate_range(struct symbol *sym)
{
struct property *prop;
int base, val, val2;
int base;
long long val, val2;
char str[64];
switch (sym->type) {
......@@ -172,7 +172,7 @@ static void sym_validate_range(struct symbol *sym)
prop = sym_get_range_prop(sym);
if (!prop)
return;
val = strtol(sym->curr.val, NULL, base);
val = strtoll(sym->curr.val, NULL, base);
val2 = sym_get_range_val(prop->expr->left.sym, base);
if (val >= val2) {
val2 = sym_get_range_val(prop->expr->right.sym, base);
......@@ -180,21 +180,55 @@ static void sym_validate_range(struct symbol *sym)
return;
}
if (sym->type == S_INT)
sprintf(str, "%d", val2);
sprintf(str, "%lld", val2);
else
sprintf(str, "0x%x", val2);
sprintf(str, "0x%llx", val2);
sym->curr.val = strdup(str);
}
static void sym_set_changed(struct symbol *sym)
{
struct property *prop;
sym->flags |= SYMBOL_CHANGED;
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->menu)
prop->menu->flags |= MENU_CHANGED;
}
}
static void sym_set_all_changed(void)
{
struct symbol *sym;
int i;
for_all_symbols(i, sym)
sym_set_changed(sym);
}
static void sym_calc_visibility(struct symbol *sym)
{
struct property *prop;
struct symbol *choice_sym = NULL;
tristate tri;
/* any prompt visible? */
tri = no;
if (sym_is_choice_value(sym))
choice_sym = prop_get_symbol(sym_get_choice_prop(sym));
for_all_prompts(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
/*
* Tristate choice_values with visibility 'mod' are
* not visible if the corresponding choice's value is
* 'yes'.
*/
if (choice_sym && sym->type == S_TRISTATE &&
prop->visible.tri == mod && choice_sym->curr.tri == yes)
prop->visible.tri = no;
tri = EXPR_OR(tri, prop->visible.tri);
}
if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
......@@ -205,6 +239,16 @@ static void sym_calc_visibility(struct symbol *sym)
}
if (sym_is_choice_value(sym))
return;
/* defaulting to "yes" if no explicit "depends on" are given */
tri = yes;
if (sym->dir_dep.expr)
tri = expr_calc_value(sym->dir_dep.expr);
if (tri == mod)
tri = yes;
if (sym->dir_dep.tri != tri) {
sym->dir_dep.tri = tri;
sym_set_changed(sym);
}
tri = no;
if (sym->rev_dep.expr)
tri = expr_calc_value(sym->rev_dep.expr);
......@@ -216,42 +260,68 @@ static void sym_calc_visibility(struct symbol *sym)
}
}
static struct symbol *sym_calc_choice(struct symbol *sym)
/*
* Find the default symbol for a choice.
* First try the default values for the choice symbol
* Next locate the first visible choice value
* Return NULL if none was found
*/
struct symbol *sym_choice_default(struct symbol *sym)
{
struct symbol *def_sym;
struct property *prop;
struct expr *e;
/* is the user choice visible? */
def_sym = sym->def[S_DEF_USER].val;
if (def_sym) {
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
}
/* any of the defaults visible? */
for_all_defaults(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri == no)
continue;
def_sym = prop_get_symbol(prop);
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
}
/* just get the first visible value */
prop = sym_get_choice_prop(sym);
expr_list_for_each_sym(prop->expr, e, def_sym)
if (def_sym->visible != no)
return def_sym;
/* failed to locate any defaults */
return NULL;
}
static struct symbol *sym_calc_choice(struct symbol *sym)
{
struct symbol *def_sym;
struct property *prop;
struct expr *e;
int flags;
/* first calculate all choice values' visibilities */
flags = sym->flags;
prop = sym_get_choice_prop(sym);
expr_list_for_each_sym(prop->expr, e, def_sym) {
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
flags &= def_sym->flags;
}
/* no choice? reset tristate value */
sym->curr.tri = no;
return NULL;
sym->flags &= flags | ~SYMBOL_DEF_USER;
/* is the user choice visible? */
def_sym = sym->def[S_DEF_USER].val;
if (def_sym && def_sym->visible != no)
return def_sym;
def_sym = sym_choice_default(sym);
if (def_sym == NULL)
/* no choice? reset tristate value */
sym->curr.tri = no;
return def_sym;
}
void sym_calc_value(struct symbol *sym)
......@@ -265,6 +335,14 @@ void sym_calc_value(struct symbol *sym)
if (sym->flags & SYMBOL_VALID)
return;
if (sym_is_choice_value(sym) &&
sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {
sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;
prop = sym_get_choice_prop(sym);
sym_calc_value(prop_get_symbol(prop));
}
sym->flags |= SYMBOL_VALID;
oldval = sym->curr;
......@@ -321,6 +399,18 @@ void sym_calc_value(struct symbol *sym)
}
}
calc_newval:
if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
struct expr *e;
e = expr_simplify_unmet_dep(sym->rev_dep.expr,
sym->dir_dep.expr);
fprintf(stderr, "warning: (");
expr_fprint(e, stderr);
fprintf(stderr, ") selects %s which has unmet direct dependencies (",
sym->name);
expr_fprint(sym->dir_dep.expr, stderr);
fprintf(stderr, ")\n");
expr_free(e);
}
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
}
if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
......@@ -365,18 +455,22 @@ void sym_calc_value(struct symbol *sym)
if (sym_is_choice(sym)) {
struct symbol *choice_sym;
int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
prop = sym_get_choice_prop(sym);
expr_list_for_each_sym(prop->expr, e, choice_sym) {
choice_sym->flags |= flags;
if (flags & SYMBOL_CHANGED)
if ((sym->flags & SYMBOL_WRITE) &&
choice_sym->visible != no)
choice_sym->flags |= SYMBOL_WRITE;
if (sym->flags & SYMBOL_CHANGED)
sym_set_changed(choice_sym);
}
}
if (sym->flags & SYMBOL_AUTO)
sym->flags &= ~SYMBOL_WRITE;
if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
set_all_choice_values(sym);
}
void sym_clear_all_valid(void)
......@@ -387,28 +481,7 @@ void sym_clear_all_valid(void)
for_all_symbols(i, sym)
sym->flags &= ~SYMBOL_VALID;
sym_add_change_count(1);
if (modules_sym)
sym_calc_value(modules_sym);
}
void sym_set_changed(struct symbol *sym)
{
struct property *prop;
sym->flags |= SYMBOL_CHANGED;
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->menu)
prop->menu->flags |= MENU_CHANGED;
}
}
void sym_set_all_changed(void)
{
struct symbol *sym;
int i;
for_all_symbols(i, sym)
sym_set_changed(sym);
sym_calc_value(modules_sym);
}
bool sym_tristate_within_range(struct symbol *sym, tristate val)
......@@ -535,7 +608,7 @@ bool sym_string_valid(struct symbol *sym, const char *str)
bool sym_string_within_range(struct symbol *sym, const char *str)
{
struct property *prop;
int val;
long long val;
switch (sym->type) {
case S_STRING:
......@@ -546,7 +619,7 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
prop = sym_get_range_prop(sym);
if (!prop)
return true;
val = strtol(str, NULL, 10);
val = strtoll(str, NULL, 10);
return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
val <= sym_get_range_val(prop->expr->right.sym, 10);
case S_HEX:
......@@ -555,7 +628,7 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
prop = sym_get_range_prop(sym);
if (!prop)
return true;
val = strtol(str, NULL, 16);
val = strtoll(str, NULL, 16);
return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
val <= sym_get_range_val(prop->expr->right.sym, 16);
case S_BOOLEAN:
......@@ -608,11 +681,11 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
size = strlen(newval) + 1;
if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
size += 2;
sym->def[S_DEF_USER].val = val = malloc(size);
sym->def[S_DEF_USER].val = val = xmalloc(size);
*val++ = '0';
*val++ = 'x';
} else if (!oldval || strcmp(oldval, newval))
sym->def[S_DEF_USER].val = val = malloc(size);
sym->def[S_DEF_USER].val = val = xmalloc(size);
else
return true;
......@@ -623,6 +696,80 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
return true;
}
/*
* Find the default value associated to a symbol.
* For tristate symbol handle the modules=n case
* in which case "m" becomes "y".
* If the symbol does not have any default then fallback
* to the fixed default values.
*/
const char *sym_get_string_default(struct symbol *sym)
{
struct property *prop;
struct symbol *ds;
const char *str;
tristate val;
sym_calc_visibility(sym);
sym_calc_value(modules_sym);
val = symbol_no.curr.tri;
str = symbol_empty.curr.val;
/* If symbol has a default value look it up */
prop = sym_get_default_prop(sym);
if (prop != NULL) {
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
/* The visibility may limit the value from yes => mod */
val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
break;
default:
/*
* The following fails to handle the situation
* where a default value is further limited by
* the valid range.
*/
ds = prop_get_symbol(prop);
if (ds != NULL) {
sym_calc_value(ds);
str = (const char *)ds->curr.val;
}
}
}
/* Handle select statements */
val = EXPR_OR(val, sym->rev_dep.tri);
/* transpose mod to yes if modules are not enabled */
if (val == mod)
if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
val = yes;
/* transpose mod to yes if type is bool */
if (sym->type == S_BOOLEAN && val == mod)
val = yes;
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
switch (val) {
case no: return "n";
case mod: return "m";
case yes: return "y";
}
case S_INT:
case S_HEX:
return str;
case S_STRING:
return str;
case S_OTHER:
case S_UNKNOWN:
break;
}
return "";
}
const char *sym_get_string_value(struct symbol *sym)
{
tristate val;
......@@ -635,7 +782,8 @@ const char *sym_get_string_value(struct symbol *sym)
case no:
return "n";
case mod:
return "m";
sym_calc_value(modules_sym);
return (modules_sym->curr.tri == no) ? "n" : "m";
case yes:
return "y";
}
......@@ -651,12 +799,20 @@ bool sym_is_changable(struct symbol *sym)
return sym->visible > sym->rev_dep.tri;
}
static unsigned strhash(const char *s)
{
/* fnv32 hash */
unsigned hash = 2166136261U;
for (; *s; s++)
hash = (hash ^ *s) * 0x01000193;
return hash;
}
struct symbol *sym_lookup(const char *name, int flags)
{
struct symbol *symbol;
const char *ptr;
char *new_name;
int hash = 0;
int hash;
if (name) {
if (name[0] && !name[1]) {
......@@ -666,12 +822,11 @@ struct symbol *sym_lookup(const char *name, int flags)
case 'n': return &symbol_no;
}
}
for (ptr = name; *ptr; ptr++)
hash += *ptr;
hash &= 0xff;
hash = strhash(name) % SYMBOL_HASHSIZE;
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
if (!strcmp(symbol->name, name) &&
if (symbol->name &&
!strcmp(symbol->name, name) &&
(flags ? symbol->flags & flags
: !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
return symbol;
......@@ -679,10 +834,10 @@ struct symbol *sym_lookup(const char *name, int flags)
new_name = strdup(name);
} else {
new_name = NULL;
hash = 256;
hash = 0;
}
symbol = malloc(sizeof(*symbol));
symbol = xmalloc(sizeof(*symbol));
memset(symbol, 0, sizeof(*symbol));
symbol->name = new_name;
symbol->type = S_UNKNOWN;
......@@ -697,7 +852,6 @@ struct symbol *sym_lookup(const char *name, int flags)
struct symbol *sym_find(const char *name)
{
struct symbol *symbol = NULL;
const char *ptr;
int hash = 0;
if (!name)
......@@ -710,12 +864,11 @@ struct symbol *sym_find(const char *name)
case 'n': return &symbol_no;
}
}
for (ptr = name; *ptr; ptr++)
hash += *ptr;
hash &= 0xff;
hash = strhash(name) % SYMBOL_HASHSIZE;
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
if (!strcmp(symbol->name, name) &&
if (symbol->name &&
!strcmp(symbol->name, name) &&
!(symbol->flags & SYMBOL_CONST))
break;
}
......@@ -723,42 +876,294 @@ struct symbol *sym_find(const char *name)
return symbol;
}
/*
* Expand symbol's names embedded in the string given in argument. Symbols'
* name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
* the empty string.
*/
const char *sym_expand_string_value(const char *in)
{
const char *src;
char *res;
size_t reslen;
reslen = strlen(in) + 1;
res = xmalloc(reslen);
res[0] = '\0';
while ((src = strchr(in, '$'))) {
char *p, name[SYMBOL_MAXLENGTH];
const char *symval = "";
struct symbol *sym;
size_t newlen;
strncat(res, in, src - in);
src++;
p = name;
while (isalnum(*src) || *src == '_')
*p++ = *src++;
*p = '\0';
sym = sym_find(name);
if (sym != NULL) {
sym_calc_value(sym);
symval = sym_get_string_value(sym);
}
newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
if (newlen > reslen) {
reslen = newlen;
res = realloc(res, reslen);
}
strcat(res, symval);
in = src;
}
strcat(res, in);
return res;
}
const char *sym_escape_string_value(const char *in)
{
const char *p;
size_t reslen;
char *res;
size_t l;
reslen = strlen(in) + strlen("\"\"") + 1;
p = in;
for (;;) {
l = strcspn(p, "\"\\");
p += l;
if (p[0] == '\0')
break;
reslen++;
p++;
}
res = xmalloc(reslen);
res[0] = '\0';
strcat(res, "\"");
p = in;
for (;;) {
l = strcspn(p, "\"\\");
strncat(res, p, l);
p += l;
if (p[0] == '\0')
break;
strcat(res, "\\");
strncat(res, p++, 1);
}
strcat(res, "\"");
return res;
}
struct sym_match {
struct symbol *sym;
off_t so, eo;
};
/* Compare matched symbols as thus:
* - first, symbols that match exactly
* - then, alphabetical sort
*/
static int sym_rel_comp(const void *sym1, const void *sym2)
{
const struct sym_match *s1 = sym1;
const struct sym_match *s2 = sym2;
int exact1, exact2;
/* Exact match:
* - if matched length on symbol s1 is the length of that symbol,
* then this symbol should come first;
* - if matched length on symbol s2 is the length of that symbol,
* then this symbol should come first.
* Note: since the search can be a regexp, both symbols may match
* exactly; if this is the case, we can't decide which comes first,
* and we fallback to sorting alphabetically.
*/
exact1 = (s1->eo - s1->so) == strlen(s1->sym->name);
exact2 = (s2->eo - s2->so) == strlen(s2->sym->name);
if (exact1 && !exact2)
return -1;
if (!exact1 && exact2)
return 1;
/* As a fallback, sort symbols alphabetically */
return strcmp(s1->sym->name, s2->sym->name);
}
struct symbol **sym_re_search(const char *pattern)
{
struct symbol *sym, **sym_arr = NULL;
struct sym_match *sym_match_arr = NULL;
int i, cnt, size;
regex_t re;
regmatch_t match[1];
cnt = size = 0;
/* Skip if empty */
if (strlen(pattern) == 0)
return NULL;
if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
return NULL;
for_all_symbols(i, sym) {
if (sym->flags & SYMBOL_CONST || !sym->name)
continue;
if (regexec(&re, sym->name, 0, NULL, 0))
if (regexec(&re, sym->name, 1, match, 0))
continue;
if (cnt + 1 >= size) {
void *tmp = sym_arr;
if (cnt >= size) {
void *tmp;
size += 16;
sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
if (!sym_arr) {
free(tmp);
return NULL;
}
tmp = realloc(sym_match_arr, size * sizeof(struct sym_match));
if (!tmp)
goto sym_re_search_free;
sym_match_arr = tmp;
}
sym_arr[cnt++] = sym;
sym_calc_value(sym);
/* As regexec returned 0, we know we have a match, so
* we can use match[0].rm_[se]o without further checks
*/
sym_match_arr[cnt].so = match[0].rm_so;
sym_match_arr[cnt].eo = match[0].rm_eo;
sym_match_arr[cnt++].sym = sym;
}
if (sym_arr)
if (sym_match_arr) {
qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp);
sym_arr = malloc((cnt+1) * sizeof(struct symbol));
if (!sym_arr)
goto sym_re_search_free;
for (i = 0; i < cnt; i++)
sym_arr[i] = sym_match_arr[i].sym;
sym_arr[cnt] = NULL;
}
sym_re_search_free:
/* sym_match_arr can be NULL if no match, but free(NULL) is OK */
free(sym_match_arr);
regfree(&re);
return sym_arr;
}
/*
* When we check for recursive dependencies we use a stack to save
* current state so we can print out relevant info to user.
* The entries are located on the call stack so no need to free memory.
* Note insert() remove() must always match to properly clear the stack.
*/
static struct dep_stack {
struct dep_stack *prev, *next;
struct symbol *sym;
struct property *prop;
struct expr *expr;
} *check_top;
static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
{
memset(stack, 0, sizeof(*stack));
if (check_top)
check_top->next = stack;
stack->prev = check_top;
stack->sym = sym;
check_top = stack;
}
static void dep_stack_remove(void)
{
check_top = check_top->prev;
if (check_top)
check_top->next = NULL;
}
/*
* Called when we have detected a recursive dependency.
* check_top point to the top of the stact so we use
* the ->prev pointer to locate the bottom of the stack.
*/
static void sym_check_print_recursive(struct symbol *last_sym)
{
struct dep_stack *stack;
struct symbol *sym, *next_sym;
struct menu *menu = NULL;
struct property *prop;
struct dep_stack cv_stack;
if (sym_is_choice_value(last_sym)) {
dep_stack_insert(&cv_stack, last_sym);
last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
}
for (stack = check_top; stack != NULL; stack = stack->prev)
if (stack->sym == last_sym)
break;
if (!stack) {
fprintf(stderr, "unexpected recursive dependency error\n");
return;
}
for (; stack; stack = stack->next) {
sym = stack->sym;
next_sym = stack->next ? stack->next->sym : last_sym;
prop = stack->prop;
if (prop == NULL)
prop = stack->sym->prop;
/* for choice values find the menu entry (used below) */
if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
for (prop = sym->prop; prop; prop = prop->next) {
menu = prop->menu;
if (prop->menu)
break;
}
}
if (stack->sym == last_sym)
fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
prop->file->name, prop->lineno);
fprintf(stderr, "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n");
fprintf(stderr, "subsection \"Kconfig recursive dependency limitations\"\n");
if (stack->expr) {
fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
prop->file->name, prop->lineno,
sym->name ? sym->name : "<choice>",
prop_get_type_name(prop->type),
next_sym->name ? next_sym->name : "<choice>");
} else if (stack->prop) {
fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
prop->file->name, prop->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
} else if (sym_is_choice(sym)) {
fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
menu->file->name, menu->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
} else if (sym_is_choice_value(sym)) {
fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
menu->file->name, menu->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
} else {
fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
prop->file->name, prop->lineno,
sym->name ? sym->name : "<choice>",
next_sym->name ? next_sym->name : "<choice>");
}
}
if (check_top == &cv_stack)
dep_stack_remove();
}
static struct symbol *sym_check_expr_deps(struct expr *e)
{
......@@ -776,6 +1181,10 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
case E_NOT:
return sym_check_expr_deps(e->left.expr);
case E_EQUAL:
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
sym = sym_check_deps(e->left.sym);
if (sym)
......@@ -795,24 +1204,33 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
{
struct symbol *sym2;
struct property *prop;
struct dep_stack stack;
dep_stack_insert(&stack, sym);
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
if (sym2)
return sym2;
goto out;
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->type == P_CHOICE || prop->type == P_SELECT)
continue;
stack.prop = prop;
sym2 = sym_check_expr_deps(prop->visible.expr);
if (sym2)
break;
if (prop->type != P_DEFAULT || sym_is_choice(sym))
continue;
stack.expr = prop->expr;
sym2 = sym_check_expr_deps(prop->expr);
if (sym2)
break;
stack.expr = NULL;
}
out:
dep_stack_remove();
return sym2;
}
......@@ -821,6 +1239,9 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
struct symbol *sym, *sym2;
struct property *prop;
struct expr *e;
struct dep_stack stack;
dep_stack_insert(&stack, choice);
prop = sym_get_choice_prop(choice);
expr_list_for_each_sym(prop->expr, e, sym)
......@@ -834,10 +1255,8 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
expr_list_for_each_sym(prop->expr, e, sym) {
sym2 = sym_check_sym_deps(sym);
if (sym2) {
fprintf(stderr, " -> %s", sym->name);
if (sym2)
break;
}
}
out:
expr_list_for_each_sym(prop->expr, e, sym)
......@@ -847,6 +1266,8 @@ out:
prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
sym2 = choice;
dep_stack_remove();
return sym2;
}
......@@ -856,18 +1277,20 @@ struct symbol *sym_check_deps(struct symbol *sym)
struct property *prop;
if (sym->flags & SYMBOL_CHECK) {
fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
sym->prop->file->name, sym->prop->lineno,
sym->name ? sym->name : "<choice>");
sym_check_print_recursive(sym);
return sym;
}
if (sym->flags & SYMBOL_CHECKED)
return NULL;
if (sym_is_choice_value(sym)) {
struct dep_stack stack;
/* for choice groups start the check with main choice symbol */
dep_stack_insert(&stack, sym);
prop = sym_get_choice_prop(sym);
sym2 = sym_check_deps(prop_get_symbol(prop));
dep_stack_remove();
} else if (sym_is_choice(sym)) {
sym2 = sym_check_choice_deps(sym);
} else {
......@@ -876,14 +1299,8 @@ struct symbol *sym_check_deps(struct symbol *sym)
sym->flags &= ~SYMBOL_CHECK;
}
if (sym2) {
fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
if (sym2 == sym) {
fprintf(stderr, "\n");
zconfnerrs++;
sym2 = NULL;
}
}
if (sym2 && sym2 == sym)
sym2 = NULL;
return sym2;
}
......@@ -893,7 +1310,7 @@ struct property *prop_alloc(enum prop_type type, struct symbol *sym)
struct property *prop;
struct property **propp;
prop = malloc(sizeof(*prop));
prop = xmalloc(sizeof(*prop));
memset(prop, 0, sizeof(*prop));
prop->type = type;
prop->sym = sym;
......@@ -937,6 +1354,8 @@ const char *prop_get_type_name(enum prop_type type)
return "select";
case P_RANGE:
return "range";
case P_SYMBOL:
return "symbol";
case P_UNKNOWN:
break;
}
......
......@@ -5,6 +5,8 @@
* Released under the terms of the GNU GPL v2.0.
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "lkc.h"
......@@ -12,15 +14,18 @@
struct file *file_lookup(const char *name)
{
struct file *file;
const char *file_name = sym_expand_string_value(name);
for (file = file_list; file; file = file->next) {
if (!strcmp(name, file->name))
if (!strcmp(name, file->name)) {
free((void *)file_name);
return file;
}
}
file = malloc(sizeof(*file));
file = xmalloc(sizeof(*file));
memset(file, 0, sizeof(*file));
file->name = strdup(name);
file->name = file_name;
file->next = file_list;
file_list = file;
return file;
......@@ -72,25 +77,17 @@ int file_write_dep(const char *name)
}
/* Allocate initial growable sting */
/* Allocate initial growable string */
struct gstr str_new(void)
{
struct gstr gs;
gs.s = malloc(sizeof(char) * 64);
gs.s = xmalloc(sizeof(char) * 64);
gs.len = 64;
gs.max_width = 0;
strcpy(gs.s, "\0");
return gs;
}
/* Allocate and assign growable string */
struct gstr str_assign(const char *s)
{
struct gstr gs;
gs.s = strdup(s);
gs.len = strlen(s) + 1;
return gs;
}
/* Free storage for growable string */
void str_free(struct gstr *gs)
{
......@@ -131,3 +128,20 @@ const char *str_get(struct gstr *gs)
return gs->s;
}
void *xmalloc(size_t size)
{
void *p = malloc(size);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}
void *xcalloc(size_t nmemb, size_t size)
{
void *p = calloc(nmemb, size);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}
......@@ -9,7 +9,7 @@
struct kconf_id;
static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
%%
mainmenu, T_MAINMENU, TF_COMMAND
......@@ -22,6 +22,7 @@ comment, T_COMMENT, TF_COMMAND
config, T_CONFIG, TF_COMMAND
menuconfig, T_MENUCONFIG, TF_COMMAND
help, T_HELP, TF_COMMAND
---help---, T_HELP, TF_COMMAND
if, T_IF, TF_COMMAND|TF_PARAM
endif, T_ENDIF, TF_COMMAND
depends, T_DEPENDS, TF_COMMAND
......@@ -38,9 +39,11 @@ hex, T_TYPE, TF_COMMAND, S_HEX
string, T_TYPE, TF_COMMAND, S_STRING
select, T_SELECT, TF_COMMAND
range, T_RANGE, TF_COMMAND
visible, T_VISIBLE, TF_COMMAND
option, T_OPTION, TF_COMMAND
on, T_ON, TF_PARAM
modules, T_OPT_MODULES, TF_OPTION
defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION
env, T_OPT_ENV, TF_OPTION
allnoconfig_y, T_OPT_ALLNOCONFIG_Y,TF_OPTION
%%
/* ANSI-C code produced by gperf version 3.0.3 */
/* Command-line: gperf */
/* Computed positions: -k'1,3' */
/* ANSI-C code produced by gperf version 3.0.4 */
/* Command-line: gperf -t --output-file scripts/kconfig/zconf.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/kconfig/zconf.gperf */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
......@@ -29,10 +28,11 @@
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
#endif
#line 10 "scripts/kconfig/zconf.gperf"
struct kconf_id;
static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
/* maximum key range = 47, duplicates = 0 */
static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
/* maximum key range = 71, duplicates = 0 */
#ifdef __GNUC__
__inline
......@@ -44,34 +44,34 @@ inline
static unsigned int
kconf_id_hash (register const char *str, register unsigned int len)
{
static unsigned char asso_values[] =
static const unsigned char asso_values[] =
{
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 11, 5,
0, 0, 5, 49, 5, 20, 49, 49, 5, 20,
5, 0, 30, 49, 0, 15, 0, 10, 0, 49,
25, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 0, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 5, 25, 25,
0, 0, 0, 5, 0, 0, 73, 73, 5, 0,
10, 5, 45, 73, 20, 20, 0, 15, 15, 73,
20, 5, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73
};
register int hval = len;
......@@ -85,137 +85,190 @@ kconf_id_hash (register const char *str, register unsigned int len)
hval += asso_values[(unsigned char)str[0]];
break;
}
return hval;
return hval + asso_values[(unsigned char)str[len - 1]];
}
struct kconf_id_strings_t
{
char kconf_id_strings_str2[sizeof("on")];
char kconf_id_strings_str3[sizeof("env")];
char kconf_id_strings_str2[sizeof("if")];
char kconf_id_strings_str3[sizeof("int")];
char kconf_id_strings_str5[sizeof("endif")];
char kconf_id_strings_str6[sizeof("option")];
char kconf_id_strings_str7[sizeof("endmenu")];
char kconf_id_strings_str8[sizeof("optional")];
char kconf_id_strings_str7[sizeof("default")];
char kconf_id_strings_str8[sizeof("tristate")];
char kconf_id_strings_str9[sizeof("endchoice")];
char kconf_id_strings_str10[sizeof("range")];
char kconf_id_strings_str11[sizeof("choice")];
char kconf_id_strings_str12[sizeof("default")];
char kconf_id_strings_str10[sizeof("---help---")];
char kconf_id_strings_str12[sizeof("def_tristate")];
char kconf_id_strings_str13[sizeof("def_bool")];
char kconf_id_strings_str14[sizeof("help")];
char kconf_id_strings_str15[sizeof("bool")];
char kconf_id_strings_str16[sizeof("config")];
char kconf_id_strings_str17[sizeof("def_tristate")];
char kconf_id_strings_str18[sizeof("boolean")];
char kconf_id_strings_str19[sizeof("defconfig_list")];
char kconf_id_strings_str21[sizeof("string")];
char kconf_id_strings_str22[sizeof("if")];
char kconf_id_strings_str23[sizeof("int")];
char kconf_id_strings_str26[sizeof("select")];
char kconf_id_strings_str14[sizeof("defconfig_list")];
char kconf_id_strings_str17[sizeof("on")];
char kconf_id_strings_str18[sizeof("optional")];
char kconf_id_strings_str21[sizeof("option")];
char kconf_id_strings_str22[sizeof("endmenu")];
char kconf_id_strings_str23[sizeof("mainmenu")];
char kconf_id_strings_str25[sizeof("menuconfig")];
char kconf_id_strings_str27[sizeof("modules")];
char kconf_id_strings_str28[sizeof("tristate")];
char kconf_id_strings_str28[sizeof("allnoconfig_y")];
char kconf_id_strings_str29[sizeof("menu")];
char kconf_id_strings_str31[sizeof("source")];
char kconf_id_strings_str31[sizeof("select")];
char kconf_id_strings_str32[sizeof("comment")];
char kconf_id_strings_str33[sizeof("hex")];
char kconf_id_strings_str35[sizeof("menuconfig")];
char kconf_id_strings_str36[sizeof("prompt")];
char kconf_id_strings_str37[sizeof("depends")];
char kconf_id_strings_str48[sizeof("mainmenu")];
char kconf_id_strings_str33[sizeof("env")];
char kconf_id_strings_str35[sizeof("range")];
char kconf_id_strings_str36[sizeof("choice")];
char kconf_id_strings_str39[sizeof("bool")];
char kconf_id_strings_str41[sizeof("source")];
char kconf_id_strings_str42[sizeof("visible")];
char kconf_id_strings_str43[sizeof("hex")];
char kconf_id_strings_str46[sizeof("config")];
char kconf_id_strings_str47[sizeof("boolean")];
char kconf_id_strings_str51[sizeof("string")];
char kconf_id_strings_str54[sizeof("help")];
char kconf_id_strings_str56[sizeof("prompt")];
char kconf_id_strings_str72[sizeof("depends")];
};
static struct kconf_id_strings_t kconf_id_strings_contents =
static const struct kconf_id_strings_t kconf_id_strings_contents =
{
"on",
"env",
"if",
"int",
"endif",
"default",
"tristate",
"endchoice",
"---help---",
"def_tristate",
"def_bool",
"defconfig_list",
"on",
"optional",
"option",
"endmenu",
"optional",
"endchoice",
"mainmenu",
"menuconfig",
"modules",
"allnoconfig_y",
"menu",
"select",
"comment",
"env",
"range",
"choice",
"default",
"def_bool",
"help",
"bool",
"source",
"visible",
"hex",
"config",
"def_tristate",
"boolean",
"defconfig_list",
"string",
"if",
"int",
"select",
"modules",
"tristate",
"menu",
"source",
"comment",
"hex",
"menuconfig",
"help",
"prompt",
"depends",
"mainmenu"
"depends"
};
#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
#ifdef __GNUC__
__inline
#ifdef __GNUC_STDC_INLINE__
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
__attribute__ ((__gnu_inline__))
#endif
#endif
struct kconf_id *
const struct kconf_id *
kconf_id_lookup (register const char *str, register unsigned int len)
{
enum
{
TOTAL_KEYWORDS = 31,
TOTAL_KEYWORDS = 34,
MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 14,
MIN_HASH_VALUE = 2,
MAX_HASH_VALUE = 48
MAX_HASH_VALUE = 72
};
static struct kconf_id wordlist[] =
static const struct kconf_id wordlist[] =
{
{-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_OPT_ENV, TF_OPTION},
#line 26 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM},
#line 37 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT},
{-1},
#line 27 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_OPTION, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_OPTIONAL, TF_COMMAND},
{-1},
#line 30 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
#line 32 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE},
#line 20 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_CHOICE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_HELP, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str15, T_TYPE, TF_COMMAND, S_BOOLEAN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_CONFIG, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_TYPE, TF_COMMAND, S_BOOLEAN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19, T_OPT_DEFCONFIG_LIST,TF_OPTION},
#line 25 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_HELP, TF_COMMAND},
{-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_TYPE, TF_COMMAND, S_STRING},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT},
#line 33 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE},
#line 36 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
#line 46 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION},
{-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND},
#line 44 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_ON, TF_PARAM},
#line 29 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND},
{-1}, {-1},
#line 43 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_OPTION, TF_COMMAND},
#line 17 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND},
#line 15 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_MAINMENU, TF_COMMAND},
{-1},
#line 23 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25, T_MENUCONFIG, TF_COMMAND},
{-1},
#line 45 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE},
#line 48 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_OPT_ALLNOCONFIG_Y,TF_OPTION},
#line 16 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND},
{-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SOURCE, TF_COMMAND},
#line 40 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND},
#line 21 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_HEX},
#line 47 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_OPT_ENV, TF_OPTION},
{-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_PROMPT, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_DEPENDS, TF_COMMAND},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
#line 41 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_RANGE, TF_COMMAND},
#line 19 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_CHOICE, TF_COMMAND},
{-1}, {-1},
#line 34 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39, T_TYPE, TF_COMMAND, S_BOOLEAN},
{-1},
#line 18 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND},
#line 42 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_VISIBLE, TF_COMMAND},
#line 38 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_TYPE, TF_COMMAND, S_HEX},
{-1}, {-1},
#line 22 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_CONFIG, TF_COMMAND},
#line 35 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN},
{-1}, {-1}, {-1},
#line 39 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_TYPE, TF_COMMAND, S_STRING},
{-1}, {-1},
#line 24 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str54, T_HELP, TF_COMMAND},
{-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND}
#line 31 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str56, T_PROMPT, TF_COMMAND},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
#line 28 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str72, T_DEPENDS, TF_COMMAND}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
......@@ -236,4 +289,5 @@ kconf_id_lookup (register const char *str, register unsigned int len)
}
return 0;
}
#line 49 "scripts/kconfig/zconf.gperf"
%option backup nostdinit noyywrap never-interactive full ecs
%option 8bit backup nodefault perf-report perf-report
%option nostdinit noyywrap never-interactive full ecs
%option 8bit nodefault perf-report perf-report
%option noinput
%x COMMAND HELP STRING PARAM
%{
......@@ -14,7 +14,6 @@
#include <string.h>
#include <unistd.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
#define START_STRSIZE 16
......@@ -28,8 +27,8 @@ static char *text;
static int text_size, text_asize;
struct buffer {
struct buffer *parent;
YY_BUFFER_STATE state;
struct buffer *parent;
YY_BUFFER_STATE state;
};
struct buffer *current_buf;
......@@ -41,7 +40,7 @@ static void zconf_endfile(void);
static void new_string(void)
{
text = malloc(START_STRSIZE);
text = xmalloc(START_STRSIZE);
text_asize = START_STRSIZE;
text_size = 0;
*text = 0;
......@@ -63,14 +62,20 @@ static void append_string(const char *str, int size)
static void alloc_string(const char *str, int size)
{
text = malloc(size + 1);
text = xmalloc(size + 1);
memcpy(text, str, size);
text[size] = 0;
}
static void warn_ignored_character(char chr)
{
fprintf(stderr,
"%s:%d:warning: ignoring unsupported character '%c'\n",
zconf_curname(), zconf_lineno(), chr);
}
%}
ws [ \n\t]
n [A-Za-z0-9_]
n [A-Za-z0-9_-]
%%
int str = 0;
......@@ -96,7 +101,7 @@ n [A-Za-z0-9_]
<COMMAND>{
{n}+ {
struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
BEGIN(PARAM);
current_pos.file = current_file;
current_pos.lineno = current_file->lineno;
......@@ -108,7 +113,7 @@ n [A-Za-z0-9_]
zconflval.string = text;
return T_WORD;
}
.
. warn_ignored_character(*yytext);
\n {
BEGIN(INITIAL);
current_file->lineno++;
......@@ -124,15 +129,18 @@ n [A-Za-z0-9_]
"!" return T_NOT;
"=" return T_EQUAL;
"!=" return T_UNEQUAL;
"<=" return T_LESS_EQUAL;
">=" return T_GREATER_EQUAL;
"<" return T_LESS;
">" return T_GREATER;
\"|\' {
str = yytext[0];
new_string();
BEGIN(STRING);
}
\n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
--- /* ignore */
({n}|[-/.])+ {
struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
({n}|[/.])+ {
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
if (id && id->flags & TF_PARAM) {
zconflval.id = id;
return id->token;
......@@ -143,7 +151,8 @@ n [A-Za-z0-9_]
}
#.* /* comment */
\\\n current_file->lineno++;
.
[[:blank:]]+
. warn_ignored_character(*yytext);
<<EOF>> {
BEGIN(INITIAL);
}
......@@ -289,42 +298,50 @@ void zconf_initscan(const char *name)
exit(1);
}
current_buf = malloc(sizeof(*current_buf));
current_buf = xmalloc(sizeof(*current_buf));
memset(current_buf, 0, sizeof(*current_buf));
current_file = file_lookup(name);
current_file->lineno = 1;
current_file->flags = FILE_BUSY;
}
void zconf_nextfile(const char *name)
{
struct file *iter;
struct file *file = file_lookup(name);
struct buffer *buf = malloc(sizeof(*buf));
struct buffer *buf = xmalloc(sizeof(*buf));
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
yyin = zconf_fopen(name);
yyin = zconf_fopen(file->name);
if (!yyin) {
printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
printf("%s:%d: can't open file \"%s\"\n",
zconf_curname(), zconf_lineno(), file->name);
exit(1);
}
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
buf->parent = current_buf;
current_buf = buf;
if (file->flags & FILE_BUSY) {
printf("%s:%d: do not source '%s' from itself\n",
zconf_curname(), zconf_lineno(), name);
exit(1);
}
if (file->flags & FILE_SCANNED) {
printf("%s:%d: file '%s' is already sourced from '%s'\n",
zconf_curname(), zconf_lineno(), name,
file->parent->name);
exit(1);
for (iter = current_file->parent; iter; iter = iter->parent ) {
if (!strcmp(current_file->name,iter->name) ) {
printf("%s:%d: recursive inclusion detected. "
"Inclusion path:\n current file : '%s'\n",
zconf_curname(), zconf_lineno(),
zconf_curname());
iter = current_file->parent;
while (iter && \
strcmp(iter->name,current_file->name)) {
printf(" included from: '%s:%d'\n",
iter->name, iter->lineno-1);
iter = iter->parent;
}
if (iter)
printf(" included from: '%s:%d'\n",
iter->name, iter->lineno+1);
exit(1);
}
}
file->flags |= FILE_BUSY;
file->lineno = 1;
file->parent = current_file;
current_file = file;
......@@ -334,8 +351,6 @@ static void zconf_endfile(void)
{
struct buffer *parent;
current_file->flags |= FILE_SCANNED;
current_file->flags &= ~FILE_BUSY;
current_file = current_file->parent;
parent = current_buf->parent;
......@@ -353,7 +368,7 @@ int zconf_lineno(void)
return current_pos.lineno;
}
char *zconf_curname(void)
const char *zconf_curname(void)
{
return current_pos.file ? current_pos.file->name : "<none>";
}
#line 3 "scripts/kconfig/lex.zconf.c"
#line 3 "scripts/kconfig/zconf.lex.c_shipped"
#define YY_INT_ALIGNED short int
......@@ -374,323 +374,338 @@ int zconflineno = 1;
extern char *zconftext;
#define yytext_ptr zconftext
static yyconst flex_int16_t yy_nxt[][17] =
static yyconst flex_int16_t yy_nxt[][18] =
{
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0
},
{
11, 12, 13, 14, 12, 12, 15, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12
12, 12, 12, 12, 12, 12, 12, 12
},
{
11, 12, 13, 14, 12, 12, 15, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12
12, 12, 12, 12, 12, 12, 12, 12
},
{
11, 16, 16, 17, 16, 16, 16, 16, 16, 16,
16, 16, 16, 18, 16, 16, 16
16, 18, 16, 16, 16, 16, 16, 16
},
{
11, 16, 16, 17, 16, 16, 16, 16, 16, 16,
16, 16, 16, 18, 16, 16, 16
16, 18, 16, 16, 16, 16, 16, 16
},
{
11, 19, 20, 21, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19
19, 19, 19, 19, 19, 19, 19, 19
},
{
11, 19, 20, 21, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19
19, 19, 19, 19, 19, 19, 19, 19
},
{
11, 22, 22, 23, 22, 24, 22, 22, 24, 22,
22, 22, 22, 22, 22, 25, 22
22, 22, 22, 22, 22, 22, 25, 22
},
{
11, 22, 22, 23, 22, 24, 22, 22, 24, 22,
22, 22, 22, 22, 22, 25, 22
22, 22, 22, 22, 22, 22, 25, 22
},
{
11, 26, 26, 27, 28, 29, 30, 31, 29, 32,
33, 34, 35, 35, 36, 37, 38
11, 26, 27, 28, 29, 30, 31, 32, 30, 33,
34, 35, 35, 36, 37, 38, 39, 40
},
{
11, 26, 26, 27, 28, 29, 30, 31, 29, 32,
33, 34, 35, 35, 36, 37, 38
11, 26, 27, 28, 29, 30, 31, 32, 30, 33,
34, 35, 35, 36, 37, 38, 39, 40
},
{
-11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
-11, -11, -11, -11, -11, -11, -11
-11, -11, -11, -11, -11, -11, -11, -11
},
{
11, -12, -12, -12, -12, -12, -12, -12, -12, -12,
-12, -12, -12, -12, -12, -12, -12
-12, -12, -12, -12, -12, -12, -12, -12
},
{
11, -13, 39, 40, -13, -13, 41, -13, -13, -13,
-13, -13, -13, -13, -13, -13, -13
11, -13, 41, 42, -13, -13, 43, -13, -13, -13,
-13, -13, -13, -13, -13, -13, -13, -13
},
{
11, -14, -14, -14, -14, -14, -14, -14, -14, -14,
-14, -14, -14, -14, -14, -14, -14
-14, -14, -14, -14, -14, -14, -14, -14
},
{
11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42
11, 44, 44, 45, 44, 44, 44, 44, 44, 44,
44, 44, 44, 44, 44, 44, 44, 44
},
{
11, -16, -16, -16, -16, -16, -16, -16, -16, -16,
-16, -16, -16, -16, -16, -16, -16
-16, -16, -16, -16, -16, -16, -16, -16
},
{
11, -17, -17, -17, -17, -17, -17, -17, -17, -17,
-17, -17, -17, -17, -17, -17, -17
-17, -17, -17, -17, -17, -17, -17, -17
},
{
11, -18, -18, -18, -18, -18, -18, -18, -18, -18,
-18, -18, -18, 44, -18, -18, -18
-18, 46, -18, -18, -18, -18, -18, -18
},
{
11, 45, 45, -19, 45, 45, 45, 45, 45, 45,
45, 45, 45, 45, 45, 45, 45
11, 47, 47, -19, 47, 47, 47, 47, 47, 47,
47, 47, 47, 47, 47, 47, 47, 47
},
{
11, -20, 46, 47, -20, -20, -20, -20, -20, -20,
-20, -20, -20, -20, -20, -20, -20
11, -20, 48, 49, -20, -20, -20, -20, -20, -20,
-20, -20, -20, -20, -20, -20, -20, -20
},
{
11, 48, -21, -21, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48
11, 50, -21, -21, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50
},
{
11, 49, 49, 50, 49, -22, 49, 49, -22, 49,
49, 49, 49, 49, 49, -22, 49
11, 51, 51, 52, 51, -22, 51, 51, -22, 51,
51, 51, 51, 51, 51, 51, -22, 51
},
{
11, -23, -23, -23, -23, -23, -23, -23, -23, -23,
-23, -23, -23, -23, -23, -23, -23
-23, -23, -23, -23, -23, -23, -23, -23
},
{
11, -24, -24, -24, -24, -24, -24, -24, -24, -24,
-24, -24, -24, -24, -24, -24, -24
-24, -24, -24, -24, -24, -24, -24, -24
},
{
11, 51, 51, 52, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51
11, 53, 53, 54, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53
},
{
11, -26, -26, -26, -26, -26, -26, -26, -26, -26,
-26, -26, -26, -26, -26, -26, -26
-26, -26, -26, -26, -26, -26, -26, -26
},
{
11, -27, -27, -27, -27, -27, -27, -27, -27, -27,
-27, -27, -27, -27, -27, -27, -27
11, -27, 55, -27, -27, -27, -27, -27, -27, -27,
-27, -27, -27, -27, -27, -27, -27, -27
},
{
11, -28, -28, -28, -28, -28, -28, -28, -28, -28,
-28, -28, -28, -28, 53, -28, -28
-28, -28, -28, -28, -28, -28, -28, -28
},
{
11, -29, -29, -29, -29, -29, -29, -29, -29, -29,
-29, -29, -29, -29, -29, -29, -29
-29, -29, -29, -29, 56, -29, -29, -29
},
{
11, 54, 54, -30, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54
11, -30, -30, -30, -30, -30, -30, -30, -30, -30,
-30, -30, -30, -30, -30, -30, -30, -30
},
{
11, -31, -31, -31, -31, -31, -31, 55, -31, -31,
-31, -31, -31, -31, -31, -31, -31
11, 57, 57, -31, 57, 57, 57, 57, 57, 57,
57, 57, 57, 57, 57, 57, 57, 57
},
{
11, -32, -32, -32, -32, -32, -32, -32, -32, -32,
-32, -32, -32, -32, -32, -32, -32
11, -32, -32, -32, -32, -32, -32, 58, -32, -32,
-32, -32, -32, -32, -32, -32, -32, -32
},
{
11, -33, -33, -33, -33, -33, -33, -33, -33, -33,
-33, -33, -33, -33, -33, -33, -33
-33, -33, -33, -33, -33, -33, -33, -33
},
{
11, -34, -34, -34, -34, -34, -34, -34, -34, -34,
-34, 56, 57, 57, -34, -34, -34
-34, -34, -34, -34, -34, -34, -34, -34
},
{
11, -35, -35, -35, -35, -35, -35, -35, -35, -35,
-35, 57, 57, 57, -35, -35, -35
-35, 59, 59, -35, -35, -35, -35, -35
},
{
11, -36, -36, -36, -36, -36, -36, -36, -36, -36,
-36, -36, -36, -36, -36, -36, -36
-36, -36, -36, -36, 60, -36, -36, -36
},
{
11, -37, -37, 58, -37, -37, -37, -37, -37, -37,
-37, -37, -37, -37, -37, -37, -37
11, -37, -37, -37, -37, -37, -37, -37, -37, -37,
-37, -37, -37, -37, -37, -37, -37, -37
},
{
11, -38, -38, -38, -38, -38, -38, -38, -38, -38,
-38, -38, -38, -38, -38, -38, 59
-38, -38, -38, -38, 61, -38, -38, -38
},
{
11, -39, 39, 40, -39, -39, 41, -39, -39, -39,
-39, -39, -39, -39, -39, -39, -39
11, -39, -39, 62, -39, -39, -39, -39, -39, -39,
-39, -39, -39, -39, -39, -39, -39, -39
},
{
11, -40, -40, -40, -40, -40, -40, -40, -40, -40,
-40, -40, -40, -40, -40, -40, -40
-40, -40, -40, -40, -40, -40, -40, 63
},
{
11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42
11, -41, 41, 42, -41, -41, 43, -41, -41, -41,
-41, -41, -41, -41, -41, -41, -41, -41
},
{
11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42
11, -42, -42, -42, -42, -42, -42, -42, -42, -42,
-42, -42, -42, -42, -42, -42, -42, -42
},
{
11, -43, -43, -43, -43, -43, -43, -43, -43, -43,
-43, -43, -43, -43, -43, -43, -43
11, 44, 44, 45, 44, 44, 44, 44, 44, 44,
44, 44, 44, 44, 44, 44, 44, 44
},
{
11, -44, -44, -44, -44, -44, -44, -44, -44, -44,
-44, -44, -44, 44, -44, -44, -44
11, 44, 44, 45, 44, 44, 44, 44, 44, 44,
44, 44, 44, 44, 44, 44, 44, 44
},
{
11, 45, 45, -45, 45, 45, 45, 45, 45, 45,
45, 45, 45, 45, 45, 45, 45
11, -45, -45, -45, -45, -45, -45, -45, -45, -45,
-45, -45, -45, -45, -45, -45, -45, -45
},
{
11, -46, 46, 47, -46, -46, -46, -46, -46, -46,
-46, -46, -46, -46, -46, -46, -46
11, -46, -46, -46, -46, -46, -46, -46, -46, -46,
-46, 46, -46, -46, -46, -46, -46, -46
},
{
11, 48, -47, -47, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48
11, 47, 47, -47, 47, 47, 47, 47, 47, 47,
47, 47, 47, 47, 47, 47, 47, 47
},
{
11, -48, -48, -48, -48, -48, -48, -48, -48, -48,
-48, -48, -48, -48, -48, -48, -48
11, -48, 48, 49, -48, -48, -48, -48, -48, -48,
-48, -48, -48, -48, -48, -48, -48, -48
},
{
11, 49, 49, 50, 49, -49, 49, 49, -49, 49,
49, 49, 49, 49, 49, -49, 49
11, 50, -49, -49, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50
},
{
11, -50, -50, -50, -50, -50, -50, -50, -50, -50,
-50, -50, -50, -50, -50, -50, -50
-50, -50, -50, -50, -50, -50, -50, -50
},
{
11, -51, -51, 52, -51, -51, -51, -51, -51, -51,
-51, -51, -51, -51, -51, -51, -51
11, 51, 51, 52, 51, -51, 51, 51, -51, 51,
51, 51, 51, 51, 51, 51, -51, 51
},
{
11, -52, -52, -52, -52, -52, -52, -52, -52, -52,
-52, -52, -52, -52, -52, -52, -52
-52, -52, -52, -52, -52, -52, -52, -52
},
{
11, -53, -53, -53, -53, -53, -53, -53, -53, -53,
-53, -53, -53, -53, -53, -53, -53
11, -53, -53, 54, -53, -53, -53, -53, -53, -53,
-53, -53, -53, -53, -53, -53, -53, -53
},
{
11, 54, 54, -54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54
11, -54, -54, -54, -54, -54, -54, -54, -54, -54,
-54, -54, -54, -54, -54, -54, -54, -54
},
{
11, -55, -55, -55, -55, -55, -55, -55, -55, -55,
-55, -55, -55, -55, -55, -55, -55
11, -55, 55, -55, -55, -55, -55, -55, -55, -55,
-55, -55, -55, -55, -55, -55, -55, -55
},
{
11, -56, -56, -56, -56, -56, -56, -56, -56, -56,
-56, 60, 57, 57, -56, -56, -56
-56, -56, -56, -56, -56, -56, -56, -56
},
{
11, -57, -57, -57, -57, -57, -57, -57, -57, -57,
-57, 57, 57, 57, -57, -57, -57
11, 57, 57, -57, 57, 57, 57, 57, 57, 57,
57, 57, 57, 57, 57, 57, 57, 57
},
{
11, -58, -58, -58, -58, -58, -58, -58, -58, -58,
-58, -58, -58, -58, -58, -58, -58
-58, -58, -58, -58, -58, -58, -58, -58
},
{
11, -59, -59, -59, -59, -59, -59, -59, -59, -59,
-59, -59, -59, -59, -59, -59, -59
-59, 59, 59, -59, -59, -59, -59, -59
},
{
11, -60, -60, -60, -60, -60, -60, -60, -60, -60,
-60, 57, 57, 57, -60, -60, -60
-60, -60, -60, -60, -60, -60, -60, -60
},
{
11, -61, -61, -61, -61, -61, -61, -61, -61, -61,
-61, -61, -61, -61, -61, -61, -61, -61
},
{
11, -62, -62, -62, -62, -62, -62, -62, -62, -62,
-62, -62, -62, -62, -62, -62, -62, -62
},
{
11, -63, -63, -63, -63, -63, -63, -63, -63, -63,
-63, -63, -63, -63, -63, -63, -63, -63
},
} ;
......@@ -710,8 +725,8 @@ static void yy_fatal_error (yyconst char msg[] );
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
#define YY_NUM_RULES 33
#define YY_END_OF_BUFFER 34
#define YY_NUM_RULES 37
#define YY_END_OF_BUFFER 38
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
......@@ -719,14 +734,15 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static yyconst flex_int16_t yy_accept[61] =
static yyconst flex_int16_t yy_accept[64] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34, 5, 4, 2, 3, 7, 8, 6, 32, 29,
31, 24, 28, 27, 26, 22, 17, 13, 16, 20,
22, 11, 12, 19, 19, 14, 22, 22, 4, 2,
3, 3, 1, 6, 32, 29, 31, 30, 24, 23,
26, 25, 15, 20, 9, 19, 19, 21, 10, 18
38, 5, 4, 2, 3, 7, 8, 6, 36, 33,
35, 28, 32, 31, 30, 26, 25, 21, 13, 20,
23, 26, 11, 12, 22, 18, 14, 19, 26, 26,
4, 2, 3, 3, 1, 6, 36, 33, 35, 34,
28, 27, 30, 29, 25, 15, 23, 9, 22, 16,
17, 24, 10
} ;
static yyconst flex_int32_t yy_ec[256] =
......@@ -735,16 +751,16 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 4, 5, 6, 1, 1, 7, 8, 9,
10, 1, 1, 1, 11, 12, 12, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 1, 1, 1,
14, 1, 1, 1, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
1, 15, 1, 1, 13, 1, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 1, 16, 1, 1, 1, 1, 1, 1,
10, 1, 1, 1, 11, 12, 12, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 1, 1, 13,
14, 15, 1, 1, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
1, 16, 1, 1, 11, 1, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 1, 17, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
......@@ -785,7 +801,6 @@ char *zconftext;
#include <string.h>
#include <unistd.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
#define START_STRSIZE 16
......@@ -799,8 +814,8 @@ static char *text;
static int text_size, text_asize;
struct buffer {
struct buffer *parent;
YY_BUFFER_STATE state;
struct buffer *parent;
YY_BUFFER_STATE state;
};
struct buffer *current_buf;
......@@ -812,7 +827,7 @@ static void zconf_endfile(void);
static void new_string(void)
{
text = malloc(START_STRSIZE);
text = xmalloc(START_STRSIZE);
text_asize = START_STRSIZE;
text_size = 0;
*text = 0;
......@@ -834,11 +849,18 @@ static void append_string(const char *str, int size)
static void alloc_string(const char *str, int size)
{
text = malloc(size + 1);
text = xmalloc(size + 1);
memcpy(text, str, size);
text[size] = 0;
}
static void warn_ignored_character(char chr)
{
fprintf(stderr,
"%s:%d:warning: ignoring unsupported character '%c'\n",
zconf_curname(), zconf_lineno(), chr);
}
#define INITIAL 0
#define COMMAND 1
#define HELP 2
......@@ -1100,7 +1122,7 @@ YY_RULE_SETUP
case 6:
YY_RULE_SETUP
{
struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
BEGIN(PARAM);
current_pos.file = current_file;
current_pos.lineno = current_file->lineno;
......@@ -1115,7 +1137,7 @@ YY_RULE_SETUP
YY_BREAK
case 7:
YY_RULE_SETUP
warn_ignored_character(*zconftext);
YY_BREAK
case 8:
/* rule 8 can match eol */
......@@ -1157,25 +1179,37 @@ return T_UNEQUAL;
YY_BREAK
case 16:
YY_RULE_SETUP
return T_LESS_EQUAL;
YY_BREAK
case 17:
YY_RULE_SETUP
return T_GREATER_EQUAL;
YY_BREAK
case 18:
YY_RULE_SETUP
return T_LESS;
YY_BREAK
case 19:
YY_RULE_SETUP
return T_GREATER;
YY_BREAK
case 20:
YY_RULE_SETUP
{
str = zconftext[0];
new_string();
BEGIN(STRING);
}
YY_BREAK
case 17:
/* rule 17 can match eol */
case 21:
/* rule 21 can match eol */
YY_RULE_SETUP
BEGIN(INITIAL); current_file->lineno++; return T_EOL;
YY_BREAK
case 18:
YY_RULE_SETUP
/* ignore */
YY_BREAK
case 19:
case 22:
YY_RULE_SETUP
{
struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
if (id && id->flags & TF_PARAM) {
zconflval.id = id;
return id->token;
......@@ -1185,18 +1219,22 @@ YY_RULE_SETUP
return T_WORD;
}
YY_BREAK
case 20:
case 23:
YY_RULE_SETUP
/* comment */
YY_BREAK
case 21:
/* rule 21 can match eol */
case 24:
/* rule 24 can match eol */
YY_RULE_SETUP
current_file->lineno++;
YY_BREAK
case 22:
case 25:
YY_RULE_SETUP
YY_BREAK
case 26:
YY_RULE_SETUP
warn_ignored_character(*zconftext);
YY_BREAK
case YY_STATE_EOF(PARAM):
{
......@@ -1204,8 +1242,8 @@ case YY_STATE_EOF(PARAM):
}
YY_BREAK
case 23:
/* rule 23 can match eol */
case 27:
/* rule 27 can match eol */
*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
(yy_c_buf_p) = yy_cp -= 1;
YY_DO_BEFORE_ACTION; /* set up zconftext again */
......@@ -1216,14 +1254,14 @@ YY_RULE_SETUP
return T_WORD_QUOTE;
}
YY_BREAK
case 24:
case 28:
YY_RULE_SETUP
{
append_string(zconftext, zconfleng);
}
YY_BREAK
case 25:
/* rule 25 can match eol */
case 29:
/* rule 29 can match eol */
*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
(yy_c_buf_p) = yy_cp -= 1;
YY_DO_BEFORE_ACTION; /* set up zconftext again */
......@@ -1234,13 +1272,13 @@ YY_RULE_SETUP
return T_WORD_QUOTE;
}
YY_BREAK
case 26:
case 30:
YY_RULE_SETUP
{
append_string(zconftext + 1, zconfleng - 1);
}
YY_BREAK
case 27:
case 31:
YY_RULE_SETUP
{
if (str == zconftext[0]) {
......@@ -1251,8 +1289,8 @@ YY_RULE_SETUP
append_string(zconftext, 1);
}
YY_BREAK
case 28:
/* rule 28 can match eol */
case 32:
/* rule 32 can match eol */
YY_RULE_SETUP
{
printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
......@@ -1267,7 +1305,7 @@ case YY_STATE_EOF(STRING):
}
YY_BREAK
case 29:
case 33:
YY_RULE_SETUP
{
ts = 0;
......@@ -1292,8 +1330,8 @@ YY_RULE_SETUP
}
}
YY_BREAK
case 30:
/* rule 30 can match eol */
case 34:
/* rule 34 can match eol */
*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
(yy_c_buf_p) = yy_cp -= 1;
YY_DO_BEFORE_ACTION; /* set up zconftext again */
......@@ -1304,15 +1342,15 @@ YY_RULE_SETUP
return T_HELPTEXT;
}
YY_BREAK
case 31:
/* rule 31 can match eol */
case 35:
/* rule 35 can match eol */
YY_RULE_SETUP
{
current_file->lineno++;
append_string("\n", 1);
}
YY_BREAK
case 32:
case 36:
YY_RULE_SETUP
{
while (zconfleng) {
......@@ -1343,7 +1381,7 @@ case YY_STATE_EOF(COMMAND):
yyterminate();
}
YY_BREAK
case 33:
case 37:
YY_RULE_SETUP
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
......@@ -2358,42 +2396,50 @@ void zconf_initscan(const char *name)
exit(1);
}
current_buf = malloc(sizeof(*current_buf));
current_buf = xmalloc(sizeof(*current_buf));
memset(current_buf, 0, sizeof(*current_buf));
current_file = file_lookup(name);
current_file->lineno = 1;
current_file->flags = FILE_BUSY;
}
void zconf_nextfile(const char *name)
{
struct file *iter;
struct file *file = file_lookup(name);
struct buffer *buf = malloc(sizeof(*buf));
struct buffer *buf = xmalloc(sizeof(*buf));
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
zconfin = zconf_fopen(name);
zconfin = zconf_fopen(file->name);
if (!zconfin) {
printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
printf("%s:%d: can't open file \"%s\"\n",
zconf_curname(), zconf_lineno(), file->name);
exit(1);
}
zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
buf->parent = current_buf;
current_buf = buf;
if (file->flags & FILE_BUSY) {
printf("%s:%d: do not source '%s' from itself\n",
zconf_curname(), zconf_lineno(), name);
exit(1);
}
if (file->flags & FILE_SCANNED) {
printf("%s:%d: file '%s' is already sourced from '%s'\n",
zconf_curname(), zconf_lineno(), name,
file->parent->name);
exit(1);
for (iter = current_file->parent; iter; iter = iter->parent ) {
if (!strcmp(current_file->name,iter->name) ) {
printf("%s:%d: recursive inclusion detected. "
"Inclusion path:\n current file : '%s'\n",
zconf_curname(), zconf_lineno(),
zconf_curname());
iter = current_file->parent;
while (iter && \
strcmp(iter->name,current_file->name)) {
printf(" included from: '%s:%d'\n",
iter->name, iter->lineno-1);
iter = iter->parent;
}
if (iter)
printf(" included from: '%s:%d'\n",
iter->name, iter->lineno+1);
exit(1);
}
}
file->flags |= FILE_BUSY;
file->lineno = 1;
file->parent = current_file;
current_file = file;
......@@ -2403,8 +2449,6 @@ static void zconf_endfile(void)
{
struct buffer *parent;
current_file->flags |= FILE_SCANNED;
current_file->flags &= ~FILE_BUSY;
current_file = current_file->parent;
parent = current_buf->parent;
......@@ -2422,7 +2466,7 @@ int zconf_lineno(void)
return current_pos.lineno;
}
char *zconf_curname(void)
const char *zconf_curname(void)
{
return current_pos.file ? current_pos.file->name : "<none>";
}
......
/* A Bison parser, made by GNU Bison 2.5.1. */
/* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton implementation for Bison's Yacc-like parsers in C
/* Bison implementation for Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -46,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
#define YYBISON_VERSION "2.4.1"
#define YYBISON_VERSION "2.5.1"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
......@@ -88,7 +86,6 @@
#include <string.h>
#include <stdbool.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
......@@ -102,22 +99,26 @@ extern int zconflex(void);
static void zconfprint(const char *err, ...);
static void zconf_error(const char *err, ...);
static void zconferror(const char *err);
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
struct symbol *symbol_hash[257];
struct symbol *symbol_hash[SYMBOL_HASHSIZE];
static struct menu *current_menu, *current_entry;
#define YYDEBUG 0
#if YYDEBUG
#define YYERROR_VERBOSE
#endif
# ifndef YY_NULL
# if defined __cplusplus && 201103L <= __cplusplus
# define YY_NULL nullptr
# else
# define YY_NULL 0
# endif
# endif
/* Enabling traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
# define YYDEBUG 1
#endif
/* Enabling verbose error messages. */
......@@ -160,18 +161,23 @@ static struct menu *current_menu, *current_entry;
T_DEFAULT = 275,
T_SELECT = 276,
T_RANGE = 277,
T_OPTION = 278,
T_ON = 279,
T_WORD = 280,
T_WORD_QUOTE = 281,
T_UNEQUAL = 282,
T_CLOSE_PAREN = 283,
T_OPEN_PAREN = 284,
T_EOL = 285,
T_OR = 286,
T_AND = 287,
T_EQUAL = 288,
T_NOT = 289
T_VISIBLE = 278,
T_OPTION = 279,
T_ON = 280,
T_WORD = 281,
T_WORD_QUOTE = 282,
T_UNEQUAL = 283,
T_LESS = 284,
T_LESS_EQUAL = 285,
T_GREATER = 286,
T_GREATER_EQUAL = 287,
T_CLOSE_PAREN = 288,
T_OPEN_PAREN = 289,
T_EOL = 290,
T_OR = 291,
T_AND = 292,
T_EQUAL = 293,
T_NOT = 294
};
#endif
......@@ -187,7 +193,7 @@ typedef union YYSTYPE
struct symbol *symbol;
struct expr *expr;
struct menu *menu;
struct kconf_id *id;
const struct kconf_id *id;
......@@ -254,7 +260,7 @@ typedef short int yytype_int16;
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
# if YYENABLE_NLS
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
......@@ -307,11 +313,12 @@ YYID (yyi)
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# ifndef _STDLIB_H
# define _STDLIB_H 1
/* Use EXIT_SUCCESS as a witness for stdlib.h. */
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
# endif
# endif
# endif
......@@ -334,24 +341,24 @@ YYID (yyi)
# ifndef YYSTACK_ALLOC_MAXIMUM
# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
# endif
# if (defined __cplusplus && ! defined _STDLIB_H \
# if (defined __cplusplus && ! defined EXIT_SUCCESS \
&& ! ((defined YYMALLOC || defined malloc) \
&& (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# ifndef _STDLIB_H
# define _STDLIB_H 1
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
# endif
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
......@@ -380,23 +387,7 @@ union yyalloc
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
/* Copy COUNT objects from FROM to TO. The source and destination do
not overlap. */
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(To, From, Count) \
__builtin_memcpy (To, From, (Count) * sizeof (*(From)))
# else
# define YYCOPY(To, From, Count) \
do \
{ \
YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(To)[yyi] = (From)[yyi]; \
} \
while (YYID (0))
# endif
# endif
# define YYCOPY_NEEDED 1
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
......@@ -416,23 +407,43 @@ union yyalloc
#endif
#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
/* Copy COUNT objects from SRC to DST. The source and destination do
not overlap. */
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(Dst, Src, Count) \
__builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
# else
# define YYCOPY(Dst, Src, Count) \
do \
{ \
YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(Dst)[yyi] = (Src)[yyi]; \
} \
while (YYID (0))
# endif
# endif
#endif /* !YYCOPY_NEEDED */
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 3
#define YYFINAL 11
/* YYLAST -- Last index in YYTABLE. */
#define YYLAST 259
#define YYLAST 298
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 35
#define YYNTOKENS 40
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 46
#define YYNNTS 50
/* YYNRULES -- Number of rules. */
#define YYNRULES 110
#define YYNRULES 122
/* YYNRULES -- Number of states. */
#define YYNSTATES 180
#define YYNSTATES 199
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 289
#define YYMAXUTOK 294
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
......@@ -468,7 +479,8 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39
};
#if YYDEBUG
......@@ -476,73 +488,78 @@ static const yytype_uint8 yytranslate[] =
YYRHS. */
static const yytype_uint16 yyprhs[] =
{
0, 0, 3, 5, 6, 9, 12, 15, 20, 23,
28, 33, 37, 39, 41, 43, 45, 47, 49, 51,
53, 55, 57, 59, 61, 63, 67, 70, 74, 77,
81, 84, 85, 88, 91, 94, 97, 100, 103, 107,
112, 117, 122, 128, 132, 133, 137, 138, 141, 145,
148, 150, 154, 155, 158, 161, 164, 167, 170, 175,
179, 182, 187, 188, 191, 195, 197, 201, 202, 205,
208, 211, 215, 218, 220, 224, 225, 228, 231, 234,
238, 242, 245, 248, 251, 252, 255, 258, 261, 266,
267, 270, 272, 274, 277, 280, 283, 285, 288, 289,
292, 294, 298, 302, 306, 309, 313, 317, 319, 321,
322
0, 0, 3, 6, 8, 11, 13, 14, 17, 20,
23, 26, 31, 36, 40, 42, 44, 46, 48, 50,
52, 54, 56, 58, 60, 62, 64, 66, 68, 72,
75, 79, 82, 86, 89, 90, 93, 96, 99, 102,
105, 108, 112, 117, 122, 127, 133, 137, 138, 142,
143, 146, 150, 153, 155, 159, 160, 163, 166, 169,
172, 175, 180, 184, 187, 192, 193, 196, 200, 202,
206, 207, 210, 213, 216, 220, 224, 228, 230, 234,
235, 238, 241, 244, 248, 252, 255, 258, 261, 262,
265, 268, 271, 276, 277, 280, 283, 286, 287, 290,
292, 294, 297, 300, 303, 305, 308, 309, 312, 314,
318, 322, 326, 330, 334, 338, 342, 345, 349, 353,
355, 357, 358
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
36, 0, -1, 37, -1, -1, 37, 39, -1, 37,
53, -1, 37, 64, -1, 37, 3, 74, 76, -1,
37, 75, -1, 37, 25, 1, 30, -1, 37, 38,
1, 30, -1, 37, 1, 30, -1, 16, -1, 18,
-1, 19, -1, 21, -1, 17, -1, 22, -1, 20,
-1, 30, -1, 59, -1, 68, -1, 42, -1, 44,
-1, 66, -1, 25, 1, 30, -1, 1, 30, -1,
10, 25, 30, -1, 41, 45, -1, 11, 25, 30,
-1, 43, 45, -1, -1, 45, 46, -1, 45, 47,
-1, 45, 72, -1, 45, 70, -1, 45, 40, -1,
45, 30, -1, 19, 73, 30, -1, 18, 74, 77,
30, -1, 20, 78, 77, 30, -1, 21, 25, 77,
30, -1, 22, 79, 79, 77, 30, -1, 23, 48,
30, -1, -1, 48, 25, 49, -1, -1, 33, 74,
-1, 7, 80, 30, -1, 50, 54, -1, 75, -1,
51, 56, 52, -1, -1, 54, 55, -1, 54, 72,
-1, 54, 70, -1, 54, 30, -1, 54, 40, -1,
18, 74, 77, 30, -1, 19, 73, 30, -1, 17,
30, -1, 20, 25, 77, 30, -1, -1, 56, 39,
-1, 14, 78, 76, -1, 75, -1, 57, 60, 58,
-1, -1, 60, 39, -1, 60, 64, -1, 60, 53,
-1, 4, 74, 30, -1, 61, 71, -1, 75, -1,
62, 65, 63, -1, -1, 65, 39, -1, 65, 64,
-1, 65, 53, -1, 6, 74, 30, -1, 9, 74,
30, -1, 67, 71, -1, 12, 30, -1, 69, 13,
-1, -1, 71, 72, -1, 71, 30, -1, 71, 40,
-1, 16, 24, 78, 30, -1, -1, 74, 77, -1,
25, -1, 26, -1, 5, 30, -1, 8, 30, -1,
15, 30, -1, 30, -1, 76, 30, -1, -1, 14,
78, -1, 79, -1, 79, 33, 79, -1, 79, 27,
79, -1, 29, 78, 28, -1, 34, 78, -1, 78,
31, 78, -1, 78, 32, 78, -1, 25, -1, 26,
-1, -1, 25, -1
41, 0, -1, 85, 42, -1, 42, -1, 67, 43,
-1, 43, -1, -1, 43, 45, -1, 43, 59, -1,
43, 71, -1, 43, 84, -1, 43, 26, 1, 35,
-1, 43, 44, 1, 35, -1, 43, 1, 35, -1,
16, -1, 18, -1, 19, -1, 21, -1, 17, -1,
22, -1, 20, -1, 23, -1, 35, -1, 65, -1,
75, -1, 48, -1, 50, -1, 73, -1, 26, 1,
35, -1, 1, 35, -1, 10, 26, 35, -1, 47,
51, -1, 11, 26, 35, -1, 49, 51, -1, -1,
51, 52, -1, 51, 53, -1, 51, 79, -1, 51,
77, -1, 51, 46, -1, 51, 35, -1, 19, 82,
35, -1, 18, 83, 86, 35, -1, 20, 87, 86,
35, -1, 21, 26, 86, 35, -1, 22, 88, 88,
86, 35, -1, 24, 54, 35, -1, -1, 54, 26,
55, -1, -1, 38, 83, -1, 7, 89, 35, -1,
56, 60, -1, 84, -1, 57, 62, 58, -1, -1,
60, 61, -1, 60, 79, -1, 60, 77, -1, 60,
35, -1, 60, 46, -1, 18, 83, 86, 35, -1,
19, 82, 35, -1, 17, 35, -1, 20, 26, 86,
35, -1, -1, 62, 45, -1, 14, 87, 85, -1,
84, -1, 63, 66, 64, -1, -1, 66, 45, -1,
66, 71, -1, 66, 59, -1, 3, 83, 85, -1,
4, 83, 35, -1, 68, 80, 78, -1, 84, -1,
69, 72, 70, -1, -1, 72, 45, -1, 72, 71,
-1, 72, 59, -1, 6, 83, 35, -1, 9, 83,
35, -1, 74, 78, -1, 12, 35, -1, 76, 13,
-1, -1, 78, 79, -1, 78, 35, -1, 78, 46,
-1, 16, 25, 87, 35, -1, -1, 80, 81, -1,
80, 35, -1, 23, 86, -1, -1, 83, 86, -1,
26, -1, 27, -1, 5, 35, -1, 8, 35, -1,
15, 35, -1, 35, -1, 85, 35, -1, -1, 14,
87, -1, 88, -1, 88, 29, 88, -1, 88, 30,
88, -1, 88, 31, 88, -1, 88, 32, 88, -1,
88, 38, 88, -1, 88, 28, 88, -1, 34, 87,
33, -1, 39, 87, -1, 87, 36, 87, -1, 87,
37, 87, -1, 26, -1, 27, -1, -1, 26, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
0, 107, 107, 109, 111, 112, 113, 114, 115, 116,
117, 121, 125, 125, 125, 125, 125, 125, 125, 129,
130, 131, 132, 133, 134, 138, 139, 145, 153, 159,
167, 177, 179, 180, 181, 182, 183, 184, 187, 195,
201, 211, 217, 223, 226, 228, 239, 240, 245, 254,
259, 267, 270, 272, 273, 274, 275, 276, 279, 285,
296, 302, 312, 314, 319, 327, 335, 338, 340, 341,
342, 347, 354, 359, 367, 370, 372, 373, 374, 377,
385, 392, 399, 405, 412, 414, 415, 416, 419, 427,
429, 434, 435, 438, 439, 440, 444, 445, 448, 449,
452, 453, 454, 455, 456, 457, 458, 461, 462, 465,
466
0, 108, 108, 108, 110, 110, 112, 114, 115, 116,
117, 118, 119, 123, 127, 127, 127, 127, 127, 127,
127, 127, 131, 132, 133, 134, 135, 136, 140, 141,
147, 155, 161, 169, 179, 181, 182, 183, 184, 185,
186, 189, 197, 203, 213, 219, 225, 228, 230, 241,
242, 247, 256, 261, 269, 272, 274, 275, 276, 277,
278, 281, 287, 298, 304, 314, 316, 321, 329, 337,
340, 342, 343, 344, 349, 356, 363, 368, 376, 379,
381, 382, 383, 386, 394, 401, 408, 414, 421, 423,
424, 425, 428, 436, 438, 439, 442, 449, 451, 456,
457, 460, 461, 462, 466, 467, 470, 471, 474, 475,
476, 477, 478, 479, 480, 481, 482, 483, 484, 487,
488, 491, 492
};
#endif
......@@ -555,19 +572,20 @@ static const char *const yytname[] =
"T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
"T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
"T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
"T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
"T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
"T_LESS", "T_LESS_EQUAL", "T_GREATER", "T_GREATER_EQUAL",
"T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
"T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt",
"option_error", "config_entry_start", "config_stmt",
"T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
"common_stmt", "option_error", "config_entry_start", "config_stmt",
"menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
"config_option", "symbol_option", "symbol_option_list",
"symbol_option_arg", "choice", "choice_entry", "choice_end",
"choice_stmt", "choice_option_list", "choice_option", "choice_block",
"if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry",
"menu_end", "menu_stmt", "menu_block", "source_stmt", "comment",
"comment_stmt", "help_start", "help", "depends_list", "depends",
"prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol",
"word_opt", 0
"if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu",
"menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
"comment", "comment_stmt", "help_start", "help", "depends_list",
"depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
"end", "nl", "if_expr", "expr", "symbol", "word_opt", YY_NULL
};
#endif
......@@ -579,201 +597,222 @@ static const yytype_uint16 yytoknum[] =
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289
285, 286, 287, 288, 289, 290, 291, 292, 293, 294
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
0, 35, 36, 37, 37, 37, 37, 37, 37, 37,
37, 37, 38, 38, 38, 38, 38, 38, 38, 39,
39, 39, 39, 39, 39, 40, 40, 41, 42, 43,
44, 45, 45, 45, 45, 45, 45, 45, 46, 46,
46, 46, 46, 47, 48, 48, 49, 49, 50, 51,
52, 53, 54, 54, 54, 54, 54, 54, 55, 55,
55, 55, 56, 56, 57, 58, 59, 60, 60, 60,
60, 61, 62, 63, 64, 65, 65, 65, 65, 66,
67, 68, 69, 70, 71, 71, 71, 71, 72, 73,
73, 74, 74, 75, 75, 75, 76, 76, 77, 77,
78, 78, 78, 78, 78, 78, 78, 79, 79, 80,
80
0, 40, 41, 41, 42, 42, 43, 43, 43, 43,
43, 43, 43, 43, 44, 44, 44, 44, 44, 44,
44, 44, 45, 45, 45, 45, 45, 45, 46, 46,
47, 48, 49, 50, 51, 51, 51, 51, 51, 51,
51, 52, 52, 52, 52, 52, 53, 54, 54, 55,
55, 56, 57, 58, 59, 60, 60, 60, 60, 60,
60, 61, 61, 61, 61, 62, 62, 63, 64, 65,
66, 66, 66, 66, 67, 68, 69, 70, 71, 72,
72, 72, 72, 73, 74, 75, 76, 77, 78, 78,
78, 78, 79, 80, 80, 80, 81, 82, 82, 83,
83, 84, 84, 84, 85, 85, 86, 86, 87, 87,
87, 87, 87, 87, 87, 87, 87, 87, 87, 88,
88, 89, 89
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
0, 2, 1, 0, 2, 2, 2, 4, 2, 4,
4, 3, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 3, 2, 3, 2, 3,
2, 0, 2, 2, 2, 2, 2, 2, 3, 4,
4, 4, 5, 3, 0, 3, 0, 2, 3, 2,
1, 3, 0, 2, 2, 2, 2, 2, 4, 3,
2, 4, 0, 2, 3, 1, 3, 0, 2, 2,
2, 3, 2, 1, 3, 0, 2, 2, 2, 3,
3, 2, 2, 2, 0, 2, 2, 2, 4, 0,
2, 1, 1, 2, 2, 2, 1, 2, 0, 2,
1, 3, 3, 3, 2, 3, 3, 1, 1, 0,
1
0, 2, 2, 1, 2, 1, 0, 2, 2, 2,
2, 4, 4, 3, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 3, 2,
3, 2, 3, 2, 0, 2, 2, 2, 2, 2,
2, 3, 4, 4, 4, 5, 3, 0, 3, 0,
2, 3, 2, 1, 3, 0, 2, 2, 2, 2,
2, 4, 3, 2, 4, 0, 2, 3, 1, 3,
0, 2, 2, 2, 3, 3, 3, 1, 3, 0,
2, 2, 2, 3, 3, 2, 2, 2, 0, 2,
2, 2, 4, 0, 2, 2, 2, 0, 2, 1,
1, 2, 2, 2, 1, 2, 0, 2, 1, 3,
3, 3, 3, 3, 3, 3, 2, 3, 3, 1,
1, 0, 1
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
STATE-NUM when YYTABLE doesn't specify something else to do. Zero
/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
Performed when YYTABLE doesn't specify something else to do. Zero
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
3, 0, 0, 1, 0, 0, 0, 0, 0, 109,
0, 0, 0, 0, 0, 0, 12, 16, 13, 14,
18, 15, 17, 0, 19, 0, 4, 31, 22, 31,
23, 52, 62, 5, 67, 20, 84, 75, 6, 24,
84, 21, 8, 11, 91, 92, 0, 0, 93, 0,
110, 0, 94, 0, 0, 0, 107, 108, 0, 0,
0, 100, 95, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 96, 7, 71, 79, 48, 80, 27,
29, 0, 104, 0, 0, 64, 0, 0, 9, 10,
0, 0, 0, 0, 89, 0, 0, 0, 44, 0,
37, 36, 32, 33, 0, 35, 34, 0, 0, 89,
0, 56, 57, 53, 55, 54, 63, 51, 50, 68,
70, 66, 69, 65, 86, 87, 85, 76, 78, 74,
77, 73, 97, 103, 105, 106, 102, 101, 26, 82,
0, 98, 0, 98, 98, 98, 0, 0, 0, 83,
60, 98, 0, 98, 0, 0, 0, 38, 90, 0,
0, 98, 46, 43, 25, 0, 59, 0, 88, 99,
39, 40, 41, 0, 0, 45, 58, 61, 42, 47
6, 0, 104, 0, 3, 0, 6, 6, 99, 100,
0, 1, 0, 0, 0, 0, 121, 0, 0, 0,
0, 0, 0, 14, 18, 15, 16, 20, 17, 19,
21, 0, 22, 0, 7, 34, 25, 34, 26, 55,
65, 8, 70, 23, 93, 79, 9, 27, 88, 24,
10, 0, 105, 2, 74, 13, 0, 101, 0, 122,
0, 102, 0, 0, 0, 119, 120, 0, 0, 0,
108, 103, 0, 0, 0, 0, 0, 0, 0, 88,
0, 0, 75, 83, 51, 84, 30, 32, 0, 116,
0, 0, 67, 0, 0, 0, 0, 0, 0, 11,
12, 0, 0, 0, 0, 97, 0, 0, 0, 47,
0, 40, 39, 35, 36, 0, 38, 37, 0, 0,
97, 0, 59, 60, 56, 58, 57, 66, 54, 53,
71, 73, 69, 72, 68, 106, 95, 0, 94, 80,
82, 78, 81, 77, 90, 91, 89, 115, 117, 118,
114, 109, 110, 111, 112, 113, 29, 86, 0, 106,
0, 106, 106, 106, 0, 0, 0, 87, 63, 106,
0, 106, 0, 96, 0, 0, 41, 98, 0, 0,
106, 49, 46, 28, 0, 62, 0, 107, 92, 42,
43, 44, 0, 0, 48, 61, 64, 45, 50
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
-1, 1, 2, 25, 26, 101, 27, 28, 29, 30,
65, 102, 103, 147, 175, 31, 32, 117, 33, 67,
113, 68, 34, 121, 35, 69, 36, 37, 129, 38,
71, 39, 40, 41, 104, 105, 70, 106, 142, 143,
42, 74, 156, 60, 61, 51
-1, 3, 4, 5, 33, 34, 112, 35, 36, 37,
38, 74, 113, 114, 165, 194, 39, 40, 128, 41,
76, 124, 77, 42, 132, 43, 78, 6, 44, 45,
141, 46, 80, 47, 48, 49, 115, 116, 81, 117,
79, 138, 160, 161, 50, 7, 173, 69, 70, 60
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
#define YYPACT_NINF -80
#define YYPACT_NINF -91
static const yytype_int16 yypact[] =
{
-80, 2, 132, -80, -13, -1, -1, -2, -1, 9,
33, -1, 27, 40, -3, 38, -80, -80, -80, -80,
-80, -80, -80, 71, -80, 77, -80, -80, -80, -80,
-80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
-80, -80, -80, -80, -80, -80, 57, 61, -80, 63,
-80, 76, -80, 87, 101, 133, -80, -80, -3, -3,
195, -6, -80, 136, 149, 39, 104, 65, 150, 5,
194, 5, 167, -80, 176, -80, -80, -80, -80, -80,
-80, 68, -80, -3, -3, 176, 72, 72, -80, -80,
177, 187, 78, -1, -1, -3, 196, 72, -80, 222,
-80, -80, -80, -80, 221, -80, -80, 205, -1, -1,
211, -80, -80, -80, -80, -80, -80, -80, -80, -80,
-80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
-80, -80, -80, -80, 206, -80, -80, -80, -80, -80,
-3, 223, 209, 223, 197, 223, 72, 7, 210, -80,
-80, 223, 212, 223, 201, -3, 213, -80, -80, 214,
215, 223, 208, -80, -80, 216, -80, 217, -80, 113,
-80, -80, -80, 218, -1, -80, -80, -80, -80, -80
19, 37, -91, 13, -91, 79, -91, 20, -91, -91,
-16, -91, 21, 37, 25, 37, 41, 36, 37, 78,
83, 31, 56, -91, -91, -91, -91, -91, -91, -91,
-91, 116, -91, 127, -91, -91, -91, -91, -91, -91,
-91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
-91, 147, -91, -91, 105, -91, 109, -91, 111, -91,
114, -91, 136, 137, 142, -91, -91, 31, 31, 76,
254, -91, 143, 146, 27, 115, 207, 258, 243, -14,
243, 179, -91, -91, -91, -91, -91, -91, -7, -91,
31, 31, 105, 51, 51, 51, 51, 51, 51, -91,
-91, 156, 168, 181, 37, 37, 31, 178, 51, -91,
206, -91, -91, -91, -91, 196, -91, -91, 175, 37,
37, 185, -91, -91, -91, -91, -91, -91, -91, -91,
-91, -91, -91, -91, -91, 214, -91, 230, -91, -91,
-91, -91, -91, -91, -91, -91, -91, -91, 183, -91,
-91, -91, -91, -91, -91, -91, -91, -91, 31, 214,
194, 214, 45, 214, 51, 26, 195, -91, -91, 214,
197, 214, 31, -91, 139, 208, -91, -91, 220, 224,
214, 222, -91, -91, 226, -91, 227, 123, -91, -91,
-91, -91, 235, 37, -91, -91, -91, -91, -91
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
-80, -80, -80, -80, 122, -34, -80, -80, -80, -80,
220, -80, -80, -80, -80, -80, -80, -80, 59, -80,
-80, -80, -80, -80, -80, -80, -80, -80, -80, 125,
-80, -80, -80, -80, -80, 183, 219, 22, 142, -5,
147, 192, 69, -54, -79, -80
-91, -91, 264, 268, -91, 30, -65, -91, -91, -91,
-91, 238, -91, -91, -91, -91, -91, -91, -91, -12,
-91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
-91, -5, -91, -91, -91, -91, -91, 200, 209, -61,
-91, -91, 170, -1, 65, 0, 118, -66, -90, -91
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -82
number is the opposite. If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -86
static const yytype_int16 yytable[] =
{
46, 47, 3, 49, 81, 82, 53, 136, 137, 6,
7, 8, 9, 10, 11, 12, 13, 43, 146, 14,
15, 86, 56, 57, 44, 45, 58, 87, 48, 134,
135, 59, 162, 112, 50, 24, 125, 163, 125, -28,
90, 144, -28, -28, -28, -28, -28, -28, -28, -28,
-28, 91, 54, -28, -28, 92, -28, 93, 94, 95,
96, 97, 98, 52, 99, 55, 90, 161, 62, 100,
-49, -49, 63, -49, -49, -49, -49, 91, 64, -49,
-49, 92, 107, 108, 109, 110, 154, 73, 141, 115,
99, 75, 126, 76, 126, 111, 133, 56, 57, 83,
84, 169, 140, 151, -30, 90, 77, -30, -30, -30,
-30, -30, -30, -30, -30, -30, 91, 78, -30, -30,
92, -30, 93, 94, 95, 96, 97, 98, 120, 99,
128, 79, -2, 4, 100, 5, 6, 7, 8, 9,
10, 11, 12, 13, 83, 84, 14, 15, 16, 17,
18, 19, 20, 21, 22, 7, 8, 23, 10, 11,
12, 13, 24, 80, 14, 15, 88, -81, 90, 179,
-81, -81, -81, -81, -81, -81, -81, -81, -81, 89,
24, -81, -81, 92, -81, -81, -81, -81, -81, -81,
116, 119, 99, 127, 122, 90, 130, 124, -72, -72,
-72, -72, -72, -72, -72, -72, 132, 138, -72, -72,
92, 155, 158, 159, 160, 118, 123, 139, 131, 99,
165, 145, 167, 148, 124, 73, 83, 84, 83, 84,
173, 168, 83, 84, 149, 150, 153, 155, 84, 157,
164, 174, 166, 170, 171, 172, 176, 177, 178, 66,
114, 152, 85, 0, 0, 0, 0, 0, 0, 72
10, 88, 89, 150, 151, 152, 153, 154, 155, 135,
54, 123, 56, 11, 58, 126, 145, 62, 164, 2,
146, 136, 1, 1, 148, 149, 147, -31, 101, 90,
91, -31, -31, -31, -31, -31, -31, -31, -31, 102,
162, -31, -31, 103, -31, 104, 105, 106, 107, 108,
-31, 109, 181, 110, 2, 52, 55, 65, 66, 172,
57, 182, 111, 8, 9, 67, 131, 59, 140, 92,
68, 61, 145, 133, 180, 142, 146, 65, 66, -5,
12, 90, 91, 13, 14, 15, 16, 17, 18, 19,
20, 71, 174, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 159, 63, 31, 187, 127, 130, 64,
139, 2, 90, 91, 32, -33, 101, 72, 169, -33,
-33, -33, -33, -33, -33, -33, -33, 102, 73, -33,
-33, 103, -33, 104, 105, 106, 107, 108, -33, 109,
52, 110, 129, 134, 82, 143, 83, -4, 12, 84,
111, 13, 14, 15, 16, 17, 18, 19, 20, 90,
91, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 85, 86, 31, 188, 90, 91, 87, 99, -85,
101, 100, 32, -85, -85, -85, -85, -85, -85, -85,
-85, 156, 198, -85, -85, 103, -85, -85, -85, -85,
-85, -85, -85, 157, 163, 110, 158, 166, 101, 167,
168, 171, -52, -52, 144, -52, -52, -52, -52, 102,
91, -52, -52, 103, 118, 119, 120, 121, 172, 176,
183, 101, 185, 110, -76, -76, -76, -76, -76, -76,
-76, -76, 122, 189, -76, -76, 103, 13, 14, 15,
16, 17, 18, 19, 20, 190, 110, 21, 22, 191,
193, 195, 196, 14, 15, 144, 17, 18, 19, 20,
197, 53, 21, 22, 51, 75, 125, 175, 32, 177,
178, 179, 93, 94, 95, 96, 97, 184, 137, 186,
170, 0, 98, 32, 0, 0, 0, 0, 192
};
#define yypact_value_is_default(yystate) \
((yystate) == (-91))
#define yytable_value_is_error(yytable_value) \
YYID (0)
static const yytype_int16 yycheck[] =
{
5, 6, 0, 8, 58, 59, 11, 86, 87, 4,
5, 6, 7, 8, 9, 10, 11, 30, 97, 14,
15, 27, 25, 26, 25, 26, 29, 33, 30, 83,
84, 34, 25, 67, 25, 30, 70, 30, 72, 0,
1, 95, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 25, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 30, 25, 25, 1, 146, 30, 30,
5, 6, 1, 8, 9, 10, 11, 12, 1, 14,
15, 16, 17, 18, 19, 20, 140, 30, 93, 67,
25, 30, 70, 30, 72, 30, 28, 25, 26, 31,
32, 155, 24, 108, 0, 1, 30, 3, 4, 5,
6, 7, 8, 9, 10, 11, 12, 30, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 69, 25,
71, 30, 0, 1, 30, 3, 4, 5, 6, 7,
8, 9, 10, 11, 31, 32, 14, 15, 16, 17,
18, 19, 20, 21, 22, 5, 6, 25, 8, 9,
10, 11, 30, 30, 14, 15, 30, 0, 1, 174,
3, 4, 5, 6, 7, 8, 9, 10, 11, 30,
30, 14, 15, 16, 17, 18, 19, 20, 21, 22,
68, 69, 25, 71, 69, 1, 71, 30, 4, 5,
6, 7, 8, 9, 10, 11, 30, 30, 14, 15,
16, 14, 143, 144, 145, 68, 69, 30, 71, 25,
151, 25, 153, 1, 30, 30, 31, 32, 31, 32,
161, 30, 31, 32, 13, 30, 25, 14, 32, 30,
30, 33, 30, 30, 30, 30, 30, 30, 30, 29,
67, 109, 60, -1, -1, -1, -1, -1, -1, 40
1, 67, 68, 93, 94, 95, 96, 97, 98, 23,
10, 76, 13, 0, 15, 76, 81, 18, 108, 35,
81, 35, 3, 3, 90, 91, 33, 0, 1, 36,
37, 4, 5, 6, 7, 8, 9, 10, 11, 12,
106, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 26, 26, 35, 35, 35, 26, 27, 14,
35, 35, 35, 26, 27, 34, 78, 26, 80, 69,
39, 35, 137, 78, 164, 80, 137, 26, 27, 0,
1, 36, 37, 4, 5, 6, 7, 8, 9, 10,
11, 35, 158, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 104, 26, 26, 172, 77, 78, 26,
80, 35, 36, 37, 35, 0, 1, 1, 119, 4,
5, 6, 7, 8, 9, 10, 11, 12, 1, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
35, 26, 77, 78, 35, 80, 35, 0, 1, 35,
35, 4, 5, 6, 7, 8, 9, 10, 11, 36,
37, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 35, 35, 26, 35, 36, 37, 35, 35, 0,
1, 35, 35, 4, 5, 6, 7, 8, 9, 10,
11, 35, 193, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 35, 26, 26, 25, 1, 1, 13,
35, 26, 5, 6, 35, 8, 9, 10, 11, 12,
37, 14, 15, 16, 17, 18, 19, 20, 14, 35,
35, 1, 35, 26, 4, 5, 6, 7, 8, 9,
10, 11, 35, 35, 14, 15, 16, 4, 5, 6,
7, 8, 9, 10, 11, 35, 26, 14, 15, 35,
38, 35, 35, 5, 6, 35, 8, 9, 10, 11,
35, 7, 14, 15, 6, 37, 76, 159, 35, 161,
162, 163, 28, 29, 30, 31, 32, 169, 79, 171,
120, -1, 38, 35, -1, -1, -1, -1, 180
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
0, 36, 37, 0, 1, 3, 4, 5, 6, 7,
8, 9, 10, 11, 14, 15, 16, 17, 18, 19,
20, 21, 22, 25, 30, 38, 39, 41, 42, 43,
44, 50, 51, 53, 57, 59, 61, 62, 64, 66,
67, 68, 75, 30, 25, 26, 74, 74, 30, 74,
25, 80, 30, 74, 25, 25, 25, 26, 29, 34,
78, 79, 30, 1, 1, 45, 45, 54, 56, 60,
71, 65, 71, 30, 76, 30, 30, 30, 30, 30,
30, 78, 78, 31, 32, 76, 27, 33, 30, 30,
1, 12, 16, 18, 19, 20, 21, 22, 23, 25,
30, 40, 46, 47, 69, 70, 72, 17, 18, 19,
20, 30, 40, 55, 70, 72, 39, 52, 75, 39,
53, 58, 64, 75, 30, 40, 72, 39, 53, 63,
64, 75, 30, 28, 78, 78, 79, 79, 30, 30,
24, 74, 73, 74, 78, 25, 79, 48, 1, 13,
30, 74, 73, 25, 78, 14, 77, 30, 77, 77,
77, 79, 25, 30, 30, 77, 30, 77, 30, 78,
30, 30, 30, 77, 33, 49, 30, 30, 30, 74
0, 3, 35, 41, 42, 43, 67, 85, 26, 27,
83, 0, 1, 4, 5, 6, 7, 8, 9, 10,
11, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 26, 35, 44, 45, 47, 48, 49, 50, 56,
57, 59, 63, 65, 68, 69, 71, 73, 74, 75,
84, 43, 35, 42, 85, 35, 83, 35, 83, 26,
89, 35, 83, 26, 26, 26, 27, 34, 39, 87,
88, 35, 1, 1, 51, 51, 60, 62, 66, 80,
72, 78, 35, 35, 35, 35, 35, 35, 87, 87,
36, 37, 85, 28, 29, 30, 31, 32, 38, 35,
35, 1, 12, 16, 18, 19, 20, 21, 22, 24,
26, 35, 46, 52, 53, 76, 77, 79, 17, 18,
19, 20, 35, 46, 61, 77, 79, 45, 58, 84,
45, 59, 64, 71, 84, 23, 35, 78, 81, 45,
59, 70, 71, 84, 35, 46, 79, 33, 87, 87,
88, 88, 88, 88, 88, 88, 35, 35, 25, 83,
82, 83, 87, 26, 88, 54, 1, 13, 35, 83,
82, 26, 14, 86, 87, 86, 35, 86, 86, 86,
88, 26, 35, 35, 86, 35, 86, 87, 35, 35,
35, 35, 86, 38, 55, 35, 35, 35, 83
};
#define yyerrok (yyerrstatus = 0)
......@@ -788,24 +827,33 @@ static const yytype_uint8 yystos[] =
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
Once GCC version 2 has supplanted version 1, this can go. */
Once GCC version 2 has supplanted version 1, this can go. However,
YYFAIL appears to be in use. Nevertheless, it is formally deprecated
in Bison 2.4.2's NEWS entry, where a plan to phase it out is
discussed. */
#define YYFAIL goto yyerrlab
#if defined YYFAIL
/* This is here to suppress warnings from the GCC cpp's
-Wunused-macros. Normally we don't worry about that warning, but
some users do, and we want to make it easy for users to remove
YYFAIL uses, which will produce warnings from Bison 2.5. */
#endif
#define YYRECOVERING() (!!yyerrstatus)
#define YYBACKUP(Token, Value) \
do \
if (yychar == YYEMPTY && yylen == 1) \
{ \
yychar = (Token); \
yylval = (Value); \
yytoken = YYTRANSLATE (yychar); \
YYPOPSTACK (1); \
goto yybackup; \
} \
else \
{ \
#define YYBACKUP(Token, Value) \
do \
if (yychar == YYEMPTY) \
{ \
yychar = (Token); \
yylval = (Value); \
YYPOPSTACK (yylen); \
yystate = *yyssp; \
goto yybackup; \
} \
else \
{ \
yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
......@@ -842,19 +890,10 @@ while (YYID (0))
#endif
/* YY_LOCATION_PRINT -- Print the location on the stream.
This macro was not mandated originally: define only if we know
we won't break user code: when these are the locations we know. */
/* This macro is provided for backward compatibility. */
#ifndef YY_LOCATION_PRINT
# if YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
(Loc).last_line, (Loc).last_column)
# else
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
# endif
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
#endif
......@@ -909,6 +948,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
YYSTYPE const * const yyvaluep;
#endif
{
FILE *yyo = yyoutput;
YYUSE (yyo);
if (!yyvaluep)
return;
# ifdef YYPRINT
......@@ -1046,7 +1087,6 @@ int yydebug;
# define YYMAXDEPTH 10000
#endif
#if YYERROR_VERBOSE
......@@ -1149,115 +1189,142 @@ yytnamerr (char *yyres, const char *yystr)
}
# endif
/* Copy into YYRESULT an error message about the unexpected token
YYCHAR while in state YYSTATE. Return the number of bytes copied,
including the terminating null byte. If YYRESULT is null, do not
copy anything; just return the number of bytes that would be
copied. As a special case, return 0 if an ordinary "syntax error"
message will do. Return YYSIZE_MAXIMUM if overflow occurs during
size calculation. */
static YYSIZE_T
yysyntax_error (char *yyresult, int yystate, int yychar)
{
int yyn = yypact[yystate];
/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
about the unexpected token YYTOKEN for the state stack whose top is
YYSSP.
if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
return 0;
else
Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
not large enough to hold the message. In that case, also set
*YYMSG_ALLOC to the required number of bytes. Return 2 if the
required number of bytes is too large to store. */
static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yytype_int16 *yyssp, int yytoken)
{
YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
YYSIZE_T yysize = yysize0;
YYSIZE_T yysize1;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */
const char *yyformat = YY_NULL;
/* Arguments of yyformat. */
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
/* Number of reported tokens (one for the "unexpected", one per
"expected"). */
int yycount = 0;
/* There are many possibilities here to consider:
- Assume YYFAIL is not used. It's too flawed to consider. See
<http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
for details. YYERROR is fine as it does not invoke this
function.
- If this state is a consistent state with a default action, then
the only way this function was invoked is if the default action
is an error action. In that case, don't check for expected
tokens because there are none.
- The only way there can be no lookahead present (in yychar) is if
this state is a consistent state with a default action. Thus,
detecting the absence of a lookahead is sufficient to determine
that there is no unexpected or expected token to report. In that
case, just report a simple "syntax error".
- Don't assume there isn't a lookahead just because this state is a
consistent state with a default action. There might have been a
previous inconsistent state, consistent state with a non-default
action, or user semantic action that manipulated yychar.
- Of course, the expected token list depends on states to have
correct lookahead information, and it depends on the parser not
to perform extra reductions after fetching a lookahead from the
scanner and before detecting a syntax error. Thus, state merging
(from LALR or IELR) and default reductions corrupt the expected
token list. However, the list is correct for canonical LR with
one exception: it will still contain any token that will not be
accepted due to an error action in a later state.
*/
if (yytoken != YYEMPTY)
{
int yytype = YYTRANSLATE (yychar);
YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
YYSIZE_T yysize = yysize0;
YYSIZE_T yysize1;
int yysize_overflow = 0;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
int yyx;
# if 0
/* This is so xgettext sees the translatable formats that are
constructed on the fly. */
YY_("syntax error, unexpected %s");
YY_("syntax error, unexpected %s, expecting %s");
YY_("syntax error, unexpected %s, expecting %s or %s");
YY_("syntax error, unexpected %s, expecting %s or %s or %s");
YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
# endif
char *yyfmt;
char const *yyf;
static char const yyunexpected[] = "syntax error, unexpected %s";
static char const yyexpecting[] = ", expecting %s";
static char const yyor[] = " or %s";
char yyformat[sizeof yyunexpected
+ sizeof yyexpecting - 1
+ ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
* (sizeof yyor - 1))];
char const *yyprefix = yyexpecting;
/* Start YYX at -YYN if negative to avoid negative indexes in
YYCHECK. */
int yyxbegin = yyn < 0 ? -yyn : 0;
/* Stay within bounds of both yycheck and yytname. */
int yychecklim = YYLAST - yyn + 1;
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yycount = 1;
yyarg[0] = yytname[yytype];
yyfmt = yystpcpy (yyformat, yyunexpected);
for (yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
{
if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
{
yycount = 1;
yysize = yysize0;
yyformat[sizeof yyunexpected - 1] = '\0';
break;
}
yyarg[yycount++] = yytname[yyx];
yysize1 = yysize + yytnamerr (0, yytname[yyx]);
yysize_overflow |= (yysize1 < yysize);
yysize = yysize1;
yyfmt = yystpcpy (yyfmt, yyprefix);
yyprefix = yyor;
}
int yyn = yypact[*yyssp];
yyarg[yycount++] = yytname[yytoken];
if (!yypact_value_is_default (yyn))
{
/* Start YYX at -YYN if negative to avoid negative indexes in
YYCHECK. In other words, skip the first -YYN actions for
this state because they are default actions. */
int yyxbegin = yyn < 0 ? -yyn : 0;
/* Stay within bounds of both yycheck and yytname. */
int yychecklim = YYLAST - yyn + 1;
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yyx;
for (yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
&& !yytable_value_is_error (yytable[yyx + yyn]))
{
if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
{
yycount = 1;
yysize = yysize0;
break;
}
yyarg[yycount++] = yytname[yyx];
yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
if (! (yysize <= yysize1
&& yysize1 <= YYSTACK_ALLOC_MAXIMUM))
return 2;
yysize = yysize1;
}
}
}
yyf = YY_(yyformat);
yysize1 = yysize + yystrlen (yyf);
yysize_overflow |= (yysize1 < yysize);
yysize = yysize1;
switch (yycount)
{
# define YYCASE_(N, S) \
case N: \
yyformat = S; \
break
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
# undef YYCASE_
}
if (yysize_overflow)
return YYSIZE_MAXIMUM;
yysize1 = yysize + yystrlen (yyformat);
if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
return 2;
yysize = yysize1;
if (yyresult)
{
/* Avoid sprintf, as that infringes on the user's name space.
Don't have undefined behavior even if the translation
produced a string with the wrong number of "%s"s. */
char *yyp = yyresult;
int yyi = 0;
while ((*yyp = *yyf) != '\0')
{
if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
{
yyp += yytnamerr (yyp, yyarg[yyi++]);
yyf += 2;
}
else
{
yyp++;
yyf++;
}
}
}
return yysize;
if (*yymsg_alloc < yysize)
{
*yymsg_alloc = 2 * yysize;
if (! (yysize <= *yymsg_alloc
&& *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
*yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
return 1;
}
/* Avoid sprintf, as that infringes on the user's name space.
Don't have undefined behavior even if the translation
produced a string with the wrong number of "%s"s. */
{
char *yyp = *yymsg;
int yyi = 0;
while ((*yyp = *yyformat) != '\0')
if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
{
yyp += yytnamerr (yyp, yyarg[yyi++]);
yyformat += 2;
}
else
{
yyp++;
yyformat++;
}
}
return 0;
}
#endif /* YYERROR_VERBOSE */
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
......@@ -1284,7 +1351,7 @@ yydestruct (yymsg, yytype, yyvaluep)
switch (yytype)
{
case 51: /* "choice_entry" */
case 57: /* "choice_entry" */
{
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
......@@ -1294,7 +1361,7 @@ yydestruct (yymsg, yytype, yyvaluep)
};
break;
case 57: /* "if_entry" */
case 63: /* "if_entry" */
{
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
......@@ -1304,7 +1371,7 @@ yydestruct (yymsg, yytype, yyvaluep)
};
break;
case 62: /* "menu_entry" */
case 69: /* "menu_entry" */
{
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
......@@ -1320,6 +1387,7 @@ yydestruct (yymsg, yytype, yyvaluep)
}
}
/* Prevent warnings from -Wmissing-prototypes. */
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
......@@ -1346,10 +1414,9 @@ YYSTYPE yylval;
int yynerrs;
/*-------------------------.
| yyparse or yypush_parse. |
`-------------------------*/
/*----------.
| yyparse. |
`----------*/
#ifdef YYPARSE_PARAM
#if (defined __STDC__ || defined __C99__FUNC__ \
......@@ -1373,8 +1440,6 @@ yyparse ()
#endif
#endif
{
int yystate;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
......@@ -1383,7 +1448,7 @@ yyparse ()
`yyss': related to states.
`yyvs': related to semantic values.
Refer to the stacks thru separate pointers, to allow yyoverflow
Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
/* The state stack. */
......@@ -1529,7 +1594,7 @@ yybackup:
/* First try to decide what to do without reference to lookahead token. */
yyn = yypact[yystate];
if (yyn == YYPACT_NINF)
if (yypact_value_is_default (yyn))
goto yydefault;
/* Not known => get a lookahead token if don't already have one. */
......@@ -1560,8 +1625,8 @@ yybackup:
yyn = yytable[yyn];
if (yyn <= 0)
{
if (yyn == 0 || yyn == YYTABLE_NINF)
goto yyerrlab;
if (yytable_value_is_error (yyn))
goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
......@@ -1614,67 +1679,67 @@ yyreduce:
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
case 8:
case 10:
{ zconf_error("unexpected end statement"); ;}
{ zconf_error("unexpected end statement"); }
break;
case 9:
case 11:
{ zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;}
{ zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); }
break;
case 10:
case 12:
{
zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
;}
}
break;
case 11:
case 13:
{ zconf_error("invalid statement"); ;}
{ zconf_error("invalid statement"); }
break;
case 25:
case 28:
{ zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;}
{ zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); }
break;
case 26:
case 29:
{ zconf_error("invalid option"); ;}
{ zconf_error("invalid option"); }
break;
case 27:
case 30:
{
struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
;}
}
break;
case 28:
case 31:
{
menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 29:
case 32:
{
struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
;}
}
break;
case 30:
case 33:
{
if (current_entry->prompt)
......@@ -1683,28 +1748,28 @@ yyreduce:
zconfprint("warning: menuconfig statement without prompt");
menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 38:
case 41:
{
menu_set_type((yyvsp[(1) - (3)].id)->stype);
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
zconf_curname(), zconf_lineno(),
(yyvsp[(1) - (3)].id)->stype);
;}
}
break;
case 39:
case 42:
{
menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 40:
case 43:
{
menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
......@@ -1713,48 +1778,48 @@ yyreduce:
printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
zconf_curname(), zconf_lineno(),
(yyvsp[(1) - (4)].id)->stype);
;}
}
break;
case 41:
case 44:
{
menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 42:
case 45:
{
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 45:
case 48:
{
struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
if (id && id->flags & TF_OPTION)
menu_add_option(id->token, (yyvsp[(3) - (3)].string));
else
zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string));
free((yyvsp[(2) - (3)].string));
;}
}
break;
case 46:
case 49:
{ (yyval.string) = NULL; ;}
{ (yyval.string) = NULL; }
break;
case 47:
case 50:
{ (yyval.string) = (yyvsp[(2) - (2)].string); ;}
{ (yyval.string) = (yyvsp[(2) - (2)].string); }
break;
case 48:
case 51:
{
struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
......@@ -1762,35 +1827,35 @@ yyreduce:
menu_add_entry(sym);
menu_add_expr(P_CHOICE, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 49:
case 52:
{
(yyval.menu) = menu_add_menu();
;}
}
break;
case 50:
case 53:
{
if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
}
;}
}
break;
case 58:
case 61:
{
menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 59:
case 62:
{
if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
......@@ -1800,18 +1865,18 @@ yyreduce:
(yyvsp[(1) - (3)].id)->stype);
} else
YYERROR;
;}
}
break;
case 60:
case 63:
{
current_entry->sym->flags |= SYMBOL_OPTIONAL;
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 61:
case 64:
{
if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
......@@ -1820,188 +1885,233 @@ yyreduce:
zconf_curname(), zconf_lineno());
} else
YYERROR;
;}
}
break;
case 64:
case 67:
{
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
menu_add_entry(NULL);
menu_add_dep((yyvsp[(2) - (3)].expr));
(yyval.menu) = menu_add_menu();
;}
}
break;
case 65:
case 68:
{
if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
}
;}
}
break;
case 71:
case 74:
{
menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
}
break;
case 75:
{
menu_add_entry(NULL);
menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 72:
case 76:
{
(yyval.menu) = menu_add_menu();
;}
}
break;
case 73:
case 77:
{
if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
}
;}
}
break;
case 79:
case 83:
{
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
zconf_nextfile((yyvsp[(2) - (3)].string));
;}
}
break;
case 80:
case 84:
{
menu_add_entry(NULL);
menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 81:
case 85:
{
menu_end_entry();
;}
}
break;
case 82:
case 86:
{
printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
zconf_starthelp();
;}
}
break;
case 83:
case 87:
{
current_entry->help = (yyvsp[(2) - (2)].string);
;}
}
break;
case 88:
case 92:
{
menu_add_dep((yyvsp[(3) - (4)].expr));
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
;}
}
break;
case 90:
case 96:
{
menu_add_visibility((yyvsp[(2) - (2)].expr));
}
break;
case 98:
{
menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
;}
}
break;
case 93:
case 101:
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
{ (yyval.id) = (yyvsp[(1) - (2)].id); }
break;
case 94:
case 102:
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
{ (yyval.id) = (yyvsp[(1) - (2)].id); }
break;
case 95:
case 103:
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
{ (yyval.id) = (yyvsp[(1) - (2)].id); }
break;
case 98:
case 106:
{ (yyval.expr) = NULL; ;}
{ (yyval.expr) = NULL; }
break;
case 99:
case 107:
{ (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
{ (yyval.expr) = (yyvsp[(2) - (2)].expr); }
break;
case 100:
case 108:
{ (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;}
{ (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); }
break;
case 101:
case 109:
{ (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
{ (yyval.expr) = expr_alloc_comp(E_LTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
break;
case 102:
case 110:
{ (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
{ (yyval.expr) = expr_alloc_comp(E_LEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
break;
case 103:
case 111:
{ (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
{ (yyval.expr) = expr_alloc_comp(E_GTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
break;
case 104:
case 112:
{ (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;}
{ (yyval.expr) = expr_alloc_comp(E_GEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
break;
case 105:
case 113:
{ (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
{ (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
break;
case 106:
case 114:
{ (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
{ (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
break;
case 107:
case 115:
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;}
{ (yyval.expr) = (yyvsp[(2) - (3)].expr); }
break;
case 108:
case 116:
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;}
{ (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); }
break;
case 109:
case 117:
{ (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
break;
{ (yyval.string) = NULL; ;}
case 118:
{ (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
break;
case 119:
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); }
break;
case 120:
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); }
break;
case 121:
{ (yyval.string) = NULL; }
break;
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
that yytoken be updated with the new translation. We take the
approach of translating immediately before every use of yytoken.
One alternative is translating here after every semantic action,
but that translation would be missed if the semantic action invokes
YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
incorrect destructor might then be invoked immediately. In the
case of YYERROR or YYBACKUP, subsequent parser actions might lead
to an incorrect destructor call or verbose syntax error message
before the lookahead is translated. */
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
YYPOPSTACK (yylen);
......@@ -2029,6 +2139,10 @@ yyreduce:
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
......@@ -2036,37 +2150,36 @@ yyerrlab:
#if ! YYERROR_VERBOSE
yyerror (YY_("syntax error"));
#else
# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
yyssp, yytoken)
{
YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
{
YYSIZE_T yyalloc = 2 * yysize;
if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
yyalloc = YYSTACK_ALLOC_MAXIMUM;
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
yymsg = (char *) YYSTACK_ALLOC (yyalloc);
if (yymsg)
yymsg_alloc = yyalloc;
else
{
yymsg = yymsgbuf;
yymsg_alloc = sizeof yymsgbuf;
}
}
if (0 < yysize && yysize <= yymsg_alloc)
{
(void) yysyntax_error (yymsg, yystate, yychar);
yyerror (yymsg);
}
else
{
yyerror (YY_("syntax error"));
if (yysize != 0)
goto yyexhaustedlab;
}
char const *yymsgp = YY_("syntax error");
int yysyntax_error_status;
yysyntax_error_status = YYSYNTAX_ERROR;
if (yysyntax_error_status == 0)
yymsgp = yymsg;
else if (yysyntax_error_status == 1)
{
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
if (!yymsg)
{
yymsg = yymsgbuf;
yymsg_alloc = sizeof yymsgbuf;
yysyntax_error_status = 2;
}
else
{
yysyntax_error_status = YYSYNTAX_ERROR;
yymsgp = yymsg;
}
}
yyerror (yymsgp);
if (yysyntax_error_status == 2)
goto yyexhaustedlab;
}
# undef YYSYNTAX_ERROR
#endif
}
......@@ -2125,7 +2238,7 @@ yyerrlab1:
for (;;)
{
yyn = yypact[yystate];
if (yyn != YYPACT_NINF)
if (!yypact_value_is_default (yyn))
{
yyn += YYTERROR;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
......@@ -2172,7 +2285,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
#if !defined(yyoverflow) || YYERROR_VERBOSE
#if !defined yyoverflow || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
......@@ -2184,8 +2297,13 @@ yyexhaustedlab:
yyreturn:
if (yychar != YYEMPTY)
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval);
{
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
yytoken = YYTRANSLATE (yychar);
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval);
}
/* Do not reclaim the symbols of the rule which action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
......@@ -2220,30 +2338,25 @@ void conf_parse(const char *name)
zconf_initscan(name);
sym_init();
menu_init();
modules_sym = sym_lookup(NULL, 0);
modules_sym->type = S_BOOLEAN;
modules_sym->flags |= SYMBOL_AUTO;
rootmenu.prompt = menu_add_prompt(P_MENU, "WRS-sw Configuration", NULL);
_menu_init();
rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
#if YYDEBUG
if (getenv("ZCONF_DEBUG"))
zconfdebug = 1;
#endif
zconfparse();
if (zconfnerrs)
exit(1);
if (!modules_sym->prop) {
struct property *prop;
if (!modules_sym)
modules_sym = sym_find( "n" );
rootmenu.prompt->text = _(rootmenu.prompt->text);
rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
prop = prop_alloc(P_DEFAULT, modules_sym);
prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
}
menu_finalize(&rootmenu);
for_all_symbols(i, sym) {
if (sym_check_deps(sym))
zconfnerrs++;
}
}
if (zconfnerrs)
exit(1);
sym_set_change_count(1);
......@@ -2259,11 +2372,12 @@ static const char *zconf_tokenname(int token)
case T_IF: return "if";
case T_ENDIF: return "endif";
case T_DEPENDS: return "depends";
case T_VISIBLE: return "visible";
}
return "<token>";
}
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
{
if (id->token != endtoken) {
zconf_error("unexpected '%s' within %s block",
......@@ -2308,9 +2422,7 @@ static void zconf_error(const char *err, ...)
static void zconferror(const char *err)
{
#if YYDEBUG
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
#endif
}
static void print_quoted_string(FILE *out, const char *str)
......@@ -2336,9 +2448,9 @@ static void print_symbol(FILE *out, struct menu *menu)
struct property *prop;
if (sym_is_choice(sym))
fprintf(out, "choice\n");
fprintf(out, "\nchoice\n");
else
fprintf(out, "config %s\n", sym->name);
fprintf(out, "\nconfig %s\n", sym->name);
switch (sym->type) {
case S_BOOLEAN:
fputs(" boolean\n", out);
......@@ -2384,6 +2496,21 @@ static void print_symbol(FILE *out, struct menu *menu)
case P_CHOICE:
fputs(" #choice value\n", out);
break;
case P_SELECT:
fputs( " select ", out);
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
case P_RANGE:
fputs( " range ", out);
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
case P_MENU:
fputs( " menu ", out);
print_quoted_string(out, prop->text);
fputc('\n', out);
break;
default:
fprintf(out, " unknown prop %d!\n", prop->type);
break;
......@@ -2395,7 +2522,6 @@ static void print_symbol(FILE *out, struct menu *menu)
menu->help[len] = 0;
fprintf(out, " help\n%s\n", menu->help);
}
fputc('\n', out);
}
void zconfdump(FILE *out)
......@@ -2428,7 +2554,6 @@ void zconfdump(FILE *out)
expr_fprint(prop->visible.expr, out);
fputc('\n', out);
}
fputs("\n", out);
}
if (menu->list)
......@@ -2446,7 +2571,7 @@ void zconfdump(FILE *out)
}
}
#include "lex.zconf.c"
#include "zconf.lex.c"
#include "util.c"
#include "confdata.c"
#include "expr.c"
......
......@@ -11,7 +11,6 @@
#include <string.h>
#include <stdbool.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
......@@ -25,18 +24,14 @@ extern int zconflex(void);
static void zconfprint(const char *err, ...);
static void zconf_error(const char *err, ...);
static void zconferror(const char *err);
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
struct symbol *symbol_hash[257];
struct symbol *symbol_hash[SYMBOL_HASHSIZE];
static struct menu *current_menu, *current_entry;
#define YYDEBUG 0
#if YYDEBUG
#define YYERROR_VERBOSE
#endif
%}
%expect 26
%expect 30
%union
{
......@@ -45,7 +40,7 @@ static struct menu *current_menu, *current_entry;
struct symbol *symbol;
struct expr *expr;
struct menu *menu;
struct kconf_id *id;
const struct kconf_id *id;
}
%token <id>T_MAINMENU
......@@ -68,11 +63,16 @@ static struct menu *current_menu, *current_entry;
%token <id>T_DEFAULT
%token <id>T_SELECT
%token <id>T_RANGE
%token <id>T_VISIBLE
%token <id>T_OPTION
%token <id>T_ON
%token <string> T_WORD
%token <string> T_WORD_QUOTE
%token T_UNEQUAL
%token T_LESS
%token T_LESS_EQUAL
%token T_GREATER
%token T_GREATER_EQUAL
%token T_CLOSE_PAREN
%token T_OPEN_PAREN
%token T_EOL
......@@ -80,6 +80,7 @@ static struct menu *current_menu, *current_entry;
%left T_OR
%left T_AND
%left T_EQUAL T_UNEQUAL
%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
%nonassoc T_NOT
%type <string> prompt
......@@ -104,14 +105,15 @@ static struct menu *current_menu, *current_entry;
%}
%%
input: stmt_list;
input: nl start | start;
start: mainmenu_stmt stmt_list | stmt_list;
stmt_list:
/* empty */
| stmt_list common_stmt
| stmt_list choice_stmt
| stmt_list menu_stmt
| stmt_list T_MAINMENU prompt nl
| stmt_list end { zconf_error("unexpected end statement"); }
| stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
| stmt_list option_name error T_EOL
......@@ -122,7 +124,7 @@ stmt_list:
;
option_name:
T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
;
common_stmt:
......@@ -227,7 +229,7 @@ symbol_option_list:
/* empty */
| symbol_option_list T_WORD symbol_option_arg
{
struct kconf_id *id = kconf_id_lookup($2, strlen($2));
const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
if (id && id->flags & TF_OPTION)
menu_add_option(id->token, $3);
else
......@@ -342,6 +344,13 @@ if_block:
| if_block choice_stmt
;
/* mainmenu entry */
mainmenu_stmt: T_MAINMENU prompt nl
{
menu_add_prompt(P_MENU, $2, NULL);
};
/* menu entry */
menu: T_MENU prompt T_EOL
......@@ -351,7 +360,7 @@ menu: T_MENU prompt T_EOL
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
};
menu_entry: menu depends_list
menu_entry: menu visibility_list depends_list
{
$$ = menu_add_menu();
};
......@@ -422,6 +431,19 @@ depends: T_DEPENDS T_ON expr T_EOL
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
};
/* visibility option */
visibility_list:
/* empty */
| visibility_list visible
| visibility_list T_EOL
;
visible: T_VISIBLE if_expr
{
menu_add_visibility($2);
};
/* prompt statement */
prompt_stmt_opt:
......@@ -450,6 +472,10 @@ if_expr: /* empty */ { $$ = NULL; }
;
expr: symbol { $$ = expr_alloc_symbol($1); }
| symbol T_LESS symbol { $$ = expr_alloc_comp(E_LTH, $1, $3); }
| symbol T_LESS_EQUAL symbol { $$ = expr_alloc_comp(E_LEQ, $1, $3); }
| symbol T_GREATER symbol { $$ = expr_alloc_comp(E_GTH, $1, $3); }
| symbol T_GREATER_EQUAL symbol { $$ = expr_alloc_comp(E_GEQ, $1, $3); }
| symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
| symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
| T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
......@@ -475,30 +501,25 @@ void conf_parse(const char *name)
zconf_initscan(name);
sym_init();
menu_init();
modules_sym = sym_lookup(NULL, 0);
modules_sym->type = S_BOOLEAN;
modules_sym->flags |= SYMBOL_AUTO;
rootmenu.prompt = menu_add_prompt(P_MENU, "WRS-sw Configuration", NULL);
_menu_init();
rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
#if YYDEBUG
if (getenv("ZCONF_DEBUG"))
zconfdebug = 1;
#endif
zconfparse();
if (zconfnerrs)
exit(1);
if (!modules_sym->prop) {
struct property *prop;
if (!modules_sym)
modules_sym = sym_find( "n" );
rootmenu.prompt->text = _(rootmenu.prompt->text);
rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
prop = prop_alloc(P_DEFAULT, modules_sym);
prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
}
menu_finalize(&rootmenu);
for_all_symbols(i, sym) {
if (sym_check_deps(sym))
zconfnerrs++;
}
}
if (zconfnerrs)
exit(1);
sym_set_change_count(1);
......@@ -514,11 +535,12 @@ static const char *zconf_tokenname(int token)
case T_IF: return "if";
case T_ENDIF: return "endif";
case T_DEPENDS: return "depends";
case T_VISIBLE: return "visible";
}
return "<token>";
}
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
{
if (id->token != endtoken) {
zconf_error("unexpected '%s' within %s block",
......@@ -563,9 +585,7 @@ static void zconf_error(const char *err, ...)
static void zconferror(const char *err)
{
#if YYDEBUG
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
#endif
}
static void print_quoted_string(FILE *out, const char *str)
......@@ -591,9 +611,9 @@ static void print_symbol(FILE *out, struct menu *menu)
struct property *prop;
if (sym_is_choice(sym))
fprintf(out, "choice\n");
fprintf(out, "\nchoice\n");
else
fprintf(out, "config %s\n", sym->name);
fprintf(out, "\nconfig %s\n", sym->name);
switch (sym->type) {
case S_BOOLEAN:
fputs(" boolean\n", out);
......@@ -639,6 +659,21 @@ static void print_symbol(FILE *out, struct menu *menu)
case P_CHOICE:
fputs(" #choice value\n", out);
break;
case P_SELECT:
fputs( " select ", out);
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
case P_RANGE:
fputs( " range ", out);
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
case P_MENU:
fputs( " menu ", out);
print_quoted_string(out, prop->text);
fputc('\n', out);
break;
default:
fprintf(out, " unknown prop %d!\n", prop->type);
break;
......@@ -650,7 +685,6 @@ static void print_symbol(FILE *out, struct menu *menu)
menu->help[len] = 0;
fprintf(out, " help\n%s\n", menu->help);
}
fputc('\n', out);
}
void zconfdump(FILE *out)
......@@ -683,7 +717,6 @@ void zconfdump(FILE *out)
expr_fprint(prop->visible.expr, out);
fputc('\n', out);
}
fputs("\n", out);
}
if (menu->list)
......@@ -701,7 +734,7 @@ void zconfdump(FILE *out)
}
}
#include "lex.zconf.c"
#include "zconf.lex.c"
#include "util.c"
#include "confdata.c"
#include "expr.c"
......
......@@ -16,7 +16,7 @@ CFLAGS = -D KBUILD_NO_NLS
# most of this is just copying stuff in
RFILES = Kconfig dot-config wrs_release_defconfig
XFILES = conf mconf
XFILES = conf mconf nconf
FILES = $(RFILES) $(XFILES)
all: $(FILES)
......@@ -58,6 +58,13 @@ mconf:
-DCURSES_LOC="<curses.h>" -I$(CURSES_BUILD)/include \
-L$(CURSES_BUILD)/lib -lncurses
nconf:
$(CC) $(CFLAGS) -o $@ $(CONF_LOC)/nconf.c $(CONF_LOC)/zconf.tab.c \
$(CONF_LOC)/nconf.gui.c \
-DCURSES_LOC="<curses.h>" -I$(CURSES_BUILD)/include \
-L$(CURSES_BUILD)/lib -lncurses -lmenu -lpanel
# nconf.o zconf.tab.o nconf.gui.o
wrs_release_defconfig: $(WRS_BASE_DIR)/../configs/wrs_release_defconfig
cp $^ $@
......@@ -22,3 +22,10 @@ menuconfig:
./mconf Kconfig
mv .config.old dot-config.old
mv .config dot-config
nconfig:
cp dot-config .config
./nconf Kconfig
mv .config.old dot-config.old
mv .config dot-config
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment