Add a recent kconfig version to coreinfo, in order to make the
supported features configurable later (currently unused). Store all build files and results (coreinfo.elf) in build/ now. I'm self-acking this as (though non-"trivial") it doesn't affect coreinfo in its functionality, this is more or less a "cosmetic" change to the build interface ("make" -> "make menuconfig && make"). This is a kconfig checkout from the Linux kernel (where kconfig is being actively maintained) from 03/2008. The hash identifying the last commit to kconfig is 587c90616a5b44e6ccfac38e64d4fecee51d588c. The amount of changes to kconfig itself has been kept as small as possible to keep the diff small and to ease updating/porting to newer kconfig versions. The following changes were performed on the upstream Linux kconfig: - s/kernel/coreinfo/, and s/Linux/coreinfo/ in various strings. - Consistently use the env. variable KERNELVERSION in all kconfig interfaces -- e.g. config/menuconfig/gconfig/xconfig -- as version number. - Hardcode our paths/filenames in some places (could be improved upstream). - Always write .config and build/config.h, no matter which kconfig interface is used (config/menuconfig/gconfig/xconfig). We want to include build/config.h in our code. - Adapt the kconfig Makefile for our purposes (build/ directory, rules, etc). In addition, a few items in the coreinfo Makefile are needed for this to work. This kconfig setup is successfully tested with all targets from 'make help': config - Update current config utilising a line-oriented program menuconfig - Update current config utilising a menu based program xconfig - Update current config utilising a QT based front-end gconfig - Update current config utilising a GTK based front-end oldconfig - Update current config utilising a provided .config as base silentoldconfig - Same as oldconfig, but quietly randconfig - New config with random answer to all options defconfig - New config with default answer to all options allmodconfig - New config selecting modules when possible allyesconfig - New config where all options are accepted with yes allnoconfig - New config where all options are answered with no For 'make defconfig' to work you have to do (which we don't need in coreinfo): $ mkdir configs; touch configs/defconfig You can also use 'make foo_defconfig' in which case kconfig will use a file called 'configs/foo_defconfig' as basis. Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de> Acked-by: Uwe Hermann <uwe@hermann-uwe.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3188 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
0bfb5c4fb2
commit
2216d1b46a
|
@ -0,0 +1,44 @@
|
|||
##
|
||||
## This file is part of the coreinfo project.
|
||||
##
|
||||
## Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see http://lxr.linux.no/source/Documentation/kbuild/kconfig-language.txt.
|
||||
#
|
||||
|
||||
mainmenu "coreinfo Configuration"
|
||||
|
||||
menu "Modules"
|
||||
|
||||
# TODO: Currently none of these options has any effect.
|
||||
|
||||
config MODULE_COREBOOT
|
||||
bool "Enable the coreboot module"
|
||||
default y
|
||||
|
||||
config MODULE_CPUINFO
|
||||
bool "Enable the cpuinfo module"
|
||||
default y
|
||||
|
||||
config MODULE_PCI
|
||||
bool "Enable the PCI info module"
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
## This file is part of the coreinfo project.
|
||||
##
|
||||
## Copyright (C) 2008 Advanced Micro Devices, Inc.
|
||||
## Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## 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
|
||||
|
@ -17,32 +18,85 @@
|
|||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
export src := $(shell pwd)
|
||||
export srctree := $(src)
|
||||
export srck := $(src)/util/kconfig
|
||||
export obj := $(src)/build
|
||||
export objk := $(src)/build/util/kconfig
|
||||
|
||||
export KERNELVERSION := 0.1.0
|
||||
export KCONFIG_AUTOHEADER := $(obj)/config.h
|
||||
export KCONFIG_AUTOCONFIG := $(obj)/auto.conf
|
||||
|
||||
CONFIG_SHELL := sh
|
||||
KBUILD_DEFCONFIG := configs/defconfig
|
||||
UNAME_RELEASE := $(shell uname -r)
|
||||
HAVE_DOTCONFIG := $(wildcard .config)
|
||||
MAKEFLAGS += -rR --no-print-directory
|
||||
|
||||
# Make is silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
HOSTCC = gcc
|
||||
HOSTCXX = g++
|
||||
HOSTCFLAGS := -I$(srck) -I$(objk)
|
||||
HOSTCXXFLAGS := -I$(srck) -I$(objk)
|
||||
|
||||
CC = gcc
|
||||
CROSS_CFLAGS = -m32
|
||||
|
||||
INCLUDES = -I../libpayload/include
|
||||
INCLUDES += -I$(shell $(CC) $(CROSS_CFLAGS) -print-search-dirs | head -n 1 | cut -d' ' -f2)include
|
||||
|
||||
INCLUDES = -I../libpayload/include \
|
||||
-I$(shell $(CC) $(CROSS_CFLAGS) -print-search-dirs | \
|
||||
head -n 1 | cut -d' ' -f2)include
|
||||
LIBPAYLOAD = ../libpayload/libpayload.a
|
||||
LIBGCC := $(shell $(CC) $(CROSS_CFLAGS) -print-libgcc-file-name)
|
||||
CFLAGS := -Wall -Werror -Os -fno-stack-protector -nostdinc $(INCLUDES)
|
||||
|
||||
MODULES = cpuinfo_module.o cpuid.o pci_module.o coreboot_module.o
|
||||
MODULES = cpuinfo_module.o cpuid.S.o pci_module.o coreboot_module.o
|
||||
OBJECTS = coreinfo.o
|
||||
TARGET = coreinfo.elf
|
||||
OBJS = $(patsubst %,$(obj)/%,$(OBJECTS)) $(patsubst %,$(obj)/%,$(MODULES))
|
||||
TARGET = $(obj)/coreinfo.elf
|
||||
|
||||
ifeq ($(strip $(HAVE_DOTCONFIG)),)
|
||||
|
||||
all:
|
||||
$(Q)printf "Please run make config/menuconfig/xconfig/gconfig first.\n"
|
||||
|
||||
else
|
||||
|
||||
include $(src)/.config
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(Q)printf " LD $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)#ld --verbose -T ../libpayload/libpayload.ldscript -o $@ $(OBJS) \
|
||||
#--whole-archive $(LIBPAYLOAD) --no-whole-archive $(LIBGCC)
|
||||
$(Q)ld -T ../libpayload/libpayload.ldscript -o $@ $(OBJS) \
|
||||
../libpayload/i386/head.o $(LIBPAYLOAD) $(LIBGCC)
|
||||
$(Q)printf " STRIP $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)strip -s $@
|
||||
|
||||
$(obj)/%.S.o: $(src)/%.S
|
||||
$(Q)printf " AS $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(AS) --32 -o $@ $<
|
||||
|
||||
$(obj)/%.o: $(src)/%.c
|
||||
$(Q)printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CROSS_CFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
endif
|
||||
|
||||
prepare:
|
||||
$(Q)mkdir -p $(obj)/util/kconfig/lxdialog
|
||||
|
||||
clean:
|
||||
@rm -f $(TARGET) $(MODULES) $(OBJECTS)
|
||||
$(Q)rm -rf build
|
||||
|
||||
$(TARGET): $(OBJECTS) $(MODULES)
|
||||
@#ld --verbose -T ../libpayload/libpayload.ldscript -o $@ $(OBJECTS) --whole-archive $(LIBPAYLOAD) --no-whole-archive $(LIBGCC)
|
||||
ld -T ../libpayload/libpayload.ldscript -o $@ $(OBJECTS) $(MODULES) ../libpayload/i386/head.o $(LIBPAYLOAD) $(LIBGCC)
|
||||
@strip $@
|
||||
distclean: clean
|
||||
$(Q)rm -f .config .config.old ..config.tmp .kconfig.d .tmpconfig*
|
||||
|
||||
.S.o:
|
||||
$(AS) --32 -o $@ $<
|
||||
include util/kconfig/Makefile
|
||||
|
||||
.PHONY: $(PHONY) prepare clean distclean
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CROSS_CFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Generated files
|
||||
#
|
||||
config*
|
||||
lex.*.c
|
||||
*.tab.c
|
||||
*.tab.h
|
||||
zconf.hash.c
|
||||
*.moc
|
||||
lkc_defs.h
|
||||
|
||||
#
|
||||
# configuration programs
|
||||
#
|
||||
conf
|
||||
mconf
|
||||
qconf
|
||||
gconf
|
||||
kxgettext
|
|
@ -0,0 +1,337 @@
|
|||
# ===========================================================================
|
||||
# Kernel configuration targets
|
||||
# These targets are used from top-level makefile
|
||||
|
||||
PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config
|
||||
|
||||
Kconfig := Kconfig
|
||||
|
||||
xconfig: prepare $(objk)/qconf
|
||||
$(Q)$(objk)/qconf $(Kconfig)
|
||||
|
||||
gconfig: prepare $(objk)/gconf
|
||||
$(Q)$(objk)/gconf $(Kconfig)
|
||||
|
||||
menuconfig: prepare $(objk)/mconf
|
||||
$(Q)$(objk)/mconf $(Kconfig)
|
||||
|
||||
config: prepare $(objk)/conf
|
||||
$(Q)$(objk)/conf $(Kconfig)
|
||||
|
||||
oldconfig: prepare $(objk)/conf
|
||||
$(Q)$(objk)/conf -o $(Kconfig)
|
||||
|
||||
silentoldconfig: prepare $(objk)/conf
|
||||
$(Q)$(objk)/conf -s $(Kconfig)
|
||||
|
||||
# --- UNUSED, ignore ----------------------------------------------------------
|
||||
# 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 \
|
||||
--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/`; \
|
||||
do \
|
||||
echo " GEN $$i"; \
|
||||
$(obj)/kxgettext arch/$$i/Kconfig \
|
||||
>> $(obj)/config.pot; \
|
||||
done )
|
||||
$(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
|
||||
# --- UNUSED, ignore ----------------------------------------------------------
|
||||
|
||||
PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig
|
||||
|
||||
randconfig: prepare $(objk)/conf
|
||||
$(Q)$(objk)/conf -r $(Kconfig)
|
||||
|
||||
allyesconfig: prepare $(objk)/conf
|
||||
$(Q)$(objk)/conf -y $(Kconfig)
|
||||
|
||||
allnoconfig: prepare $(objk)/conf
|
||||
$(Q)$(objk)/conf -n $(Kconfig)
|
||||
|
||||
allmodconfig: prepare $(objk)/conf
|
||||
$(Q)$(objk)/conf -m $(Kconfig)
|
||||
|
||||
defconfig: prepare $(objk)/conf
|
||||
ifeq ($(KBUILD_DEFCONFIG),)
|
||||
$(Q)$(objk)/conf -d $(Kconfig)
|
||||
else
|
||||
@echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
|
||||
$(Q)$(objk)/conf -D $(KBUILD_DEFCONFIG) $(Kconfig)
|
||||
endif
|
||||
|
||||
%_defconfig: prepare $(objk)/conf
|
||||
$(Q)$(objk)/conf -D configs/$@ $(Kconfig)
|
||||
|
||||
# Help text used by make help
|
||||
help:
|
||||
@echo ' config - Update current config utilising a line-oriented program'
|
||||
@echo ' menuconfig - Update current config utilising a menu based program'
|
||||
@echo ' xconfig - Update current config utilising a QT based front-end'
|
||||
@echo ' gconfig - Update current config utilising a GTK based front-end'
|
||||
@echo ' oldconfig - Update current config utilising a provided .config as base'
|
||||
@echo ' silentoldconfig - Same as oldconfig, but quietly'
|
||||
@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 ' allnoconfig - New config where all options are answered with no'
|
||||
|
||||
# lxdialog stuff
|
||||
check-lxdialog := $(srck)/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
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# Shared Makefile for the various kconfig executables:
|
||||
# conf: Used for defconfig, oldconfig and related targets
|
||||
# mconf: Used for the mconfig target.
|
||||
# Utilizes the lxdialog package
|
||||
# qconf: Used for the xconfig target
|
||||
# Based on QT which needs to be installed to compile it
|
||||
# gconf: Used for the gconfig target
|
||||
# Based on GTK which needs to be installed to compile it
|
||||
# object files used by all kconfig flavours
|
||||
|
||||
lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
|
||||
lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
|
||||
|
||||
conf-objs := conf.o zconf.tab.o
|
||||
mconf-objs := mconf.o zconf.tab.o $(lxdialog)
|
||||
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
|
||||
|
||||
ifeq ($(gconf-target),1)
|
||||
gconf-objs := gconf.o kconfig_load.o zconf.tab.o
|
||||
endif
|
||||
|
||||
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 += config.pot coreinfo.pot
|
||||
|
||||
# Check that we have the required ncurses stuff installed for lxdialog (menuconfig)
|
||||
PHONY += $(objk)/dochecklxdialog
|
||||
$(addprefix $(obj)/,$(lxdialog)): $(objk)/dochecklxdialog
|
||||
$(objk)/dochecklxdialog:
|
||||
$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES)
|
||||
|
||||
always := dochecklxdialog
|
||||
|
||||
# Add environment specific flags
|
||||
HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srck)/check.sh $(HOSTCC) $(HOSTCFLAGS))
|
||||
|
||||
# generated files seem to need this to find local include files
|
||||
HOSTCFLAGS_lex.zconf.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
|
||||
|
||||
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
|
||||
|
||||
$(objk)/qconf.o: $(objk)/.tmp_qtcheck
|
||||
|
||||
ifeq ($(qconf-target),1)
|
||||
$(objk)/.tmp_qtcheck: $(srck)/Makefile
|
||||
-include $(objk)/.tmp_qtcheck
|
||||
|
||||
# QT needs some extra effort...
|
||||
$(objk)/.tmp_qtcheck: prepare
|
||||
@set -e; 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)"; \
|
||||
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"; \
|
||||
fi; \
|
||||
echo "KC_QT_CFLAGS=$$cflags" > $@; \
|
||||
echo "KC_QT_LIBS=$$libs" >> $@; \
|
||||
echo "KC_QT_MOC=$$moc" >> $@
|
||||
endif
|
||||
|
||||
$(objk)/gconf.o: $(objk)/.tmp_gtkcheck
|
||||
|
||||
ifeq ($(gconf-target),1)
|
||||
-include $(objk)/.tmp_gtkcheck
|
||||
|
||||
# GTK needs some extra effort, too...
|
||||
$(objk)/.tmp_gtkcheck: prepare
|
||||
@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 "*"; \
|
||||
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 "*"; \
|
||||
false; \
|
||||
fi
|
||||
endif
|
||||
|
||||
# --- UNUSED, ignore ----------------------------------------------------------
|
||||
ifdef UNUSED
|
||||
$(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)/gconf.o: $(obj)/lkc_defs.h
|
||||
|
||||
$(obj)/%.moc: $(src)/%.h
|
||||
$(KC_QT_MOC) -i $< -o $@
|
||||
|
||||
$(obj)/lkc_defs.h: $(src)/lkc_proto.h
|
||||
sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
|
||||
|
||||
# Extract gconf menu items for I18N support
|
||||
$(obj)/gconf.glade.h: $(obj)/gconf.glade
|
||||
intltool-extract --type=gettext/glade $(obj)/gconf.glade
|
||||
endif
|
||||
# --- UNUSED, ignore ----------------------------------------------------------
|
||||
|
||||
###
|
||||
# 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
|
||||
|
||||
# --- UNUSED, ignore ----------------------------------------------------------
|
||||
$(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
|
||||
# --- UNUSED, ignore ----------------------------------------------------------
|
||||
|
||||
endif
|
||||
|
||||
$(objk)/qconf: $(patsubst %,$(objk)/%,$(qconf-cxxobjs)) \
|
||||
$(patsubst %,$(objk)/%,$(qconf-objs))
|
||||
$(Q)$(HOSTCXX) $(HOSTCXXFLAGS) $(HOSTLOADLIBES_qconf) -o $@ $^
|
||||
$(objk)/gconf: $(patsubst %,$(objk)/%,$(gconf-objs))
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) $(HOSTLOADLIBES_gconf) -o $@ $^
|
||||
$(objk)/mconf: $(patsubst %,$(objk)/%,$(mconf-objs))
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES) -o $@ $^
|
||||
$(objk)/conf: $(patsubst %,$(objk)/%,$(conf-objs))
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) -o $@ $^
|
||||
|
||||
$(objk)/mconf.o: $(srck)/mconf.c
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -c -o $@ $<
|
||||
$(objk)/conf.o: $(srck)/conf.c
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) -c -o $@ $<
|
||||
|
||||
$(objk)/zconf.tab.o: $(objk)/zconf.tab.c $(objk)/lex.zconf.c \
|
||||
$(objk)/zconf.hash.c
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) -c -o $@ $(objk)/zconf.tab.c
|
||||
$(objk)/kconfig_load.o: $(srck)/kconfig_load.c $(objk)/lkc_defs.h
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) -c -o $@ $<
|
||||
$(objk)/qconf.o: $(srck)/qconf.cc $(objk)/qconf.moc $(objk)/lkc_defs.h
|
||||
$(Q)$(HOSTCXX) $(HOSTCXXFLAGS) $(HOSTCXXFLAGS_qconf.o) -c -o $@ $<
|
||||
$(objk)/gconf.o: $(srck)/gconf.c $(objk)/lkc_defs.h
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) $(HOSTCFLAGS_gconf.o) -c -o $@ $<
|
||||
$(objk)/%.moc: $(srck)/%.h
|
||||
$(Q)$(KC_QT_MOC) -i $< -o $@
|
||||
$(objk)/lkc_defs.h: $(srck)/lkc_proto.h
|
||||
$(Q)sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
|
||||
|
||||
$(objk)/lex.zconf.c: $(srck)/lex.zconf.c_shipped
|
||||
$(Q)cp $< $@
|
||||
$(objk)/zconf.hash.c: $(srck)/zconf.hash.c_shipped
|
||||
$(Q)cp $< $@
|
||||
$(objk)/zconf.tab.c: $(srck)/zconf.tab.c_shipped
|
||||
$(Q)cp $< $@
|
||||
|
||||
$(objk)/lxdialog/lxdialog: $(objk)/dochecklxdialog \
|
||||
$(patsubst %,$(objk)/lxdialog/%,$(lxdialog))
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES) \
|
||||
$(patsubst %,$(objk)/lxdialog/%,$(lxdialog)) -o $@
|
||||
$(objk)/lxdialog/%.o: $(srck)/lxdialog/%.c
|
||||
$(Q)$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $^ -c -o $@
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
util/kconfig/lxdialog/checklist.c
|
||||
util/kconfig/lxdialog/inputbox.c
|
||||
util/kconfig/lxdialog/menubox.c
|
||||
util/kconfig/lxdialog/textbox.c
|
||||
util/kconfig/lxdialog/util.c
|
||||
util/kconfig/lxdialog/yesno.c
|
||||
util/kconfig/mconf.c
|
||||
util/kconfig/conf.c
|
||||
util/kconfig/confdata.c
|
||||
util/kconfig/gconf.c
|
||||
util/kconfig/gconf.glade.h
|
||||
util/kconfig/qconf.cc
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
# Needed for systems without gettext
|
||||
$* -xc -o /dev/null - > /dev/null 2>&1 << EOF
|
||||
#include <libintl.h>
|
||||
int main()
|
||||
{
|
||||
gettext("");
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if [ ! "$?" -eq "0" ]; then
|
||||
echo -DKBUILD_NO_NLS;
|
||||
fi
|
||||
|
|
@ -0,0 +1,634 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <locale.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.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 int indent = 1;
|
||||
static int valid_stdin = 1;
|
||||
static int conf_cnt;
|
||||
static char line[128];
|
||||
static struct menu *rootEntry;
|
||||
|
||||
static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
|
||||
|
||||
static const char *get_help(struct menu *menu)
|
||||
{
|
||||
if (menu_has_help(menu))
|
||||
return _(menu_get_help(menu));
|
||||
else
|
||||
return nohelp_text;
|
||||
}
|
||||
|
||||
static void strip(char *str)
|
||||
{
|
||||
char *p = str;
|
||||
int l;
|
||||
|
||||
while ((isspace(*p)))
|
||||
p++;
|
||||
l = strlen(p);
|
||||
if (p != str)
|
||||
memmove(str, p, l + 1);
|
||||
if (!l)
|
||||
return;
|
||||
p = str + l - 1;
|
||||
while ((isspace(*p)))
|
||||
*p-- = 0;
|
||||
}
|
||||
|
||||
static void check_stdin(void)
|
||||
{
|
||||
if (!valid_stdin && input_mode == ask_silent) {
|
||||
printf(_("aborted!\n\n"));
|
||||
printf(_("Console input/output is redirected. "));
|
||||
printf(_("Run 'make oldconfig' to update configuration.\n\n"));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static int conf_askvalue(struct symbol *sym, const char *def)
|
||||
{
|
||||
enum symbol_type type = sym_get_type(sym);
|
||||
tristate val;
|
||||
|
||||
if (!sym_has_value(sym))
|
||||
printf(_("(NEW) "));
|
||||
|
||||
line[0] = '\n';
|
||||
line[1] = 0;
|
||||
|
||||
if (!sym_is_changable(sym)) {
|
||||
printf("%s\n", def);
|
||||
line[0] = '\n';
|
||||
line[1] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (input_mode) {
|
||||
case set_no:
|
||||
case set_mod:
|
||||
case set_yes:
|
||||
case set_random:
|
||||
if (sym_has_value(sym)) {
|
||||
printf("%s\n", def);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ask_new:
|
||||
case ask_silent:
|
||||
if (sym_has_value(sym)) {
|
||||
printf("%s\n", def);
|
||||
return 0;
|
||||
}
|
||||
check_stdin();
|
||||
case ask_all:
|
||||
fflush(stdout);
|
||||
fgets(line, 128, stdin);
|
||||
return 1;
|
||||
case set_default:
|
||||
printf("%s\n", def);
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
case S_STRING:
|
||||
printf("%s\n", def);
|
||||
return 1;
|
||||
default:
|
||||
;
|
||||
}
|
||||
switch (input_mode) {
|
||||
case set_yes:
|
||||
if (sym_tristate_within_range(sym, yes)) {
|
||||
line[0] = 'y';
|
||||
line[1] = '\n';
|
||||
line[2] = 0;
|
||||
break;
|
||||
}
|
||||
case set_mod:
|
||||
if (type == S_TRISTATE) {
|
||||
if (sym_tristate_within_range(sym, mod)) {
|
||||
line[0] = 'm';
|
||||
line[1] = '\n';
|
||||
line[2] = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (sym_tristate_within_range(sym, yes)) {
|
||||
line[0] = 'y';
|
||||
line[1] = '\n';
|
||||
line[2] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case set_no:
|
||||
if (sym_tristate_within_range(sym, no)) {
|
||||
line[0] = 'n';
|
||||
line[1] = '\n';
|
||||
line[2] = 0;
|
||||
break;
|
||||
}
|
||||
case set_random:
|
||||
do {
|
||||
val = (tristate)(rand() % 3);
|
||||
} while (!sym_tristate_within_range(sym, val));
|
||||
switch (val) {
|
||||
case no: line[0] = 'n'; break;
|
||||
case mod: line[0] = 'm'; break;
|
||||
case yes: line[0] = 'y'; break;
|
||||
}
|
||||
line[1] = '\n';
|
||||
line[2] = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("%s", line);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int conf_string(struct menu *menu)
|
||||
{
|
||||
struct symbol *sym = menu->sym;
|
||||
const char *def;
|
||||
|
||||
while (1) {
|
||||
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
|
||||
printf("(%s) ", sym->name);
|
||||
def = sym_get_string_value(sym);
|
||||
if (sym_get_string_value(sym))
|
||||
printf("[%s] ", def);
|
||||
if (!conf_askvalue(sym, def))
|
||||
return 0;
|
||||
switch (line[0]) {
|
||||
case '\n':
|
||||
break;
|
||||
case '?':
|
||||
/* print help */
|
||||
if (line[1] == '\n') {
|
||||
printf("\n%s\n", get_help(menu));
|
||||
def = NULL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
line[strlen(line)-1] = 0;
|
||||
def = line;
|
||||
}
|
||||
if (def && sym_set_string_value(sym, def))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int conf_sym(struct menu *menu)
|
||||
{
|
||||
struct symbol *sym = menu->sym;
|
||||
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) {
|
||||
case no:
|
||||
putchar('N');
|
||||
break;
|
||||
case mod:
|
||||
putchar('M');
|
||||
break;
|
||||
case yes:
|
||||
putchar('Y');
|
||||
break;
|
||||
}
|
||||
if (oldval != no && sym_tristate_within_range(sym, no))
|
||||
printf("/n");
|
||||
if (oldval != mod && sym_tristate_within_range(sym, mod))
|
||||
printf("/m");
|
||||
if (oldval != yes && sym_tristate_within_range(sym, yes))
|
||||
printf("/y");
|
||||
if (menu_has_help(menu))
|
||||
printf("/?");
|
||||
printf("] ");
|
||||
if (!conf_askvalue(sym, sym_get_string_value(sym)))
|
||||
return 0;
|
||||
strip(line);
|
||||
|
||||
switch (line[0]) {
|
||||
case 'n':
|
||||
case 'N':
|
||||
newval = no;
|
||||
if (!line[1] || !strcmp(&line[1], "o"))
|
||||
break;
|
||||
continue;
|
||||
case 'm':
|
||||
case 'M':
|
||||
newval = mod;
|
||||
if (!line[1])
|
||||
break;
|
||||
continue;
|
||||
case 'y':
|
||||
case 'Y':
|
||||
newval = yes;
|
||||
if (!line[1] || !strcmp(&line[1], "es"))
|
||||
break;
|
||||
continue;
|
||||
case 0:
|
||||
newval = oldval;
|
||||
break;
|
||||
case '?':
|
||||
goto help;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
if (sym_set_tristate_value(sym, newval))
|
||||
return 0;
|
||||
help:
|
||||
printf("\n%s\n", get_help(menu));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
sym_calc_value(sym);
|
||||
switch (sym_get_tristate_value(sym)) {
|
||||
case no:
|
||||
return 1;
|
||||
case mod:
|
||||
return 0;
|
||||
case yes:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (sym_get_tristate_value(sym)) {
|
||||
case no:
|
||||
return 1;
|
||||
case mod:
|
||||
printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
|
||||
return 0;
|
||||
case yes:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int cnt, def;
|
||||
|
||||
printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
|
||||
def_sym = sym_get_choice_value(sym);
|
||||
cnt = def = 0;
|
||||
line[0] = 0;
|
||||
for (child = menu->list; child; child = child->next) {
|
||||
if (!menu_is_visible(child))
|
||||
continue;
|
||||
if (!child->sym) {
|
||||
printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
|
||||
continue;
|
||||
}
|
||||
cnt++;
|
||||
if (child->sym == def_sym) {
|
||||
def = cnt;
|
||||
printf("%*c", indent, '>');
|
||||
} else
|
||||
printf("%*c", indent, ' ');
|
||||
printf(" %d. %s", cnt, _(menu_get_prompt(child)));
|
||||
if (child->sym->name)
|
||||
printf(" (%s)", child->sym->name);
|
||||
if (!sym_has_value(child->sym))
|
||||
printf(_(" (NEW)"));
|
||||
printf("\n");
|
||||
}
|
||||
printf(_("%*schoice"), indent - 1, "");
|
||||
if (cnt == 1) {
|
||||
printf("[1]: 1\n");
|
||||
goto conf_childs;
|
||||
}
|
||||
printf("[1-%d", cnt);
|
||||
if (menu_has_help(menu))
|
||||
printf("?");
|
||||
printf("]: ");
|
||||
switch (input_mode) {
|
||||
case ask_new:
|
||||
case ask_silent:
|
||||
if (!is_new) {
|
||||
cnt = def;
|
||||
printf("%d\n", cnt);
|
||||
break;
|
||||
}
|
||||
check_stdin();
|
||||
case ask_all:
|
||||
fflush(stdout);
|
||||
fgets(line, 128, stdin);
|
||||
strip(line);
|
||||
if (line[0] == '?') {
|
||||
printf("\n%s\n", get_help(menu));
|
||||
continue;
|
||||
}
|
||||
if (!line[0])
|
||||
cnt = def;
|
||||
else if (isdigit(line[0]))
|
||||
cnt = atoi(line);
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
case set_random:
|
||||
if (is_new)
|
||||
def = (rand() % cnt) + 1;
|
||||
case set_default:
|
||||
case set_yes:
|
||||
case set_mod:
|
||||
case set_no:
|
||||
cnt = def;
|
||||
printf("%d\n", cnt);
|
||||
break;
|
||||
}
|
||||
|
||||
conf_childs:
|
||||
for (child = menu->list; child; child = child->next) {
|
||||
if (!child->sym || !menu_is_visible(child))
|
||||
continue;
|
||||
if (!--cnt)
|
||||
break;
|
||||
}
|
||||
if (!child)
|
||||
continue;
|
||||
if (line[strlen(line) - 1] == '?') {
|
||||
printf("\n%s\n", get_help(child));
|
||||
continue;
|
||||
}
|
||||
sym_set_choice_value(sym, child->sym);
|
||||
for (child = child->list; child; child = child->next) {
|
||||
indent += 2;
|
||||
conf(child);
|
||||
indent -= 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void conf(struct menu *menu)
|
||||
{
|
||||
struct symbol *sym;
|
||||
struct property *prop;
|
||||
struct menu *child;
|
||||
|
||||
if (!menu_is_visible(menu))
|
||||
return;
|
||||
|
||||
sym = menu->sym;
|
||||
prop = menu->prompt;
|
||||
if (prop) {
|
||||
const char *prompt;
|
||||
|
||||
switch (prop->type) {
|
||||
case P_MENU:
|
||||
if (input_mode == ask_silent && rootEntry != menu) {
|
||||
check_conf(menu);
|
||||
return;
|
||||
}
|
||||
case P_COMMENT:
|
||||
prompt = menu_get_prompt(menu);
|
||||
if (prompt)
|
||||
printf("%*c\n%*c %s\n%*c\n",
|
||||
indent, '*',
|
||||
indent, '*', _(prompt),
|
||||
indent, '*');
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sym)
|
||||
goto conf_childs;
|
||||
|
||||
if (sym_is_choice(sym)) {
|
||||
conf_choice(menu);
|
||||
if (sym->curr.tri != mod)
|
||||
return;
|
||||
goto conf_childs;
|
||||
}
|
||||
|
||||
switch (sym->type) {
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
case S_STRING:
|
||||
conf_string(menu);
|
||||
break;
|
||||
default:
|
||||
conf_sym(menu);
|
||||
break;
|
||||
}
|
||||
|
||||
conf_childs:
|
||||
if (sym)
|
||||
indent += 2;
|
||||
for (child = menu->list; child; child = child->next)
|
||||
conf(child);
|
||||
if (sym)
|
||||
indent -= 2;
|
||||
}
|
||||
|
||||
static void check_conf(struct menu *menu)
|
||||
{
|
||||
struct symbol *sym;
|
||||
struct menu *child;
|
||||
|
||||
if (!menu_is_visible(menu))
|
||||
return;
|
||||
|
||||
sym = menu->sym;
|
||||
if (sym && !sym_has_value(sym)) {
|
||||
if (sym_is_changable(sym) ||
|
||||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
|
||||
if (!conf_cnt++)
|
||||
printf(_("*\n* Restart config...\n*\n"));
|
||||
rootEntry = menu_get_parent_menu(menu);
|
||||
conf(rootEntry);
|
||||
}
|
||||
}
|
||||
|
||||
for (child = menu->list; child; child = child->next)
|
||||
check_conf(child);
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int opt;
|
||||
const char *name;
|
||||
struct stat tmpstat;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
input_mode = ask_new;
|
||||
break;
|
||||
case 's':
|
||||
input_mode = ask_silent;
|
||||
valid_stdin = isatty(0) && isatty(1) && isatty(2);
|
||||
break;
|
||||
case 'd':
|
||||
input_mode = set_default;
|
||||
break;
|
||||
case 'D':
|
||||
input_mode = set_default;
|
||||
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':
|
||||
input_mode = set_random;
|
||||
srand(time(NULL));
|
||||
break;
|
||||
case 'h':
|
||||
printf(_("See README for usage info\n"));
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, _("See README for usage info\n"));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (ac == optind) {
|
||||
printf(_("%s: Kconfig file missing\n"), av[0]);
|
||||
exit(1);
|
||||
}
|
||||
name = av[optind];
|
||||
conf_parse(name);
|
||||
//zconfdump(stdout);
|
||||
switch (input_mode) {
|
||||
case set_default:
|
||||
if (!defconfig_file)
|
||||
defconfig_file = conf_get_default_confname();
|
||||
if (conf_read(defconfig_file)) {
|
||||
printf(_("***\n"
|
||||
"*** Can't find default configuration \"%s\"!\n"
|
||||
"***\n"), defconfig_file);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case ask_silent:
|
||||
if (stat(".config", &tmpstat)) {
|
||||
printf(_("***\n"
|
||||
"*** You have not yet configured coreinfo!\n"
|
||||
"*** (missing .config file)\n"
|
||||
"***\n"
|
||||
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
|
||||
"*** \"make menuconfig\" or \"make xconfig\").\n"
|
||||
"***\n"));
|
||||
exit(1);
|
||||
}
|
||||
case ask_all:
|
||||
case ask_new:
|
||||
conf_read(NULL);
|
||||
break;
|
||||
case set_no:
|
||||
case set_mod:
|
||||
case set_yes:
|
||||
case set_random:
|
||||
name = getenv("KCONFIG_ALLCONFIG");
|
||||
if (name && !stat(name, &tmpstat)) {
|
||||
conf_read_simple(name, S_DEF_USER);
|
||||
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;
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (input_mode != ask_silent) {
|
||||
rootEntry = &rootmenu;
|
||||
conf(&rootmenu);
|
||||
if (input_mode == ask_all) {
|
||||
input_mode = ask_silent;
|
||||
valid_stdin = 1;
|
||||
}
|
||||
} else if (conf_get_changed()) {
|
||||
name = getenv("KCONFIG_NOSILENTUPDATE");
|
||||
if (name && *name) {
|
||||
fprintf(stderr, _("\n*** coreinfo configuration requires explicit update.\n\n"));
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
goto skip_check;
|
||||
|
||||
do {
|
||||
conf_cnt = 0;
|
||||
check_conf(&rootmenu);
|
||||
} while (conf_cnt);
|
||||
if (conf_write(NULL)) {
|
||||
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
|
||||
return 1;
|
||||
}
|
||||
skip_check:
|
||||
if (input_mode == ask_silent && conf_write_autoconf()) {
|
||||
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,814 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LKC_DIRECT_LINK
|
||||
#include "lkc.h"
|
||||
|
||||
static void conf_warning(const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
static const char *conf_filename;
|
||||
static int conf_lineno, conf_warnings, conf_unsaved;
|
||||
|
||||
const char conf_defname[] = "arch/$ARCH/defconfig";
|
||||
|
||||
static void conf_warning(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
conf_warnings++;
|
||||
}
|
||||
|
||||
const char *conf_get_configname(void)
|
||||
{
|
||||
char *name = getenv("KCONFIG_CONFIG");
|
||||
|
||||
return name ? name : ".config";
|
||||
}
|
||||
|
||||
static char *conf_expand_value(const char *in)
|
||||
{
|
||||
struct symbol *sym;
|
||||
const char *src;
|
||||
static char res_value[SYMBOL_MAXLENGTH];
|
||||
char *dst, name[SYMBOL_MAXLENGTH];
|
||||
|
||||
res_value[0] = 0;
|
||||
dst = name;
|
||||
while ((src = strchr(in, '$'))) {
|
||||
strncat(res_value, in, src - in);
|
||||
src++;
|
||||
dst = name;
|
||||
while (isalnum(*src) || *src == '_')
|
||||
*dst++ = *src++;
|
||||
*dst = 0;
|
||||
sym = sym_lookup(name, 0);
|
||||
sym_calc_value(sym);
|
||||
strcat(res_value, sym_get_string_value(sym));
|
||||
in = src;
|
||||
}
|
||||
strcat(res_value, in);
|
||||
|
||||
return res_value;
|
||||
}
|
||||
|
||||
char *conf_get_default_confname(void)
|
||||
{
|
||||
struct stat buf;
|
||||
static char fullname[PATH_MAX+1];
|
||||
char *env, *name;
|
||||
|
||||
name = conf_expand_value(conf_defname);
|
||||
env = getenv(SRCTREE);
|
||||
if (env) {
|
||||
sprintf(fullname, "%s/%s", env, name);
|
||||
if (!stat(fullname, &buf))
|
||||
return fullname;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
||||
{
|
||||
char *p2;
|
||||
|
||||
switch (sym->type) {
|
||||
case S_TRISTATE:
|
||||
if (p[0] == 'm') {
|
||||
sym->def[def].tri = mod;
|
||||
sym->flags |= def_flags;
|
||||
break;
|
||||
}
|
||||
case S_BOOLEAN:
|
||||
if (p[0] == 'y') {
|
||||
sym->def[def].tri = yes;
|
||||
sym->flags |= def_flags;
|
||||
break;
|
||||
}
|
||||
if (p[0] == 'n') {
|
||||
sym->def[def].tri = no;
|
||||
sym->flags |= def_flags;
|
||||
break;
|
||||
}
|
||||
conf_warning("symbol value '%s' invalid for %s", p, sym->name);
|
||||
break;
|
||||
case S_OTHER:
|
||||
if (*p != '"') {
|
||||
for (p2 = p; *p2 && !isspace(*p2); p2++)
|
||||
;
|
||||
sym->type = S_STRING;
|
||||
goto done;
|
||||
}
|
||||
case S_STRING:
|
||||
if (*p++ != '"')
|
||||
break;
|
||||
for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
|
||||
if (*p2 == '"') {
|
||||
*p2 = 0;
|
||||
break;
|
||||
}
|
||||
memmove(p2, p2 + 1, strlen(p2));
|
||||
}
|
||||
if (!p2) {
|
||||
conf_warning("invalid string found");
|
||||
return 1;
|
||||
}
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
done:
|
||||
if (sym_string_valid(sym, p)) {
|
||||
sym->def[def].val = strdup(p);
|
||||
sym->flags |= def_flags;
|
||||
} else {
|
||||
conf_warning("symbol value '%s' invalid for %s", p, sym->name);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_read_simple(const char *name, int def)
|
||||
{
|
||||
FILE *in = NULL;
|
||||
char line[1024];
|
||||
char *p, *p2;
|
||||
struct symbol *sym;
|
||||
int i, def_flags;
|
||||
|
||||
if (name) {
|
||||
in = zconf_fopen(name);
|
||||
} else {
|
||||
struct property *prop;
|
||||
|
||||
name = conf_get_configname();
|
||||
in = zconf_fopen(name);
|
||||
if (in)
|
||||
goto load;
|
||||
sym_add_change_count(1);
|
||||
if (!sym_defconfig_list)
|
||||
return 1;
|
||||
|
||||
for_all_defaults(sym_defconfig_list, prop) {
|
||||
if (expr_calc_value(prop->visible.expr) == no ||
|
||||
prop->expr->type != E_SYMBOL)
|
||||
continue;
|
||||
name = conf_expand_value(prop->expr->left.sym->name);
|
||||
in = zconf_fopen(name);
|
||||
if (in) {
|
||||
printf(_("#\n"
|
||||
"# using defaults found in %s\n"
|
||||
"#\n"), name);
|
||||
goto load;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!in)
|
||||
return 1;
|
||||
|
||||
load:
|
||||
conf_filename = name;
|
||||
conf_lineno = 0;
|
||||
conf_warnings = 0;
|
||||
conf_unsaved = 0;
|
||||
|
||||
def_flags = SYMBOL_DEF << def;
|
||||
for_all_symbols(i, sym) {
|
||||
sym->flags |= SYMBOL_CHANGED;
|
||||
sym->flags &= ~(def_flags|SYMBOL_VALID);
|
||||
if (sym_is_choice(sym))
|
||||
sym->flags |= def_flags;
|
||||
switch (sym->type) {
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
case S_STRING:
|
||||
if (sym->def[def].val)
|
||||
free(sym->def[def].val);
|
||||
default:
|
||||
sym->def[def].val = NULL;
|
||||
sym->def[def].tri = no;
|
||||
}
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), in)) {
|
||||
conf_lineno++;
|
||||
sym = NULL;
|
||||
switch (line[0]) {
|
||||
case '#':
|
||||
if (memcmp(line + 2, "CONFIG_", 7))
|
||||
continue;
|
||||
p = strchr(line + 9, ' ');
|
||||
if (!p)
|
||||
continue;
|
||||
*p++ = 0;
|
||||
if (strncmp(p, "is not set", 10))
|
||||
continue;
|
||||
if (def == S_DEF_USER) {
|
||||
sym = sym_find(line + 9);
|
||||
if (!sym) {
|
||||
conf_warning("trying to assign nonexistent symbol %s", line + 9);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sym = sym_lookup(line + 9, 0);
|
||||
if (sym->type == S_UNKNOWN)
|
||||
sym->type = S_BOOLEAN;
|
||||
}
|
||||
if (sym->flags & def_flags) {
|
||||
conf_warning("override: reassigning to symbol %s", sym->name);
|
||||
}
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
sym->def[def].tri = no;
|
||||
sym->flags |= def_flags;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
if (memcmp(line, "CONFIG_", 7)) {
|
||||
conf_warning("unexpected data");
|
||||
continue;
|
||||
}
|
||||
p = strchr(line + 7, '=');
|
||||
if (!p)
|
||||
continue;
|
||||
*p++ = 0;
|
||||
p2 = strchr(p, '\n');
|
||||
if (p2) {
|
||||
*p2-- = 0;
|
||||
if (*p2 == '\r')
|
||||
*p2 = 0;
|
||||
}
|
||||
if (def == S_DEF_USER) {
|
||||
sym = sym_find(line + 7);
|
||||
if (!sym) {
|
||||
conf_warning("trying to assign nonexistent symbol %s", line + 7);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sym = sym_lookup(line + 7, 0);
|
||||
if (sym->type == S_UNKNOWN)
|
||||
sym->type = S_OTHER;
|
||||
}
|
||||
if (sym->flags & def_flags) {
|
||||
conf_warning("override: reassigning to symbol %s", sym->name);
|
||||
}
|
||||
if (conf_set_sym_val(sym, def, def_flags, p))
|
||||
continue;
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
break;
|
||||
default:
|
||||
conf_warning("unexpected data");
|
||||
continue;
|
||||
}
|
||||
if (sym && sym_is_choice_value(sym)) {
|
||||
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
|
||||
switch (sym->def[def].tri) {
|
||||
case no:
|
||||
break;
|
||||
case mod:
|
||||
if (cs->def[def].tri == yes) {
|
||||
conf_warning("%s creates inconsistent choice state", sym->name);
|
||||
cs->flags &= ~def_flags;
|
||||
}
|
||||
break;
|
||||
case yes:
|
||||
if (cs->def[def].tri != no)
|
||||
conf_warning("override: %s changes choice state", sym->name);
|
||||
cs->def[def].val = sym;
|
||||
break;
|
||||
}
|
||||
cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
sym_set_change_count(0);
|
||||
|
||||
if (conf_read_simple(name, S_DEF_USER))
|
||||
return 1;
|
||||
|
||||
for_all_symbols(i, sym) {
|
||||
sym_calc_value(sym);
|
||||
if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
|
||||
goto sym_ok;
|
||||
if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
|
||||
/* check that calculated value agrees with saved value */
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
|
||||
break;
|
||||
if (!sym_is_choice(sym))
|
||||
goto sym_ok;
|
||||
default:
|
||||
if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
|
||||
goto sym_ok;
|
||||
break;
|
||||
}
|
||||
} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
|
||||
/* no previous value and not saved */
|
||||
goto sym_ok;
|
||||
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) {
|
||||
if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
|
||||
/* Reset values of generates values, so they'll appear
|
||||
* as new, if they should become visible, but that
|
||||
* doesn't quite work if the Kconfig and the saved
|
||||
* configuration disagree.
|
||||
*/
|
||||
if (sym->visible == no && !conf_unsaved)
|
||||
sym->flags &= ~SYMBOL_DEF_USER;
|
||||
switch (sym->type) {
|
||||
case S_STRING:
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
/* Reset a string value if it's out of range */
|
||||
if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
|
||||
break;
|
||||
sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
|
||||
conf_unsaved++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sym_add_change_count(conf_warnings || conf_unsaved);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 *env;
|
||||
|
||||
dirname[0] = 0;
|
||||
if (name && name[0]) {
|
||||
struct stat st;
|
||||
char *slash;
|
||||
|
||||
if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
|
||||
strcpy(dirname, name);
|
||||
strcat(dirname, "/");
|
||||
basename = conf_get_configname();
|
||||
} else if ((slash = strrchr(name, '/'))) {
|
||||
int size = slash - name + 1;
|
||||
memcpy(dirname, name, size);
|
||||
dirname[size] = 0;
|
||||
if (slash[1])
|
||||
basename = slash + 1;
|
||||
else
|
||||
basename = conf_get_configname();
|
||||
} else
|
||||
basename = name;
|
||||
} else
|
||||
basename = conf_get_configname();
|
||||
|
||||
sprintf(newname, "%s%s", dirname, basename);
|
||||
env = getenv("KCONFIG_OVERWRITECONFIG");
|
||||
if (!env || !*env) {
|
||||
sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
|
||||
out = fopen(tmpname, "w");
|
||||
} else {
|
||||
*tmpname = 0;
|
||||
out = fopen(newname, "w");
|
||||
}
|
||||
if (!out)
|
||||
return 1;
|
||||
|
||||
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"
|
||||
"# coreinfo version: %s\n"
|
||||
"%s%s"
|
||||
"#\n"),
|
||||
getenv("KERNELVERSION"),
|
||||
use_timestamp ? "# " : "",
|
||||
use_timestamp ? ctime(&now) : "");
|
||||
|
||||
if (!conf_get_changed())
|
||||
sym_clear_all_valid();
|
||||
|
||||
menu = rootmenu.list;
|
||||
while (menu) {
|
||||
sym = menu->sym;
|
||||
if (!sym) {
|
||||
if (!menu_is_visible(menu))
|
||||
goto next;
|
||||
str = menu_get_prompt(menu);
|
||||
fprintf(out, "\n"
|
||||
"#\n"
|
||||
"# %s\n"
|
||||
"#\n", str);
|
||||
} else if (!(sym->flags & SYMBOL_CHOICE)) {
|
||||
sym_calc_value(sym);
|
||||
if (!(sym->flags & SYMBOL_WRITE))
|
||||
goto next;
|
||||
sym->flags &= ~SYMBOL_WRITE;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
if (menu->list) {
|
||||
menu = menu->list;
|
||||
continue;
|
||||
}
|
||||
if (menu->next)
|
||||
menu = menu->next;
|
||||
else while ((menu = menu->parent)) {
|
||||
if (menu->next) {
|
||||
menu = menu->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(out);
|
||||
|
||||
if (*tmpname) {
|
||||
strcat(dirname, basename);
|
||||
strcat(dirname, ".old");
|
||||
rename(newname, dirname);
|
||||
if (rename(tmpname, newname))
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf(_("#\n"
|
||||
"# configuration written to %s\n"
|
||||
"#\n"), newname);
|
||||
|
||||
sym_set_change_count(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_split_config(void)
|
||||
{
|
||||
char *name, path[128];
|
||||
char *s, *d, c;
|
||||
struct symbol *sym;
|
||||
struct stat sb;
|
||||
int res, i, fd;
|
||||
|
||||
name = getenv("KCONFIG_AUTOCONFIG");
|
||||
if (!name)
|
||||
name = "include/config/auto.conf";
|
||||
conf_read_simple(name, S_DEF_AUTO);
|
||||
|
||||
if (chdir("build"))
|
||||
return 1;
|
||||
|
||||
res = 0;
|
||||
for_all_symbols(i, sym) {
|
||||
sym_calc_value(sym);
|
||||
if ((sym->flags & SYMBOL_AUTO) || !sym->name)
|
||||
continue;
|
||||
if (sym->flags & SYMBOL_WRITE) {
|
||||
if (sym->flags & SYMBOL_DEF_AUTO) {
|
||||
/*
|
||||
* symbol has old and new value,
|
||||
* so compare them...
|
||||
*/
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
if (sym_get_tristate_value(sym) ==
|
||||
sym->def[S_DEF_AUTO].tri)
|
||||
continue;
|
||||
break;
|
||||
case S_STRING:
|
||||
case S_HEX:
|
||||
case S_INT:
|
||||
if (!strcmp(sym_get_string_value(sym),
|
||||
sym->def[S_DEF_AUTO].val))
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If there is no old value, only 'no' (unset)
|
||||
* is allowed as new value.
|
||||
*/
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
if (sym_get_tristate_value(sym) == no)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!(sym->flags & SYMBOL_DEF_AUTO))
|
||||
/* There is neither an old nor a new value. */
|
||||
continue;
|
||||
/* else
|
||||
* There is an old value, but no new value ('no' (unset)
|
||||
* isn't saved in auto.conf, so the old value is always
|
||||
* different from 'no').
|
||||
*/
|
||||
|
||||
/* Replace all '_' and append ".h" */
|
||||
s = sym->name;
|
||||
d = path;
|
||||
while ((c = *s++)) {
|
||||
c = tolower(c);
|
||||
*d++ = (c == '_') ? '/' : c;
|
||||
}
|
||||
strcpy(d, ".h");
|
||||
|
||||
/* Assume directory path already exists. */
|
||||
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd == -1) {
|
||||
if (errno != ENOENT) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Create directory components,
|
||||
* unless they exist already.
|
||||
*/
|
||||
d = path;
|
||||
while ((d = strchr(d, '/'))) {
|
||||
*d = 0;
|
||||
if (stat(path, &sb) && mkdir(path, 0755)) {
|
||||
res = 1;
|
||||
goto out;
|
||||
}
|
||||
*d++ = '/';
|
||||
}
|
||||
/* Try it again. */
|
||||
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd == -1) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
out:
|
||||
if (chdir("../.."))
|
||||
return 1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int conf_write_autoconf(void)
|
||||
{
|
||||
struct symbol *sym;
|
||||
const char *str;
|
||||
char *name;
|
||||
FILE *out, *out_h;
|
||||
time_t now;
|
||||
int i, l;
|
||||
|
||||
sym_clear_all_valid();
|
||||
|
||||
file_write_dep("build/auto.conf.cmd");
|
||||
|
||||
if (conf_split_config())
|
||||
return 1;
|
||||
|
||||
out = fopen(".tmpconfig", "w");
|
||||
if (!out)
|
||||
return 1;
|
||||
|
||||
out_h = fopen(".tmpconfig.h", "w");
|
||||
if (!out_h) {
|
||||
fclose(out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sym = sym_lookup("KERNELVERSION", 0);
|
||||
sym_calc_value(sym);
|
||||
time(&now);
|
||||
fprintf(out, "#\n"
|
||||
"# Automatically generated make config: don't edit\n"
|
||||
"# coreinfo version: %s\n"
|
||||
"# %s"
|
||||
"#\n",
|
||||
getenv("KERNELVERSION"), ctime(&now));
|
||||
fprintf(out_h, "/*\n"
|
||||
" * Automatically generated C config: don't edit\n"
|
||||
" * coreinfo version: %s\n"
|
||||
" * %s"
|
||||
" */\n"
|
||||
"#define AUTOCONF_INCLUDED\n",
|
||||
getenv("KERNELVERSION"), ctime(&now));
|
||||
|
||||
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(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
|
||||
break;
|
||||
case yes:
|
||||
fprintf(out, "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;
|
||||
}
|
||||
}
|
||||
fclose(out);
|
||||
fclose(out_h);
|
||||
|
||||
name = getenv("KCONFIG_AUTOHEADER");
|
||||
if (!name)
|
||||
name = "include/linux/autoconf.h";
|
||||
if (rename(".tmpconfig.h", name))
|
||||
return 1;
|
||||
name = getenv("KCONFIG_AUTOCONFIG");
|
||||
if (!name)
|
||||
name = "include/config/auto.conf";
|
||||
/*
|
||||
* This must be the last step, kbuild has a dependency on auto.conf
|
||||
* and this marks the successful completion of the previous steps.
|
||||
*/
|
||||
if (rename(".tmpconfig", name))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sym_change_count;
|
||||
static void (*conf_changed_callback)(void);
|
||||
|
||||
void sym_set_change_count(int count)
|
||||
{
|
||||
int _sym_change_count = sym_change_count;
|
||||
sym_change_count = count;
|
||||
if (conf_changed_callback &&
|
||||
(bool)_sym_change_count != (bool)count)
|
||||
conf_changed_callback();
|
||||
}
|
||||
|
||||
void sym_add_change_count(int count)
|
||||
{
|
||||
sym_set_change_count(count + sym_change_count);
|
||||
}
|
||||
|
||||
bool conf_get_changed(void)
|
||||
{
|
||||
return sym_change_count;
|
||||
}
|
||||
|
||||
void conf_set_changed_callback(void (*fn)(void))
|
||||
{
|
||||
conf_changed_callback = fn;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#ifndef EXPR_H
|
||||
#define EXPR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
struct file {
|
||||
struct file *next;
|
||||
struct file *parent;
|
||||
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
|
||||
};
|
||||
|
||||
union expr_data {
|
||||
struct expr *expr;
|
||||
struct symbol *sym;
|
||||
};
|
||||
|
||||
struct expr {
|
||||
enum expr_type type;
|
||||
union expr_data left, right;
|
||||
};
|
||||
|
||||
#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
|
||||
#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
|
||||
#define EXPR_NOT(dep) (2-(dep))
|
||||
|
||||
#define expr_list_for_each_sym(l, e, s) \
|
||||
for (e = (l); e && (s = e->right.sym); e = e->left.expr)
|
||||
|
||||
struct expr_value {
|
||||
struct expr *expr;
|
||||
tristate tri;
|
||||
};
|
||||
|
||||
struct symbol_value {
|
||||
void *val;
|
||||
tristate tri;
|
||||
};
|
||||
|
||||
enum symbol_type {
|
||||
S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
|
||||
};
|
||||
|
||||
enum {
|
||||
S_DEF_USER, /* main user value */
|
||||
S_DEF_AUTO,
|
||||
};
|
||||
|
||||
struct symbol {
|
||||
struct symbol *next;
|
||||
char *name;
|
||||
enum symbol_type type;
|
||||
struct symbol_value curr;
|
||||
struct symbol_value def[4];
|
||||
tristate visible;
|
||||
int flags;
|
||||
struct property *prop;
|
||||
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 SYMBOL_CONST 0x0001
|
||||
#define SYMBOL_CHECK 0x0008
|
||||
#define SYMBOL_CHOICE 0x0010
|
||||
#define SYMBOL_CHOICEVAL 0x0020
|
||||
#define SYMBOL_VALID 0x0080
|
||||
#define SYMBOL_OPTIONAL 0x0100
|
||||
#define SYMBOL_WRITE 0x0200
|
||||
#define SYMBOL_CHANGED 0x0400
|
||||
#define SYMBOL_AUTO 0x1000
|
||||
#define SYMBOL_CHECKED 0x2000
|
||||
#define SYMBOL_WARNED 0x8000
|
||||
#define SYMBOL_DEF 0x10000
|
||||
#define SYMBOL_DEF_USER 0x10000
|
||||
#define SYMBOL_DEF_AUTO 0x20000
|
||||
#define SYMBOL_DEF3 0x40000
|
||||
#define SYMBOL_DEF4 0x80000
|
||||
|
||||
#define SYMBOL_MAXLENGTH 256
|
||||
#define SYMBOL_HASHSIZE 257
|
||||
#define SYMBOL_HASHMASK 0xff
|
||||
|
||||
enum prop_type {
|
||||
P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE,
|
||||
P_SELECT, P_RANGE, P_ENV
|
||||
};
|
||||
|
||||
struct property {
|
||||
struct property *next;
|
||||
struct symbol *sym;
|
||||
enum prop_type type;
|
||||
const char *text;
|
||||
struct expr_value visible;
|
||||
struct expr *expr;
|
||||
struct menu *menu;
|
||||
struct file *file;
|
||||
int lineno;
|
||||
};
|
||||
|
||||
#define for_all_properties(sym, st, tok) \
|
||||
for (st = sym->prop; st; st = st->next) \
|
||||
if (st->type == (tok))
|
||||
#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
|
||||
#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
|
||||
#define for_all_prompts(sym, st) \
|
||||
for (st = sym->prop; st; st = st->next) \
|
||||
if (st->text)
|
||||
|
||||
struct menu {
|
||||
struct menu *next;
|
||||
struct menu *parent;
|
||||
struct menu *list;
|
||||
struct symbol *sym;
|
||||
struct property *prompt;
|
||||
struct expr *dep;
|
||||
unsigned int flags;
|
||||
char *help;
|
||||
struct file *file;
|
||||
int lineno;
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define MENU_CHANGED 0x0001
|
||||
#define MENU_ROOT 0x0002
|
||||
|
||||
#ifndef SWIG
|
||||
|
||||
extern struct file *file_list;
|
||||
extern struct file *current_file;
|
||||
struct file *lookup_file(const char *name);
|
||||
|
||||
extern struct symbol symbol_yes, symbol_no, symbol_mod;
|
||||
extern struct symbol *modules_sym;
|
||||
extern struct symbol *sym_defconfig_list;
|
||||
extern int cdebug;
|
||||
struct expr *expr_alloc_symbol(struct symbol *sym);
|
||||
struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
|
||||
struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
|
||||
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
|
||||
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
|
||||
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
|
||||
struct expr *expr_copy(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);
|
||||
|
||||
void expr_fprint(struct expr *e, FILE *out);
|
||||
struct gstr; /* forward */
|
||||
void expr_gstr_print(struct expr *e, struct gstr *gs);
|
||||
|
||||
static inline int expr_is_yes(struct expr *e)
|
||||
{
|
||||
return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
|
||||
}
|
||||
|
||||
static inline int expr_is_no(struct expr *e)
|
||||
{
|
||||
return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EXPR_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,648 @@
|
|||
<?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 coreinfo Configurator</property>
|
||||
<property name="type">GTK_WINDOW_TOPLEVEL</property>
|
||||
<property name="window_position">GTK_WIN_POS_NONE</property>
|
||||
<property name="modal">False</property>
|
||||
<property name="default_width">640</property>
|
||||
<property name="default_height">480</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="destroy_with_parent">False</property>
|
||||
<property name="decorated">True</property>
|
||||
<property name="skip_taskbar_hint">False</property>
|
||||
<property name="skip_pager_hint">False</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||
<signal name="destroy" handler="on_window1_destroy" object="window1"/>
|
||||
<signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/>
|
||||
<signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuBar" id="menubar1">
|
||||
<property name="visible">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="file1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_File</property>
|
||||
<property name="use_underline">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenu" id="file1_menu">
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="load1">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Load a config file</property>
|
||||
<property name="label" translatable="yes">_Load</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_load1_activate"/>
|
||||
<accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
||||
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image39">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-open</property>
|
||||
<property name="icon_size">1</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="save1">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Save the config in .config</property>
|
||||
<property name="label" translatable="yes">_Save</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_save_activate"/>
|
||||
<accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
||||
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image40">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-save</property>
|
||||
<property name="icon_size">1</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="save_as1">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Save the config in a file</property>
|
||||
<property name="label" translatable="yes">Save _as</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_save_as1_activate"/>
|
||||
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image41">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-save-as</property>
|
||||
<property name="icon_size">1</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separator1">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="quit1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Quit</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_quit1_activate"/>
|
||||
<accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
||||
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image42">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-quit</property>
|
||||
<property name="icon_size">1</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="options1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Options</property>
|
||||
<property name="use_underline">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenu" id="options1_menu">
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckMenuItem" id="show_name1">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Show name</property>
|
||||
<property name="label" translatable="yes">Show _name</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="active">False</property>
|
||||
<signal name="activate" handler="on_show_name1_activate"/>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckMenuItem" id="show_range1">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
|
||||
<property name="label" translatable="yes">Show _range</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="active">False</property>
|
||||
<signal name="activate" handler="on_show_range1_activate"/>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckMenuItem" id="show_data1">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Show value of the option</property>
|
||||
<property name="label" translatable="yes">Show _data</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="active">False</property>
|
||||
<signal name="activate" handler="on_show_data1_activate"/>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separator2">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckMenuItem" id="show_all_options1">
|
||||
<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"/>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckMenuItem" id="show_debug_info1">
|
||||
<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="use_underline">True</property>
|
||||
<property name="active">False</property>
|
||||
<signal name="activate" handler="on_show_debug_info1_activate"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="help1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Help</property>
|
||||
<property name="use_underline">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenu" id="help1_menu">
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="introduction1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Introduction</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
|
||||
<accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
||||
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image43">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-dialog-question</property>
|
||||
<property name="icon_size">1</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="about1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_About</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
|
||||
<accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
||||
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image44">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-properties</property>
|
||||
<property name="icon_size">1</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="license1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_License</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
|
||||
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image45">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-justify-fill</property>
|
||||
<property name="icon_size">1</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHandleBox" id="handlebox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<property name="handle_position">GTK_POS_LEFT</property>
|
||||
<property name="snap_edge">GTK_POS_TOP</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolbar" id="toolbar1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
|
||||
<property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
|
||||
<property name="tooltips">True</property>
|
||||
<property name="show_arrow">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolButton" id="button1">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
|
||||
<property name="label" translatable="yes">Back</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="stock_id">gtk-undo</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
<signal name="clicked" handler="on_back_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolItem" id="toolitem1">
|
||||
<property name="visible">True</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVSeparator" id="vseparator1">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolButton" id="button2">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Load a config file</property>
|
||||
<property name="label" translatable="yes">Load</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="stock_id">gtk-open</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
<signal name="clicked" handler="on_load_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolButton" id="button3">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Save a config file</property>
|
||||
<property name="label" translatable="yes">Save</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="stock_id">gtk-save</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
<signal name="clicked" handler="on_save_activate"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolItem" id="toolitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVSeparator" id="vseparator2">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolButton" id="button4">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Single view</property>
|
||||
<property name="label" translatable="yes">Single</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="stock_id">gtk-missing-image</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
<signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolButton" id="button5">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Split view</property>
|
||||
<property name="label" translatable="yes">Split</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="stock_id">gtk-missing-image</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
<signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolButton" id="button6">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Full view</property>
|
||||
<property name="label" translatable="yes">Full</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="stock_id">gtk-missing-image</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
<signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolItem" id="toolitem3">
|
||||
<property name="visible">True</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVSeparator" id="vseparator3">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolButton" id="button7">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
|
||||
<property name="label" translatable="yes">Collapse</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="stock_id">gtk-remove</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
<signal name="clicked" handler="on_collapse_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolButton" id="button8">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
|
||||
<property name="label" translatable="yes">Expand</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="stock_id">gtk-add</property>
|
||||
<property name="visible_horizontal">True</property>
|
||||
<property name="visible_vertical">True</property>
|
||||
<property name="is_important">False</property>
|
||||
<signal name="clicked" handler="on_expand_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHPaned" id="hpaned1">
|
||||
<property name="width_request">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="position">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="treeview1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">True</property>
|
||||
<property name="rules_hint">False</property>
|
||||
<property name="reorderable">False</property>
|
||||
<property name="enable_search">True</property>
|
||||
<signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/>
|
||||
<signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/>
|
||||
<signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="shrink">True</property>
|
||||
<property name="resize">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVPaned" id="vpaned1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="position">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
<property name="visible">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="treeview2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="has_focus">True</property>
|
||||
<property name="headers_visible">True</property>
|
||||
<property name="rules_hint">False</property>
|
||||
<property name="reorderable">False</property>
|
||||
<property name="enable_search">True</property>
|
||||
<signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/>
|
||||
<signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/>
|
||||
<signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="shrink">True</property>
|
||||
<property name="resize">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow3">
|
||||
<property name="visible">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTextView" id="textview3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">False</property>
|
||||
<property name="overwrite">False</property>
|
||||
<property name="accepts_tab">True</property>
|
||||
<property name="justification">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap_mode">GTK_WRAP_WORD</property>
|
||||
<property name="cursor_visible">True</property>
|
||||
<property name="pixels_above_lines">0</property>
|
||||
<property name="pixels_below_lines">0</property>
|
||||
<property name="pixels_inside_wrap">0</property>
|
||||
<property name="left_margin">0</property>
|
||||
<property name="right_margin">0</property>
|
||||
<property name="indent">0</property>
|
||||
<property name="text" translatable="yes">Sorry, no help available for this option yet.</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="shrink">True</property>
|
||||
<property name="resize">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="shrink">True</property>
|
||||
<property name="resize">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
||||
</glade-interface>
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
static const char *xpm_load[] = {
|
||||
"22 22 5 1",
|
||||
". c None",
|
||||
"# c #000000",
|
||||
"c c #838100",
|
||||
"a c #ffff00",
|
||||
"b c #ffffff",
|
||||
"......................",
|
||||
"......................",
|
||||
"......................",
|
||||
"............####....#.",
|
||||
"...........#....##.##.",
|
||||
"..................###.",
|
||||
".................####.",
|
||||
".####...........#####.",
|
||||
"#abab##########.......",
|
||||
"#babababababab#.......",
|
||||
"#ababababababa#.......",
|
||||
"#babababababab#.......",
|
||||
"#ababab###############",
|
||||
"#babab##cccccccccccc##",
|
||||
"#abab##cccccccccccc##.",
|
||||
"#bab##cccccccccccc##..",
|
||||
"#ab##cccccccccccc##...",
|
||||
"#b##cccccccccccc##....",
|
||||
"###cccccccccccc##.....",
|
||||
"##cccccccccccc##......",
|
||||
"###############.......",
|
||||
"......................"};
|
||||
|
||||
static const char *xpm_save[] = {
|
||||
"22 22 5 1",
|
||||
". c None",
|
||||
"# c #000000",
|
||||
"a c #838100",
|
||||
"b c #c5c2c5",
|
||||
"c c #cdb6d5",
|
||||
"......................",
|
||||
".####################.",
|
||||
".#aa#bbbbbbbbbbbb#bb#.",
|
||||
".#aa#bbbbbbbbbbbb#bb#.",
|
||||
".#aa#bbbbbbbbbcbb####.",
|
||||
".#aa#bbbccbbbbbbb#aa#.",
|
||||
".#aa#bbbccbbbbbbb#aa#.",
|
||||
".#aa#bbbbbbbbbbbb#aa#.",
|
||||
".#aa#bbbbbbbbbbbb#aa#.",
|
||||
".#aa#bbbbbbbbbbbb#aa#.",
|
||||
".#aa#bbbbbbbbbbbb#aa#.",
|
||||
".#aaa############aaa#.",
|
||||
".#aaaaaaaaaaaaaaaaaa#.",
|
||||
".#aaaaaaaaaaaaaaaaaa#.",
|
||||
".#aaa#############aa#.",
|
||||
".#aaa#########bbb#aa#.",
|
||||
".#aaa#########bbb#aa#.",
|
||||
".#aaa#########bbb#aa#.",
|
||||
".#aaa#########bbb#aa#.",
|
||||
".#aaa#########bbb#aa#.",
|
||||
"..##################..",
|
||||
"......................"};
|
||||
|
||||
static const char *xpm_back[] = {
|
||||
"22 22 3 1",
|
||||
". c None",
|
||||
"# c #000083",
|
||||
"a c #838183",
|
||||
"......................",
|
||||
"......................",
|
||||
"......................",
|
||||
"......................",
|
||||
"......................",
|
||||
"...........######a....",
|
||||
"..#......##########...",
|
||||
"..##...####......##a..",
|
||||
"..###.###.........##..",
|
||||
"..######..........##..",
|
||||
"..#####...........##..",
|
||||
"..######..........##..",
|
||||
"..#######.........##..",
|
||||
"..########.......##a..",
|
||||
"...............a###...",
|
||||
"...............###....",
|
||||
"......................",
|
||||
"......................",
|
||||
"......................",
|
||||
"......................",
|
||||
"......................",
|
||||
"......................"};
|
||||
|
||||
static const char *xpm_tree_view[] = {
|
||||
"22 22 2 1",
|
||||
". c None",
|
||||
"# c #000000",
|
||||
"......................",
|
||||
"......................",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......########........",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......########........",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......#...............",
|
||||
"......########........",
|
||||
"......................",
|
||||
"......................"};
|
||||
|
||||
static const char *xpm_single_view[] = {
|
||||
"22 22 2 1",
|
||||
". c None",
|
||||
"# c #000000",
|
||||
"......................",
|
||||
"......................",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"..........#...........",
|
||||
"......................",
|
||||
"......................"};
|
||||
|
||||
static const char *xpm_split_view[] = {
|
||||
"22 22 2 1",
|
||||
". c None",
|
||||
"# c #000000",
|
||||
"......................",
|
||||
"......................",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......#......#........",
|
||||
"......................",
|
||||
"......................"};
|
||||
|
||||
static const char *xpm_symbol_no[] = {
|
||||
"12 12 2 1",
|
||||
" c white",
|
||||
". c black",
|
||||
" ",
|
||||
" .......... ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" .......... ",
|
||||
" "};
|
||||
|
||||
static const char *xpm_symbol_mod[] = {
|
||||
"12 12 2 1",
|
||||
" c white",
|
||||
". c black",
|
||||
" ",
|
||||
" .......... ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . .. . ",
|
||||
" . .... . ",
|
||||
" . .... . ",
|
||||
" . .. . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" .......... ",
|
||||
" "};
|
||||
|
||||
static const char *xpm_symbol_yes[] = {
|
||||
"12 12 2 1",
|
||||
" c white",
|
||||
". c black",
|
||||
" ",
|
||||
" .......... ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . . ",
|
||||
" . .. . ",
|
||||
" . . .. . ",
|
||||
" . .... . ",
|
||||
" . .. . ",
|
||||
" . . ",
|
||||
" .......... ",
|
||||
" "};
|
||||
|
||||
static const char *xpm_choice_no[] = {
|
||||
"12 12 2 1",
|
||||
" c white",
|
||||
". c black",
|
||||
" ",
|
||||
" .... ",
|
||||
" .. .. ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" .. .. ",
|
||||
" .... ",
|
||||
" "};
|
||||
|
||||
static const char *xpm_choice_yes[] = {
|
||||
"12 12 2 1",
|
||||
" c white",
|
||||
". c black",
|
||||
" ",
|
||||
" .... ",
|
||||
" .. .. ",
|
||||
" . . ",
|
||||
" . .. . ",
|
||||
" . .... . ",
|
||||
" . .... . ",
|
||||
" . .. . ",
|
||||
" . . ",
|
||||
" .. .. ",
|
||||
" .... ",
|
||||
" "};
|
||||
|
||||
static const char *xpm_menu[] = {
|
||||
"12 12 2 1",
|
||||
" c white",
|
||||
". c black",
|
||||
" ",
|
||||
" .......... ",
|
||||
" . . ",
|
||||
" . .. . ",
|
||||
" . .... . ",
|
||||
" . ...... . ",
|
||||
" . ...... . ",
|
||||
" . .... . ",
|
||||
" . .. . ",
|
||||
" . . ",
|
||||
" .......... ",
|
||||
" "};
|
||||
|
||||
static const char *xpm_menu_inv[] = {
|
||||
"12 12 2 1",
|
||||
" c white",
|
||||
". c black",
|
||||
" ",
|
||||
" .......... ",
|
||||
" .......... ",
|
||||
" .. ...... ",
|
||||
" .. .... ",
|
||||
" .. .. ",
|
||||
" .. .. ",
|
||||
" .. .... ",
|
||||
" .. ...... ",
|
||||
" .......... ",
|
||||
" .......... ",
|
||||
" "};
|
||||
|
||||
static const char *xpm_menuback[] = {
|
||||
"12 12 2 1",
|
||||
" c white",
|
||||
". c black",
|
||||
" ",
|
||||
" .......... ",
|
||||
" . . ",
|
||||
" . .. . ",
|
||||
" . .... . ",
|
||||
" . ...... . ",
|
||||
" . ...... . ",
|
||||
" . .... . ",
|
||||
" . .. . ",
|
||||
" . . ",
|
||||
" .......... ",
|
||||
" "};
|
||||
|
||||
static const char *xpm_void[] = {
|
||||
"12 12 2 1",
|
||||
" c white",
|
||||
". c black",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
|
@ -0,0 +1,35 @@
|
|||
#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("./util/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
|
||||
}
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
|
||||
*
|
||||
* Released under the terms of the GNU GPL v2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LKC_DIRECT_LINK
|
||||
#include "lkc.h"
|
||||
|
||||
static char *escape(const char* text, char *bf, int len)
|
||||
{
|
||||
char *bfp = bf;
|
||||
int multiline = strchr(text, '\n') != NULL;
|
||||
int eol = 0;
|
||||
int textlen = strlen(text);
|
||||
|
||||
if ((textlen > 0) && (text[textlen-1] == '\n'))
|
||||
eol = 1;
|
||||
|
||||
*bfp++ = '"';
|
||||
--len;
|
||||
|
||||
if (multiline) {
|
||||
*bfp++ = '"';
|
||||
*bfp++ = '\n';
|
||||
*bfp++ = '"';
|
||||
len -= 3;
|
||||
}
|
||||
|
||||
while (*text != '\0' && len > 1) {
|
||||
if (*text == '"')
|
||||
*bfp++ = '\\';
|
||||
else if (*text == '\n') {
|
||||
*bfp++ = '\\';
|
||||
*bfp++ = 'n';
|
||||
*bfp++ = '"';
|
||||
*bfp++ = '\n';
|
||||
*bfp++ = '"';
|
||||
len -= 5;
|
||||
++text;
|
||||
goto next;
|
||||
}
|
||||
*bfp++ = *text++;
|
||||
next:
|
||||
--len;
|
||||
}
|
||||
|
||||
if (multiline && eol)
|
||||
bfp -= 3;
|
||||
|
||||
*bfp++ = '"';
|
||||
*bfp = '\0';
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
struct file_line {
|
||||
struct file_line *next;
|
||||
char* file;
|
||||
int lineno;
|
||||
};
|
||||
|
||||
static struct file_line *file_line__new(char *file, int lineno)
|
||||
{
|
||||
struct file_line *self = malloc(sizeof(*self));
|
||||
|
||||
if (self == NULL)
|
||||
goto out;
|
||||
|
||||
self->file = file;
|
||||
self->lineno = lineno;
|
||||
self->next = NULL;
|
||||
out:
|
||||
return self;
|
||||
}
|
||||
|
||||
struct message {
|
||||
const char *msg;
|
||||
const char *option;
|
||||
struct message *next;
|
||||
struct file_line *files;
|
||||
};
|
||||
|
||||
static struct message *message__list;
|
||||
|
||||
static struct message *message__new(const char *msg, char *option, char *file, int lineno)
|
||||
{
|
||||
struct message *self = malloc(sizeof(*self));
|
||||
|
||||
if (self == NULL)
|
||||
goto out;
|
||||
|
||||
self->files = file_line__new(file, lineno);
|
||||
if (self->files == NULL)
|
||||
goto out_fail;
|
||||
|
||||
self->msg = strdup(msg);
|
||||
if (self->msg == NULL)
|
||||
goto out_fail_msg;
|
||||
|
||||
self->option = option;
|
||||
self->next = NULL;
|
||||
out:
|
||||
return self;
|
||||
out_fail_msg:
|
||||
free(self->files);
|
||||
out_fail:
|
||||
free(self);
|
||||
self = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static struct message *mesage__find(const char *msg)
|
||||
{
|
||||
struct message *m = message__list;
|
||||
|
||||
while (m != NULL) {
|
||||
if (strcmp(m->msg, msg) == 0)
|
||||
break;
|
||||
m = m->next;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static int message__add_file_line(struct message *self, char *file, int lineno)
|
||||
{
|
||||
int rc = -1;
|
||||
struct file_line *fl = file_line__new(file, lineno);
|
||||
|
||||
if (fl == NULL)
|
||||
goto out;
|
||||
|
||||
fl->next = self->files;
|
||||
self->files = fl;
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int message__add(const char *msg, char *option, char *file, int lineno)
|
||||
{
|
||||
int rc = 0;
|
||||
char bf[16384];
|
||||
char *escaped = escape(msg, bf, sizeof(bf));
|
||||
struct message *m = mesage__find(escaped);
|
||||
|
||||
if (m != NULL)
|
||||
rc = message__add_file_line(m, file, lineno);
|
||||
else {
|
||||
m = message__new(escaped, option, file, lineno);
|
||||
|
||||
if (m != NULL) {
|
||||
m->next = message__list;
|
||||
message__list = m;
|
||||
} else
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void menu_build_message_list(struct menu *menu)
|
||||
{
|
||||
struct menu *child;
|
||||
|
||||
message__add(menu_get_prompt(menu), NULL,
|
||||
menu->file == NULL ? "Root Menu" : menu->file->name,
|
||||
menu->lineno);
|
||||
|
||||
if (menu->sym != NULL && menu_has_help(menu))
|
||||
message__add(menu_get_help(menu), menu->sym->name,
|
||||
menu->file == NULL ? "Root Menu" : menu->file->name,
|
||||
menu->lineno);
|
||||
|
||||
for (child = menu->list; child != NULL; child = child->next)
|
||||
if (child->prompt != NULL)
|
||||
menu_build_message_list(child);
|
||||
}
|
||||
|
||||
static void message__print_file_lineno(struct message *self)
|
||||
{
|
||||
struct file_line *fl = self->files;
|
||||
|
||||
putchar('\n');
|
||||
if (self->option != NULL)
|
||||
printf("# %s:00000\n", self->option);
|
||||
|
||||
printf("#: %s:%d", fl->file, fl->lineno);
|
||||
fl = fl->next;
|
||||
|
||||
while (fl != NULL) {
|
||||
printf(", %s:%d", fl->file, fl->lineno);
|
||||
fl = fl->next;
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void message__print_gettext_msgid_msgstr(struct message *self)
|
||||
{
|
||||
message__print_file_lineno(self);
|
||||
|
||||
printf("msgid %s\n"
|
||||
"msgstr \"\"\n", self->msg);
|
||||
}
|
||||
|
||||
void menu__xgettext(void)
|
||||
{
|
||||
struct message *m = message__list;
|
||||
|
||||
while (m != NULL) {
|
||||
/* skip empty lines ("") */
|
||||
if (strlen(m->msg) > sizeof("\"\""))
|
||||
message__print_gettext_msgid_msgstr(m);
|
||||
m = m->next;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
conf_parse(av[1]);
|
||||
|
||||
menu_build_message_list(menu_get_root_menu(NULL));
|
||||
menu__xgettext();
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#ifndef LKC_H
|
||||
#define LKC_H
|
||||
|
||||
#include "expr.h"
|
||||
|
||||
#ifndef KBUILD_NO_NLS
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
# define textdomain(Domainname) ((const char *) (Domainname))
|
||||
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
|
||||
#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 "coreinfo"
|
||||
#define LOCALEDIR "/usr/share/locale"
|
||||
|
||||
#define _(text) gettext(text)
|
||||
#define N_(text) (text)
|
||||
|
||||
|
||||
#define TF_COMMAND 0x0001
|
||||
#define TF_PARAM 0x0002
|
||||
#define TF_OPTION 0x0004
|
||||
|
||||
#define T_OPT_MODULES 1
|
||||
#define T_OPT_DEFCONFIG_LIST 2
|
||||
#define T_OPT_ENV 3
|
||||
|
||||
struct kconf_id {
|
||||
int name;
|
||||
int token;
|
||||
unsigned int flags;
|
||||
enum symbol_type stype;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
/* confdata.c */
|
||||
const char *conf_get_configname(void);
|
||||
char *conf_get_default_confname(void);
|
||||
void sym_set_change_count(int count);
|
||||
void sym_add_change_count(int count);
|
||||
|
||||
/* kconfig_load.c */
|
||||
void kconfig_load(void);
|
||||
|
||||
/* menu.c */
|
||||
void menu_init(void);
|
||||
void menu_warn(struct menu *menu, const char *fmt, ...);
|
||||
struct menu *menu_add_menu(void);
|
||||
void menu_end_menu(void);
|
||||
void menu_add_entry(struct symbol *sym);
|
||||
void menu_end_entry(void);
|
||||
void menu_add_dep(struct expr *dep);
|
||||
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
|
||||
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
|
||||
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
|
||||
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
|
||||
void menu_add_option(int token, char *arg);
|
||||
void menu_finalize(struct menu *parent);
|
||||
void menu_set_type(int type);
|
||||
|
||||
/* util.c */
|
||||
struct file *file_lookup(const char *name);
|
||||
int file_write_dep(const char *name);
|
||||
|
||||
struct gstr {
|
||||
size_t len;
|
||||
char *s;
|
||||
};
|
||||
struct gstr str_new(void);
|
||||
struct gstr str_assign(const char *s);
|
||||
void str_free(struct gstr *gs);
|
||||
void str_append(struct gstr *gs, const char *s);
|
||||
void str_printf(struct gstr *gs, const char *fmt, ...);
|
||||
const char *str_get(struct gstr *gs);
|
||||
|
||||
/* symbol.c */
|
||||
extern struct expr *sym_env_list;
|
||||
|
||||
void sym_init(void);
|
||||
void sym_clear_all_valid(void);
|
||||
void sym_set_all_changed(void);
|
||||
void sym_set_changed(struct symbol *sym);
|
||||
struct symbol *sym_check_deps(struct symbol *sym);
|
||||
struct property *prop_alloc(enum prop_type type, struct symbol *sym);
|
||||
struct symbol *prop_get_symbol(struct property *prop);
|
||||
struct property *sym_get_env_prop(struct symbol *sym);
|
||||
|
||||
static inline tristate sym_get_tristate_value(struct symbol *sym)
|
||||
{
|
||||
return sym->curr.tri;
|
||||
}
|
||||
|
||||
|
||||
static inline struct symbol *sym_get_choice_value(struct symbol *sym)
|
||||
{
|
||||
return (struct symbol *)sym->curr.val;
|
||||
}
|
||||
|
||||
static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
|
||||
{
|
||||
return sym_set_tristate_value(chval, yes);
|
||||
}
|
||||
|
||||
static inline bool sym_is_choice(struct symbol *sym)
|
||||
{
|
||||
return sym->flags & SYMBOL_CHOICE ? true : false;
|
||||
}
|
||||
|
||||
static inline bool sym_is_choice_value(struct symbol *sym)
|
||||
{
|
||||
return sym->flags & SYMBOL_CHOICEVAL ? true : false;
|
||||
}
|
||||
|
||||
static inline bool sym_is_optional(struct symbol *sym)
|
||||
{
|
||||
return sym->flags & SYMBOL_OPTIONAL ? true : false;
|
||||
}
|
||||
|
||||
static inline bool sym_has_value(struct symbol *sym)
|
||||
{
|
||||
return sym->flags & SYMBOL_DEF_USER ? true : false;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LKC_H */
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
/* 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)));
|
||||
|
||||
/* menu.c */
|
||||
P(rootmenu,struct menu,);
|
||||
|
||||
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));
|
||||
|
||||
/* symbol.c */
|
||||
P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
|
||||
|
||||
P(sym_lookup,struct symbol *,(const char *name, int isconst));
|
||||
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));
|
||||
|
||||
P(prop_get_type_name,const char *,(enum prop_type type));
|
||||
|
||||
/* expr.c */
|
||||
P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
|
||||
P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken));
|
|
@ -0,0 +1,4 @@
|
|||
#
|
||||
# Generated files
|
||||
#
|
||||
lxdialog
|
|
@ -0,0 +1,4 @@
|
|||
This is NOT the official version of dialog. This version has been
|
||||
significantly modified from the original. It is for use by the Linux
|
||||
kernel configuration script. Please do not bother Savio Lam with
|
||||
questions about this program.
|
|
@ -0,0 +1,80 @@
|
|||
#!/bin/sh
|
||||
# Check ncurses compatibility
|
||||
|
||||
# What library to link
|
||||
ldflags()
|
||||
{
|
||||
for ext in so a dylib ; do
|
||||
for lib in ncursesw ncurses curses ; do
|
||||
$cc -print-file-name=lib${lib}.${ext} | grep -q /
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "-l${lib}"
|
||||
exit
|
||||
fi
|
||||
done
|
||||
done
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Where is ncurses.h?
|
||||
ccflags()
|
||||
{
|
||||
if [ -f /usr/include/ncurses/ncurses.h ]; then
|
||||
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
|
||||
elif [ -f /usr/include/ncurses/curses.h ]; then
|
||||
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
|
||||
elif [ -f /usr/include/ncurses.h ]; then
|
||||
echo '-DCURSES_LOC="<ncurses.h>"'
|
||||
else
|
||||
echo '-DCURSES_LOC="<curses.h>"'
|
||||
fi
|
||||
}
|
||||
|
||||
# Temp file, try to clean up after us
|
||||
tmp=.lxdialog.tmp
|
||||
trap "rm -f $tmp" 0 1 2 3 15
|
||||
|
||||
# Check if we can link to ncurses
|
||||
check() {
|
||||
echo -e " #include CURSES_LOC \n main() {}" |
|
||||
$cc -xc - -o $tmp 2> /dev/null
|
||||
if [ $? != 0 ]; then
|
||||
echo " *** Unable to find the ncurses libraries or the" 1>&2
|
||||
echo " *** required header files." 1>&2
|
||||
echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2
|
||||
echo " *** " 1>&2
|
||||
echo " *** Install ncurses (ncurses-devel) and try again." 1>&2
|
||||
echo " *** " 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
printf "Usage: $0 [-check compiler options|-header|-library]\n"
|
||||
}
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cc=""
|
||||
case "$1" in
|
||||
"-check")
|
||||
shift
|
||||
cc="$@"
|
||||
check
|
||||
;;
|
||||
"-ccflags")
|
||||
ccflags
|
||||
;;
|
||||
"-ldflags")
|
||||
shift
|
||||
cc="$@"
|
||||
ldflags
|
||||
;;
|
||||
"*")
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* checklist.c -- implements the checklist box
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
|
||||
* Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
static int list_width, check_x, item_x;
|
||||
|
||||
/*
|
||||
* Print list item
|
||||
*/
|
||||
static void print_item(WINDOW * win, int choice, int selected)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Clear 'residue' of last item */
|
||||
wattrset(win, dlg.menubox.atr);
|
||||
wmove(win, choice, 0);
|
||||
for (i = 0; i < list_width; i++)
|
||||
waddch(win, ' ');
|
||||
|
||||
wmove(win, choice, check_x);
|
||||
wattrset(win, selected ? dlg.check_selected.atr
|
||||
: dlg.check.atr);
|
||||
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]);
|
||||
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
|
||||
waddstr(win, (char *)item_str() + 1);
|
||||
if (selected) {
|
||||
wmove(win, choice, check_x + 1);
|
||||
wrefresh(win);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the scroll indicators.
|
||||
*/
|
||||
static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
|
||||
int y, int x, int height)
|
||||
{
|
||||
wmove(win, y, x);
|
||||
|
||||
if (scroll > 0) {
|
||||
wattrset(win, dlg.uarrow.atr);
|
||||
waddch(win, ACS_UARROW);
|
||||
waddstr(win, "(-)");
|
||||
} else {
|
||||
wattrset(win, dlg.menubox.atr);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
}
|
||||
|
||||
y = y + height + 1;
|
||||
wmove(win, y, x);
|
||||
|
||||
if ((height < item_no) && (scroll + choice < item_no - 1)) {
|
||||
wattrset(win, dlg.darrow.atr);
|
||||
waddch(win, ACS_DARROW);
|
||||
waddstr(win, "(+)");
|
||||
} else {
|
||||
wattrset(win, dlg.menubox_border.atr);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Display the termination buttons
|
||||
*/
|
||||
static void print_buttons(WINDOW * dialog, int height, int width, int selected)
|
||||
{
|
||||
int x = width / 2 - 11;
|
||||
int y = height - 2;
|
||||
|
||||
print_button(dialog, gettext("Select"), y, x, selected == 0);
|
||||
print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
|
||||
|
||||
wmove(dialog, y, x + 1 + 14 * selected);
|
||||
wrefresh(dialog);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a dialog box with a list of options that can be turned on or off
|
||||
* in the style of radiolist (only one option turned on at a time).
|
||||
*/
|
||||
int dialog_checklist(const char *title, const char *prompt, int height,
|
||||
int width, int list_height)
|
||||
{
|
||||
int i, x, y, box_x, box_y;
|
||||
int key = 0, button = 0, choice = 0, scroll = 0, max_choice;
|
||||
WINDOW *dialog, *list;
|
||||
|
||||
/* which item to highlight */
|
||||
item_foreach() {
|
||||
if (item_is_tag('X'))
|
||||
choice = item_n();
|
||||
if (item_is_selected()) {
|
||||
choice = item_n();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
do_resize:
|
||||
if (getmaxy(stdscr) < (height + 6))
|
||||
return -ERRDISPLAYTOOSMALL;
|
||||
if (getmaxx(stdscr) < (width + 6))
|
||||
return -ERRDISPLAYTOOSMALL;
|
||||
|
||||
max_choice = MIN(list_height, item_count());
|
||||
|
||||
/* center dialog box on screen */
|
||||
x = (COLS - width) / 2;
|
||||
y = (LINES - height) / 2;
|
||||
|
||||
draw_shadow(stdscr, y, x, height, width);
|
||||
|
||||
dialog = newwin(height, width, y, x);
|
||||
keypad(dialog, TRUE);
|
||||
|
||||
draw_box(dialog, 0, 0, height, width,
|
||||
dlg.dialog.atr, dlg.border.atr);
|
||||
wattrset(dialog, dlg.border.atr);
|
||||
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
||||
for (i = 0; i < width - 2; i++)
|
||||
waddch(dialog, ACS_HLINE);
|
||||
wattrset(dialog, dlg.dialog.atr);
|
||||
waddch(dialog, ACS_RTEE);
|
||||
|
||||
print_title(dialog, title, width);
|
||||
|
||||
wattrset(dialog, dlg.dialog.atr);
|
||||
print_autowrap(dialog, prompt, width - 2, 1, 3);
|
||||
|
||||
list_width = width - 6;
|
||||
box_y = height - list_height - 5;
|
||||
box_x = (width - list_width) / 2 - 1;
|
||||
|
||||
/* create new window for the list */
|
||||
list = subwin(dialog, list_height, list_width, y + box_y + 1,
|
||||
x + box_x + 1);
|
||||
|
||||
keypad(list, TRUE);
|
||||
|
||||
/* draw a box around the list items */
|
||||
draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
|
||||
dlg.menubox_border.atr, dlg.menubox.atr);
|
||||
|
||||
/* Find length of longest item in order to center checklist */
|
||||
check_x = 0;
|
||||
item_foreach()
|
||||
check_x = MAX(check_x, strlen(item_str()) + 4);
|
||||
|
||||
check_x = (list_width - check_x) / 2;
|
||||
item_x = check_x + 4;
|
||||
|
||||
if (choice >= list_height) {
|
||||
scroll = choice - list_height + 1;
|
||||
choice -= scroll;
|
||||
}
|
||||
|
||||
/* Print the list */
|
||||
for (i = 0; i < max_choice; i++) {
|
||||
item_set(scroll + i);
|
||||
print_item(list, i, i == choice);
|
||||
}
|
||||
|
||||
print_arrows(dialog, choice, item_count(), scroll,
|
||||
box_y, box_x + check_x + 5, list_height);
|
||||
|
||||
print_buttons(dialog, height, width, 0);
|
||||
|
||||
wnoutrefresh(dialog);
|
||||
wnoutrefresh(list);
|
||||
doupdate();
|
||||
|
||||
while (key != KEY_ESC) {
|
||||
key = wgetch(dialog);
|
||||
|
||||
for (i = 0; i < max_choice; i++) {
|
||||
item_set(i + scroll);
|
||||
if (toupper(key) == toupper(item_str()[0]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
|
||||
key == '+' || key == '-') {
|
||||
if (key == KEY_UP || key == '-') {
|
||||
if (!choice) {
|
||||
if (!scroll)
|
||||
continue;
|
||||
/* Scroll list down */
|
||||
if (list_height > 1) {
|
||||
/* De-highlight current first item */
|
||||
item_set(scroll);
|
||||
print_item(list, 0, FALSE);
|
||||
scrollok(list, TRUE);
|
||||
wscrl(list, -1);
|
||||
scrollok(list, FALSE);
|
||||
}
|
||||
scroll--;
|
||||
item_set(scroll);
|
||||
print_item(list, 0, TRUE);
|
||||
print_arrows(dialog, choice, item_count(),
|
||||
scroll, box_y, box_x + check_x + 5, list_height);
|
||||
|
||||
wnoutrefresh(dialog);
|
||||
wrefresh(list);
|
||||
|
||||
continue; /* wait for another key press */
|
||||
} else
|
||||
i = choice - 1;
|
||||
} else if (key == KEY_DOWN || key == '+') {
|
||||
if (choice == max_choice - 1) {
|
||||
if (scroll + choice >= item_count() - 1)
|
||||
continue;
|
||||
/* Scroll list up */
|
||||
if (list_height > 1) {
|
||||
/* De-highlight current last item before scrolling up */
|
||||
item_set(scroll + max_choice - 1);
|
||||
print_item(list,
|
||||
max_choice - 1,
|
||||
FALSE);
|
||||
scrollok(list, TRUE);
|
||||
wscrl(list, 1);
|
||||
scrollok(list, FALSE);
|
||||
}
|
||||
scroll++;
|
||||
item_set(scroll + max_choice - 1);
|
||||
print_item(list, max_choice - 1, TRUE);
|
||||
|
||||
print_arrows(dialog, choice, item_count(),
|
||||
scroll, box_y, box_x + check_x + 5, list_height);
|
||||
|
||||
wnoutrefresh(dialog);
|
||||
wrefresh(list);
|
||||
|
||||
continue; /* wait for another key press */
|
||||
} else
|
||||
i = choice + 1;
|
||||
}
|
||||
if (i != choice) {
|
||||
/* De-highlight current item */
|
||||
item_set(scroll + choice);
|
||||
print_item(list, choice, FALSE);
|
||||
/* Highlight new item */
|
||||
choice = i;
|
||||
item_set(scroll + choice);
|
||||
print_item(list, choice, TRUE);
|
||||
wnoutrefresh(dialog);
|
||||
wrefresh(list);
|
||||
}
|
||||
continue; /* wait for another key press */
|
||||
}
|
||||
switch (key) {
|
||||
case 'H':
|
||||
case 'h':
|
||||
case '?':
|
||||
button = 1;
|
||||
/* fall-through */
|
||||
case 'S':
|
||||
case 's':
|
||||
case ' ':
|
||||
case '\n':
|
||||
item_foreach()
|
||||
item_set_selected(0);
|
||||
item_set(scroll + choice);
|
||||
item_set_selected(1);
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
return button;
|
||||
case TAB:
|
||||
case KEY_LEFT:
|
||||
case KEY_RIGHT:
|
||||
button = ((key == KEY_LEFT ? --button : ++button) < 0)
|
||||
? 1 : (button > 1 ? 0 : button);
|
||||
|
||||
print_buttons(dialog, height, width, button);
|
||||
wrefresh(dialog);
|
||||
break;
|
||||
case 'X':
|
||||
case 'x':
|
||||
key = KEY_ESC;
|
||||
break;
|
||||
case KEY_ESC:
|
||||
key = on_key_esc(dialog);
|
||||
break;
|
||||
case KEY_RESIZE:
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
on_key_resize();
|
||||
goto do_resize;
|
||||
}
|
||||
|
||||
/* Now, update everything... */
|
||||
doupdate();
|
||||
}
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
return key; /* ESC pressed */
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* dialog.h -- common declarations for all dialog modules
|
||||
*
|
||||
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef KBUILD_NO_NLS
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
#endif
|
||||
|
||||
#ifdef __sun__
|
||||
#define CURS_MACROS
|
||||
#endif
|
||||
#include CURSES_LOC
|
||||
|
||||
/*
|
||||
* Colors in ncurses 1.9.9e do not work properly since foreground and
|
||||
* background colors are OR'd rather than separately masked. This version
|
||||
* of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
|
||||
* with standard curses. The simplest fix (to make this work with standard
|
||||
* curses) uses the wbkgdset() function, not used in the original hack.
|
||||
* Turn it off if we're building with 1.9.9e, since it just confuses things.
|
||||
*/
|
||||
#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
|
||||
#define OLD_NCURSES 1
|
||||
#undef wbkgdset
|
||||
#define wbkgdset(w,p) /*nothing */
|
||||
#else
|
||||
#define OLD_NCURSES 0
|
||||
#endif
|
||||
|
||||
#define TR(params) _tracef params
|
||||
|
||||
#define KEY_ESC 27
|
||||
#define TAB 9
|
||||
#define MAX_LEN 2048
|
||||
#define BUF_SIZE (10*1024)
|
||||
#define MIN(x,y) (x < y ? x : y)
|
||||
#define MAX(x,y) (x > y ? x : y)
|
||||
|
||||
#ifndef ACS_ULCORNER
|
||||
#define ACS_ULCORNER '+'
|
||||
#endif
|
||||
#ifndef ACS_LLCORNER
|
||||
#define ACS_LLCORNER '+'
|
||||
#endif
|
||||
#ifndef ACS_URCORNER
|
||||
#define ACS_URCORNER '+'
|
||||
#endif
|
||||
#ifndef ACS_LRCORNER
|
||||
#define ACS_LRCORNER '+'
|
||||
#endif
|
||||
#ifndef ACS_HLINE
|
||||
#define ACS_HLINE '-'
|
||||
#endif
|
||||
#ifndef ACS_VLINE
|
||||
#define ACS_VLINE '|'
|
||||
#endif
|
||||
#ifndef ACS_LTEE
|
||||
#define ACS_LTEE '+'
|
||||
#endif
|
||||
#ifndef ACS_RTEE
|
||||
#define ACS_RTEE '+'
|
||||
#endif
|
||||
#ifndef ACS_UARROW
|
||||
#define ACS_UARROW '^'
|
||||
#endif
|
||||
#ifndef ACS_DARROW
|
||||
#define ACS_DARROW 'v'
|
||||
#endif
|
||||
|
||||
/* error return codes */
|
||||
#define ERRDISPLAYTOOSMALL (KEY_MAX + 1)
|
||||
|
||||
/*
|
||||
* Color definitions
|
||||
*/
|
||||
struct dialog_color {
|
||||
chtype atr; /* Color attribute */
|
||||
int fg; /* foreground */
|
||||
int bg; /* background */
|
||||
int hl; /* highlight this item */
|
||||
};
|
||||
|
||||
struct dialog_info {
|
||||
const char *backtitle;
|
||||
struct dialog_color screen;
|
||||
struct dialog_color shadow;
|
||||
struct dialog_color dialog;
|
||||
struct dialog_color title;
|
||||
struct dialog_color border;
|
||||
struct dialog_color button_active;
|
||||
struct dialog_color button_inactive;
|
||||
struct dialog_color button_key_active;
|
||||
struct dialog_color button_key_inactive;
|
||||
struct dialog_color button_label_active;
|
||||
struct dialog_color button_label_inactive;
|
||||
struct dialog_color inputbox;
|
||||
struct dialog_color inputbox_border;
|
||||
struct dialog_color searchbox;
|
||||
struct dialog_color searchbox_title;
|
||||
struct dialog_color searchbox_border;
|
||||
struct dialog_color position_indicator;
|
||||
struct dialog_color menubox;
|
||||
struct dialog_color menubox_border;
|
||||
struct dialog_color item;
|
||||
struct dialog_color item_selected;
|
||||
struct dialog_color tag;
|
||||
struct dialog_color tag_selected;
|
||||
struct dialog_color tag_key;
|
||||
struct dialog_color tag_key_selected;
|
||||
struct dialog_color check;
|
||||
struct dialog_color check_selected;
|
||||
struct dialog_color uarrow;
|
||||
struct dialog_color darrow;
|
||||
};
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
*/
|
||||
extern struct dialog_info dlg;
|
||||
extern char dialog_input_result[];
|
||||
|
||||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
|
||||
/* item list as used by checklist and menubox */
|
||||
void item_reset(void);
|
||||
void item_make(const char *fmt, ...);
|
||||
void item_add_str(const char *fmt, ...);
|
||||
void item_set_tag(char tag);
|
||||
void item_set_data(void *p);
|
||||
void item_set_selected(int val);
|
||||
int item_activate_selected(void);
|
||||
void *item_data(void);
|
||||
char item_tag(void);
|
||||
|
||||
/* item list manipulation for lxdialog use */
|
||||
#define MAXITEMSTR 200
|
||||
struct dialog_item {
|
||||
char str[MAXITEMSTR]; /* promtp displayed */
|
||||
char tag;
|
||||
void *data; /* pointer to menu item - used by menubox+checklist */
|
||||
int selected; /* Set to 1 by dialog_*() function if selected. */
|
||||
};
|
||||
|
||||
/* list of lialog_items */
|
||||
struct dialog_list {
|
||||
struct dialog_item node;
|
||||
struct dialog_list *next;
|
||||
};
|
||||
|
||||
extern struct dialog_list *item_cur;
|
||||
extern struct dialog_list item_nil;
|
||||
extern struct dialog_list *item_head;
|
||||
|
||||
int item_count(void);
|
||||
void item_set(int n);
|
||||
int item_n(void);
|
||||
const char *item_str(void);
|
||||
int item_is_selected(void);
|
||||
int item_is_tag(char tag);
|
||||
#define item_foreach() \
|
||||
for (item_cur = item_head ? item_head: item_cur; \
|
||||
item_cur && (item_cur != &item_nil); item_cur = item_cur->next)
|
||||
|
||||
/* generic key handlers */
|
||||
int on_key_esc(WINDOW *win);
|
||||
int on_key_resize(void);
|
||||
|
||||
int init_dialog(const char *backtitle);
|
||||
void set_dialog_backtitle(const char *backtitle);
|
||||
void end_dialog(int x, int y);
|
||||
void attr_clear(WINDOW * win, int height, int width, chtype attr);
|
||||
void dialog_clear(void);
|
||||
void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x);
|
||||
void print_button(WINDOW * win, const char *label, int y, int x, int selected);
|
||||
void print_title(WINDOW *dialog, const char *title, int width);
|
||||
void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box,
|
||||
chtype border);
|
||||
void draw_shadow(WINDOW * win, int y, int x, int height, int width);
|
||||
|
||||
int first_alpha(const char *string, const char *exempt);
|
||||
int dialog_yesno(const char *title, const char *prompt, int height, int width);
|
||||
int dialog_msgbox(const char *title, const char *prompt, int height,
|
||||
int width, int pause);
|
||||
int dialog_textbox(const char *title, const char *file, int height, int width);
|
||||
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);
|
||||
|
||||
/*
|
||||
* This is the base for fictitious keys, which activate
|
||||
* the buttons.
|
||||
*
|
||||
* Mouse-generated keys are the following:
|
||||
* -- the first 32 are used as numbers, in addition to '0'-'9'
|
||||
* -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
|
||||
* -- uppercase chars are used to invoke the button (M_EVENT + 'O')
|
||||
*/
|
||||
#define M_EVENT (KEY_MAX+1)
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* inputbox.c -- implements the input box
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
char dialog_input_result[MAX_LEN + 1];
|
||||
|
||||
/*
|
||||
* Print the termination buttons
|
||||
*/
|
||||
static void print_buttons(WINDOW * dialog, int height, int width, int selected)
|
||||
{
|
||||
int x = width / 2 - 11;
|
||||
int y = height - 2;
|
||||
|
||||
print_button(dialog, gettext(" Ok "), y, x, selected == 0);
|
||||
print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
|
||||
|
||||
wmove(dialog, y, x + 1 + 14 * selected);
|
||||
wrefresh(dialog);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a dialog box for inputing a string
|
||||
*/
|
||||
int dialog_inputbox(const char *title, const char *prompt, int height, int width,
|
||||
const char *init)
|
||||
{
|
||||
int i, x, y, box_y, box_x, box_width;
|
||||
int input_x = 0, scroll = 0, key = 0, button = -1;
|
||||
char *instr = dialog_input_result;
|
||||
WINDOW *dialog;
|
||||
|
||||
if (!init)
|
||||
instr[0] = '\0';
|
||||
else
|
||||
strcpy(instr, init);
|
||||
|
||||
do_resize:
|
||||
if (getmaxy(stdscr) <= (height - 2))
|
||||
return -ERRDISPLAYTOOSMALL;
|
||||
if (getmaxx(stdscr) <= (width - 2))
|
||||
return -ERRDISPLAYTOOSMALL;
|
||||
|
||||
/* center dialog box on screen */
|
||||
x = (COLS - width) / 2;
|
||||
y = (LINES - height) / 2;
|
||||
|
||||
draw_shadow(stdscr, y, x, height, width);
|
||||
|
||||
dialog = newwin(height, width, y, x);
|
||||
keypad(dialog, TRUE);
|
||||
|
||||
draw_box(dialog, 0, 0, height, width,
|
||||
dlg.dialog.atr, dlg.border.atr);
|
||||
wattrset(dialog, dlg.border.atr);
|
||||
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
||||
for (i = 0; i < width - 2; i++)
|
||||
waddch(dialog, ACS_HLINE);
|
||||
wattrset(dialog, dlg.dialog.atr);
|
||||
waddch(dialog, ACS_RTEE);
|
||||
|
||||
print_title(dialog, title, width);
|
||||
|
||||
wattrset(dialog, dlg.dialog.atr);
|
||||
print_autowrap(dialog, prompt, width - 2, 1, 3);
|
||||
|
||||
/* Draw the input field box */
|
||||
box_width = width - 6;
|
||||
getyx(dialog, y, x);
|
||||
box_y = y + 2;
|
||||
box_x = (width - box_width) / 2;
|
||||
draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
|
||||
dlg.border.atr, dlg.dialog.atr);
|
||||
|
||||
print_buttons(dialog, height, width, 0);
|
||||
|
||||
/* Set up the initial value */
|
||||
wmove(dialog, box_y, box_x);
|
||||
wattrset(dialog, dlg.inputbox.atr);
|
||||
|
||||
input_x = strlen(instr);
|
||||
|
||||
if (input_x >= box_width) {
|
||||
scroll = input_x - box_width + 1;
|
||||
input_x = box_width - 1;
|
||||
for (i = 0; i < box_width - 1; i++)
|
||||
waddch(dialog, instr[scroll + i]);
|
||||
} else {
|
||||
waddstr(dialog, instr);
|
||||
}
|
||||
|
||||
wmove(dialog, box_y, box_x + input_x);
|
||||
|
||||
wrefresh(dialog);
|
||||
|
||||
while (key != KEY_ESC) {
|
||||
key = wgetch(dialog);
|
||||
|
||||
if (button == -1) { /* Input box selected */
|
||||
switch (key) {
|
||||
case TAB:
|
||||
case KEY_UP:
|
||||
case KEY_DOWN:
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
continue;
|
||||
case KEY_RIGHT:
|
||||
continue;
|
||||
case KEY_BACKSPACE:
|
||||
case 127:
|
||||
if (input_x || scroll) {
|
||||
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;
|
||||
} else
|
||||
input_x--;
|
||||
instr[scroll + input_x] = '\0';
|
||||
mvwaddch(dialog, box_y, input_x + box_x, ' ');
|
||||
wmove(dialog, box_y, input_x + box_x);
|
||||
wrefresh(dialog);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
if (key < 0x100 && isprint(key)) {
|
||||
if (scroll + input_x < MAX_LEN) {
|
||||
wattrset(dialog, dlg.inputbox.atr);
|
||||
instr[scroll + input_x] = key;
|
||||
instr[scroll + input_x + 1] = '\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]);
|
||||
} else {
|
||||
wmove(dialog, box_y, input_x++ + box_x);
|
||||
waddch(dialog, key);
|
||||
}
|
||||
wrefresh(dialog);
|
||||
} else
|
||||
flash(); /* Alarm user about overflow */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (key) {
|
||||
case 'O':
|
||||
case 'o':
|
||||
delwin(dialog);
|
||||
return 0;
|
||||
case 'H':
|
||||
case 'h':
|
||||
delwin(dialog);
|
||||
return 1;
|
||||
case KEY_UP:
|
||||
case KEY_LEFT:
|
||||
switch (button) {
|
||||
case -1:
|
||||
button = 1; /* Indicates "Cancel" button is selected */
|
||||
print_buttons(dialog, height, width, 1);
|
||||
break;
|
||||
case 0:
|
||||
button = -1; /* Indicates input box is selected */
|
||||
print_buttons(dialog, height, width, 0);
|
||||
wmove(dialog, box_y, box_x + input_x);
|
||||
wrefresh(dialog);
|
||||
break;
|
||||
case 1:
|
||||
button = 0; /* Indicates "OK" button is selected */
|
||||
print_buttons(dialog, height, width, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TAB:
|
||||
case KEY_DOWN:
|
||||
case KEY_RIGHT:
|
||||
switch (button) {
|
||||
case -1:
|
||||
button = 0; /* Indicates "OK" button is selected */
|
||||
print_buttons(dialog, height, width, 0);
|
||||
break;
|
||||
case 0:
|
||||
button = 1; /* Indicates "Cancel" button is selected */
|
||||
print_buttons(dialog, height, width, 1);
|
||||
break;
|
||||
case 1:
|
||||
button = -1; /* Indicates input box is selected */
|
||||
print_buttons(dialog, height, width, 0);
|
||||
wmove(dialog, box_y, box_x + input_x);
|
||||
wrefresh(dialog);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ' ':
|
||||
case '\n':
|
||||
delwin(dialog);
|
||||
return (button == -1 ? 0 : button);
|
||||
case 'X':
|
||||
case 'x':
|
||||
key = KEY_ESC;
|
||||
break;
|
||||
case KEY_ESC:
|
||||
key = on_key_esc(dialog);
|
||||
break;
|
||||
case KEY_RESIZE:
|
||||
delwin(dialog);
|
||||
on_key_resize();
|
||||
goto do_resize;
|
||||
}
|
||||
}
|
||||
|
||||
delwin(dialog);
|
||||
return KEY_ESC; /* ESC pressed */
|
||||
}
|
|
@ -0,0 +1,434 @@
|
|||
/*
|
||||
* menubox.c -- implements the menu box
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Changes by Clifford Wolf (god@clifford.at)
|
||||
*
|
||||
* [ 1998-06-13 ]
|
||||
*
|
||||
* *) A bugfix for the Page-Down problem
|
||||
*
|
||||
* *) Formerly when I used Page Down and Page Up, the cursor would be set
|
||||
* to the first position in the menu box. Now lxdialog is a bit
|
||||
* smarter and works more like other menu systems (just have a look at
|
||||
* it).
|
||||
*
|
||||
* *) Formerly if I selected something my scrolling would be broken because
|
||||
* lxdialog is re-invoked by the Menuconfig shell script, can't
|
||||
* remember the last scrolling position, and just sets it so that the
|
||||
* cursor is at the bottom of the box. Now it writes the temporary file
|
||||
* lxdialog.scrltmp which contains this information. The file is
|
||||
* deleted by lxdialog if the user leaves a submenu or enters a new
|
||||
* one, but it would be nice if Menuconfig could make another "rm -f"
|
||||
* just to be sure. Just try it out - you will recognise a difference!
|
||||
*
|
||||
* [ 1998-06-14 ]
|
||||
*
|
||||
* *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
|
||||
* and menus change their size on the fly.
|
||||
*
|
||||
* *) If for some reason the last scrolling position is not saved by
|
||||
* lxdialog, it sets the scrolling so that the selected item is in the
|
||||
* middle of the menu box, not at the bottom.
|
||||
*
|
||||
* 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
|
||||
* Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
|
||||
* This fixes a bug in Menuconfig where using ' ' to descend into menus
|
||||
* would leave mis-synchronized lxdialog.scrltmp files lying around,
|
||||
* fscanf would read in 'scroll', and eventually that value would get used.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
static int menu_width, item_x;
|
||||
|
||||
/*
|
||||
* Print menu item
|
||||
*/
|
||||
static void do_print_item(WINDOW * win, const char *item, int line_y,
|
||||
int selected, int hotkey)
|
||||
{
|
||||
int j;
|
||||
char *menu_item = malloc(menu_width + 1);
|
||||
|
||||
strncpy(menu_item, item, menu_width - item_x);
|
||||
menu_item[menu_width - item_x] = '\0';
|
||||
j = first_alpha(menu_item, "YyNnMmHh");
|
||||
|
||||
/* Clear 'residue' of last item */
|
||||
wattrset(win, dlg.menubox.atr);
|
||||
wmove(win, line_y, 0);
|
||||
#if OLD_NCURSES
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < menu_width; i++)
|
||||
waddch(win, ' ');
|
||||
}
|
||||
#else
|
||||
wclrtoeol(win);
|
||||
#endif
|
||||
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
|
||||
mvwaddstr(win, line_y, item_x, menu_item);
|
||||
if (hotkey) {
|
||||
wattrset(win, selected ? dlg.tag_key_selected.atr
|
||||
: dlg.tag_key.atr);
|
||||
mvwaddch(win, line_y, item_x + j, menu_item[j]);
|
||||
}
|
||||
if (selected) {
|
||||
wmove(win, line_y, item_x + 1);
|
||||
}
|
||||
free(menu_item);
|
||||
wrefresh(win);
|
||||
}
|
||||
|
||||
#define print_item(index, choice, selected) \
|
||||
do { \
|
||||
item_set(index); \
|
||||
do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Print the scroll indicators.
|
||||
*/
|
||||
static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
|
||||
int height)
|
||||
{
|
||||
int cur_y, cur_x;
|
||||
|
||||
getyx(win, cur_y, cur_x);
|
||||
|
||||
wmove(win, y, x);
|
||||
|
||||
if (scroll > 0) {
|
||||
wattrset(win, dlg.uarrow.atr);
|
||||
waddch(win, ACS_UARROW);
|
||||
waddstr(win, "(-)");
|
||||
} else {
|
||||
wattrset(win, dlg.menubox.atr);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
}
|
||||
|
||||
y = y + height + 1;
|
||||
wmove(win, y, x);
|
||||
wrefresh(win);
|
||||
|
||||
if ((height < item_no) && (scroll + height < item_no)) {
|
||||
wattrset(win, dlg.darrow.atr);
|
||||
waddch(win, ACS_DARROW);
|
||||
waddstr(win, "(+)");
|
||||
} else {
|
||||
wattrset(win, dlg.menubox_border.atr);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
waddch(win, ACS_HLINE);
|
||||
}
|
||||
|
||||
wmove(win, cur_y, cur_x);
|
||||
wrefresh(win);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display the termination buttons.
|
||||
*/
|
||||
static void print_buttons(WINDOW * win, int height, int width, int selected)
|
||||
{
|
||||
int x = width / 2 - 16;
|
||||
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);
|
||||
|
||||
wmove(win, y, x + 1 + 12 * selected);
|
||||
wrefresh(win);
|
||||
}
|
||||
|
||||
/* scroll up n lines (n may be negative) */
|
||||
static void do_scroll(WINDOW *win, int *scroll, int n)
|
||||
{
|
||||
/* Scroll menu up */
|
||||
scrollok(win, TRUE);
|
||||
wscrl(win, n);
|
||||
scrollok(win, FALSE);
|
||||
*scroll = *scroll + n;
|
||||
wrefresh(win);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a menu for choosing among a number of options
|
||||
*/
|
||||
int dialog_menu(const char *title, const char *prompt,
|
||||
const void *selected, int *s_scroll)
|
||||
{
|
||||
int i, j, x, y, box_x, box_y;
|
||||
int height, width, menu_height;
|
||||
int key = 0, button = 0, scroll = 0, choice = 0;
|
||||
int first_item = 0, max_choice;
|
||||
WINDOW *dialog, *menu;
|
||||
|
||||
do_resize:
|
||||
height = getmaxy(stdscr);
|
||||
width = getmaxx(stdscr);
|
||||
if (height < 15 || width < 65)
|
||||
return -ERRDISPLAYTOOSMALL;
|
||||
|
||||
height -= 4;
|
||||
width -= 5;
|
||||
menu_height = height - 10;
|
||||
|
||||
max_choice = MIN(menu_height, item_count());
|
||||
|
||||
/* center dialog box on screen */
|
||||
x = (COLS - width) / 2;
|
||||
y = (LINES - height) / 2;
|
||||
|
||||
draw_shadow(stdscr, y, x, height, width);
|
||||
|
||||
dialog = newwin(height, width, y, x);
|
||||
keypad(dialog, TRUE);
|
||||
|
||||
draw_box(dialog, 0, 0, height, width,
|
||||
dlg.dialog.atr, dlg.border.atr);
|
||||
wattrset(dialog, dlg.border.atr);
|
||||
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
||||
for (i = 0; i < width - 2; i++)
|
||||
waddch(dialog, ACS_HLINE);
|
||||
wattrset(dialog, dlg.dialog.atr);
|
||||
wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
|
||||
waddch(dialog, ACS_RTEE);
|
||||
|
||||
print_title(dialog, title, width);
|
||||
|
||||
wattrset(dialog, dlg.dialog.atr);
|
||||
print_autowrap(dialog, prompt, width - 2, 1, 3);
|
||||
|
||||
menu_width = width - 6;
|
||||
box_y = height - menu_height - 5;
|
||||
box_x = (width - menu_width) / 2 - 1;
|
||||
|
||||
/* create new window for the menu */
|
||||
menu = subwin(dialog, menu_height, menu_width,
|
||||
y + box_y + 1, x + box_x + 1);
|
||||
keypad(menu, TRUE);
|
||||
|
||||
/* draw a box around the menu items */
|
||||
draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
|
||||
dlg.menubox_border.atr, dlg.menubox.atr);
|
||||
|
||||
if (menu_width >= 80)
|
||||
item_x = (menu_width - 70) / 2;
|
||||
else
|
||||
item_x = 4;
|
||||
|
||||
/* Set choice to default item */
|
||||
item_foreach()
|
||||
if (selected && (selected == item_data()))
|
||||
choice = item_n();
|
||||
/* get the saved scroll info */
|
||||
scroll = *s_scroll;
|
||||
if ((scroll <= choice) && (scroll + max_choice > choice) &&
|
||||
(scroll >= 0) && (scroll + max_choice <= item_count())) {
|
||||
first_item = scroll;
|
||||
choice = choice - scroll;
|
||||
} else {
|
||||
scroll = 0;
|
||||
}
|
||||
if ((choice >= max_choice)) {
|
||||
if (choice >= item_count() - max_choice / 2)
|
||||
scroll = first_item = item_count() - max_choice;
|
||||
else
|
||||
scroll = first_item = choice - max_choice / 2;
|
||||
choice = choice - scroll;
|
||||
}
|
||||
|
||||
/* Print the menu */
|
||||
for (i = 0; i < max_choice; i++) {
|
||||
print_item(first_item + i, i, i == choice);
|
||||
}
|
||||
|
||||
wnoutrefresh(menu);
|
||||
|
||||
print_arrows(dialog, item_count(), scroll,
|
||||
box_y, box_x + item_x + 1, menu_height);
|
||||
|
||||
print_buttons(dialog, height, width, 0);
|
||||
wmove(menu, choice, item_x + 1);
|
||||
wrefresh(menu);
|
||||
|
||||
while (key != KEY_ESC) {
|
||||
key = wgetch(menu);
|
||||
|
||||
if (key < 256 && isalpha(key))
|
||||
key = tolower(key);
|
||||
|
||||
if (strchr("ynmh", key))
|
||||
i = max_choice;
|
||||
else {
|
||||
for (i = choice + 1; i < max_choice; i++) {
|
||||
item_set(scroll + i);
|
||||
j = first_alpha(item_str(), "YyNnMmHh");
|
||||
if (key == tolower(item_str()[j]))
|
||||
break;
|
||||
}
|
||||
if (i == max_choice)
|
||||
for (i = 0; i < max_choice; i++) {
|
||||
item_set(scroll + i);
|
||||
j = first_alpha(item_str(), "YyNnMmHh");
|
||||
if (key == tolower(item_str()[j]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < max_choice ||
|
||||
key == KEY_UP || key == KEY_DOWN ||
|
||||
key == '-' || key == '+' ||
|
||||
key == KEY_PPAGE || key == KEY_NPAGE) {
|
||||
/* Remove highligt of current item */
|
||||
print_item(scroll + choice, choice, FALSE);
|
||||
|
||||
if (key == KEY_UP || key == '-') {
|
||||
if (choice < 2 && scroll) {
|
||||
/* Scroll menu down */
|
||||
do_scroll(menu, &scroll, -1);
|
||||
|
||||
print_item(scroll, 0, FALSE);
|
||||
} else
|
||||
choice = MAX(choice - 1, 0);
|
||||
|
||||
} else if (key == KEY_DOWN || key == '+') {
|
||||
print_item(scroll+choice, choice, FALSE);
|
||||
|
||||
if ((choice > max_choice - 3) &&
|
||||
(scroll + max_choice < item_count())) {
|
||||
/* Scroll menu up */
|
||||
do_scroll(menu, &scroll, 1);
|
||||
|
||||
print_item(scroll+max_choice - 1,
|
||||
max_choice - 1, FALSE);
|
||||
} else
|
||||
choice = MIN(choice + 1, max_choice - 1);
|
||||
|
||||
} else if (key == KEY_PPAGE) {
|
||||
scrollok(menu, TRUE);
|
||||
for (i = 0; (i < max_choice); i++) {
|
||||
if (scroll > 0) {
|
||||
do_scroll(menu, &scroll, -1);
|
||||
print_item(scroll, 0, FALSE);
|
||||
} else {
|
||||
if (choice > 0)
|
||||
choice--;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (key == KEY_NPAGE) {
|
||||
for (i = 0; (i < max_choice); i++) {
|
||||
if (scroll + max_choice < item_count()) {
|
||||
do_scroll(menu, &scroll, 1);
|
||||
print_item(scroll+max_choice-1,
|
||||
max_choice - 1, FALSE);
|
||||
} else {
|
||||
if (choice + 1 < max_choice)
|
||||
choice++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
choice = i;
|
||||
|
||||
print_item(scroll + choice, choice, TRUE);
|
||||
|
||||
print_arrows(dialog, item_count(), scroll,
|
||||
box_y, box_x + item_x + 1, menu_height);
|
||||
|
||||
wnoutrefresh(dialog);
|
||||
wrefresh(menu);
|
||||
|
||||
continue; /* wait for another key press */
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case KEY_LEFT:
|
||||
case TAB:
|
||||
case KEY_RIGHT:
|
||||
button = ((key == KEY_LEFT ? --button : ++button) < 0)
|
||||
? 2 : (button > 2 ? 0 : button);
|
||||
|
||||
print_buttons(dialog, height, width, button);
|
||||
wrefresh(menu);
|
||||
break;
|
||||
case ' ':
|
||||
case 's':
|
||||
case 'y':
|
||||
case 'n':
|
||||
case 'm':
|
||||
case '/':
|
||||
/* save scroll info */
|
||||
*s_scroll = scroll;
|
||||
delwin(menu);
|
||||
delwin(dialog);
|
||||
item_set(scroll + choice);
|
||||
item_set_selected(1);
|
||||
switch (key) {
|
||||
case 's':
|
||||
return 3;
|
||||
case 'y':
|
||||
return 3;
|
||||
case 'n':
|
||||
return 4;
|
||||
case 'm':
|
||||
return 5;
|
||||
case ' ':
|
||||
return 6;
|
||||
case '/':
|
||||
return 7;
|
||||
}
|
||||
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;
|
||||
break;
|
||||
case KEY_ESC:
|
||||
key = on_key_esc(menu);
|
||||
break;
|
||||
case KEY_RESIZE:
|
||||
on_key_resize();
|
||||
delwin(menu);
|
||||
delwin(dialog);
|
||||
goto do_resize;
|
||||
}
|
||||
}
|
||||
delwin(menu);
|
||||
delwin(dialog);
|
||||
return key; /* ESC pressed */
|
||||
}
|
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
* textbox.c -- implements the text box
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
static void back_lines(int n);
|
||||
static void print_page(WINDOW * win, int height, int width);
|
||||
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;
|
||||
|
||||
/*
|
||||
* refresh window content
|
||||
*/
|
||||
static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
|
||||
int cur_y, int cur_x)
|
||||
{
|
||||
print_page(box, boxh, boxw);
|
||||
print_position(dialog);
|
||||
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
|
||||
wrefresh(dialog);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display text from a file in a dialog box.
|
||||
*/
|
||||
int dialog_textbox(const char *title, const char *tbuf,
|
||||
int initial_height, int initial_width)
|
||||
{
|
||||
int i, x, y, cur_x, cur_y, key = 0;
|
||||
int height, width, boxh, boxw;
|
||||
int passed_end;
|
||||
WINDOW *dialog, *box;
|
||||
|
||||
begin_reached = 1;
|
||||
end_reached = 0;
|
||||
page_length = 0;
|
||||
hscroll = 0;
|
||||
buf = tbuf;
|
||||
page = buf; /* page is pointer to start of page to be displayed */
|
||||
|
||||
do_resize:
|
||||
getmaxyx(stdscr, height, width);
|
||||
if (height < 8 || width < 8)
|
||||
return -ERRDISPLAYTOOSMALL;
|
||||
if (initial_height != 0)
|
||||
height = initial_height;
|
||||
else
|
||||
if (height > 4)
|
||||
height -= 4;
|
||||
else
|
||||
height = 0;
|
||||
if (initial_width != 0)
|
||||
width = initial_width;
|
||||
else
|
||||
if (width > 5)
|
||||
width -= 5;
|
||||
else
|
||||
width = 0;
|
||||
|
||||
/* center dialog box on screen */
|
||||
x = (COLS - width) / 2;
|
||||
y = (LINES - height) / 2;
|
||||
|
||||
draw_shadow(stdscr, y, x, height, width);
|
||||
|
||||
dialog = newwin(height, width, y, x);
|
||||
keypad(dialog, TRUE);
|
||||
|
||||
/* Create window for box region, used for scrolling text */
|
||||
boxh = height - 4;
|
||||
boxw = width - 2;
|
||||
box = subwin(dialog, boxh, boxw, y + 1, x + 1);
|
||||
wattrset(box, dlg.dialog.atr);
|
||||
wbkgdset(box, dlg.dialog.atr & A_COLOR);
|
||||
|
||||
keypad(box, TRUE);
|
||||
|
||||
/* register the new window, along with its borders */
|
||||
draw_box(dialog, 0, 0, height, width,
|
||||
dlg.dialog.atr, dlg.border.atr);
|
||||
|
||||
wattrset(dialog, dlg.border.atr);
|
||||
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
||||
for (i = 0; i < width - 2; i++)
|
||||
waddch(dialog, ACS_HLINE);
|
||||
wattrset(dialog, dlg.dialog.atr);
|
||||
wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
|
||||
waddch(dialog, ACS_RTEE);
|
||||
|
||||
print_title(dialog, title, width);
|
||||
|
||||
print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
|
||||
wnoutrefresh(dialog);
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
|
||||
/* Print first page of text */
|
||||
attr_clear(box, boxh, boxw, dlg.dialog.atr);
|
||||
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
|
||||
|
||||
while ((key != KEY_ESC) && (key != '\n')) {
|
||||
key = wgetch(dialog);
|
||||
switch (key) {
|
||||
case 'E': /* Exit */
|
||||
case 'e':
|
||||
case 'X':
|
||||
case 'x':
|
||||
delwin(box);
|
||||
delwin(dialog);
|
||||
return 0;
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case 'G': /* Last page */
|
||||
case KEY_END:
|
||||
|
||||
end_reached = 1;
|
||||
/* point to last char in buf */
|
||||
page = buf + strlen(buf);
|
||||
back_lines(boxh);
|
||||
refresh_text_box(dialog, box, boxh, boxw,
|
||||
cur_y, cur_x);
|
||||
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;
|
||||
}
|
||||
|
||||
print_position(dialog);
|
||||
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
|
||||
wrefresh(dialog);
|
||||
}
|
||||
break;
|
||||
case 'B': /* Previous page */
|
||||
case 'b':
|
||||
case KEY_PPAGE:
|
||||
if (begin_reached)
|
||||
break;
|
||||
back_lines(page_length + boxh);
|
||||
refresh_text_box(dialog, box, boxh, boxw,
|
||||
cur_y, cur_x);
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case KEY_NPAGE: /* Next page */
|
||||
case ' ':
|
||||
if (end_reached)
|
||||
break;
|
||||
|
||||
begin_reached = 0;
|
||||
refresh_text_box(dialog, box, boxh, boxw,
|
||||
cur_y, cur_x);
|
||||
break;
|
||||
case '0': /* Beginning of line */
|
||||
case 'H': /* Scroll left */
|
||||
case 'h':
|
||||
case KEY_LEFT:
|
||||
if (hscroll <= 0)
|
||||
break;
|
||||
|
||||
if (key == '0')
|
||||
hscroll = 0;
|
||||
else
|
||||
hscroll--;
|
||||
/* Reprint current page to scroll horizontally */
|
||||
back_lines(page_length);
|
||||
refresh_text_box(dialog, box, boxh, boxw,
|
||||
cur_y, cur_x);
|
||||
break;
|
||||
case 'L': /* Scroll right */
|
||||
case 'l':
|
||||
case KEY_RIGHT:
|
||||
if (hscroll >= MAX_LEN)
|
||||
break;
|
||||
hscroll++;
|
||||
/* Reprint current page to scroll horizontally */
|
||||
back_lines(page_length);
|
||||
refresh_text_box(dialog, box, boxh, boxw,
|
||||
cur_y, cur_x);
|
||||
break;
|
||||
case KEY_ESC:
|
||||
key = on_key_esc(dialog);
|
||||
break;
|
||||
case KEY_RESIZE:
|
||||
back_lines(height);
|
||||
delwin(box);
|
||||
delwin(dialog);
|
||||
on_key_resize();
|
||||
goto do_resize;
|
||||
}
|
||||
}
|
||||
delwin(box);
|
||||
delwin(dialog);
|
||||
return key; /* ESC pressed */
|
||||
}
|
||||
|
||||
/*
|
||||
* Go back 'n' lines in text. Called by dialog_textbox().
|
||||
* 'page' will be updated to point to the desired line in 'buf'.
|
||||
*/
|
||||
static void back_lines(int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
begin_reached = 0;
|
||||
/* Go back 'n' lines */
|
||||
for (i = 0; i < n; i++) {
|
||||
if (*page == '\0') {
|
||||
if (end_reached) {
|
||||
end_reached = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (page == buf) {
|
||||
begin_reached = 1;
|
||||
return;
|
||||
}
|
||||
page--;
|
||||
do {
|
||||
if (page == buf) {
|
||||
begin_reached = 1;
|
||||
return;
|
||||
}
|
||||
page--;
|
||||
} while (*page != '\n');
|
||||
page++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a new page of text. Called by dialog_textbox().
|
||||
*/
|
||||
static void print_page(WINDOW * win, int height, int width)
|
||||
{
|
||||
int i, passed_end = 0;
|
||||
|
||||
page_length = 0;
|
||||
for (i = 0; i < height; i++) {
|
||||
print_line(win, i, width);
|
||||
if (!passed_end)
|
||||
page_length++;
|
||||
if (end_reached && !passed_end)
|
||||
passed_end = 1;
|
||||
}
|
||||
wnoutrefresh(win);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a new line of text. Called by dialog_textbox() and print_page().
|
||||
*/
|
||||
static void print_line(WINDOW * win, int row, int width)
|
||||
{
|
||||
int y, x;
|
||||
char *line;
|
||||
|
||||
line = get_line();
|
||||
line += MIN(strlen(line), hscroll); /* Scroll horizontally */
|
||||
wmove(win, row, 0); /* move cursor to correct line */
|
||||
waddch(win, ' ');
|
||||
waddnstr(win, line, MIN(strlen(line), width - 2));
|
||||
|
||||
getyx(win, y, x);
|
||||
/* Clear 'residue' of previous line */
|
||||
#if OLD_NCURSES
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width - x; i++)
|
||||
waddch(win, ' ');
|
||||
}
|
||||
#else
|
||||
wclrtoeol(win);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Return current line of text. Called by dialog_textbox() and print_line().
|
||||
* 'page' should point to start of current line before calling, and will be
|
||||
* updated to point to start of next line.
|
||||
*/
|
||||
static char *get_line(void)
|
||||
{
|
||||
int i = 0;
|
||||
static char line[MAX_LEN + 1];
|
||||
|
||||
end_reached = 0;
|
||||
while (*page != '\n') {
|
||||
if (*page == '\0') {
|
||||
if (!end_reached) {
|
||||
end_reached = 1;
|
||||
break;
|
||||
}
|
||||
} else if (i < MAX_LEN)
|
||||
line[i++] = *(page++);
|
||||
else {
|
||||
/* Truncate lines longer than MAX_LEN characters */
|
||||
if (i == MAX_LEN)
|
||||
line[i++] = '\0';
|
||||
page++;
|
||||
}
|
||||
}
|
||||
if (i <= MAX_LEN)
|
||||
line[i] = '\0';
|
||||
if (!end_reached)
|
||||
page++; /* move pass '\n' */
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print current position
|
||||
*/
|
||||
static void print_position(WINDOW * win)
|
||||
{
|
||||
int percent;
|
||||
|
||||
wattrset(win, dlg.position_indicator.atr);
|
||||
wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
|
||||
percent = (page - buf) * 100 / strlen(buf);
|
||||
wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
|
||||
wprintw(win, "(%3d%%)", percent);
|
||||
}
|
|
@ -0,0 +1,655 @@
|
|||
/*
|
||||
* util.c
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
struct dialog_info dlg;
|
||||
|
||||
static void set_mono_theme(void)
|
||||
{
|
||||
dlg.screen.atr = A_NORMAL;
|
||||
dlg.shadow.atr = A_NORMAL;
|
||||
dlg.dialog.atr = A_NORMAL;
|
||||
dlg.title.atr = A_BOLD;
|
||||
dlg.border.atr = A_NORMAL;
|
||||
dlg.button_active.atr = A_REVERSE;
|
||||
dlg.button_inactive.atr = A_DIM;
|
||||
dlg.button_key_active.atr = A_REVERSE;
|
||||
dlg.button_key_inactive.atr = A_BOLD;
|
||||
dlg.button_label_active.atr = A_REVERSE;
|
||||
dlg.button_label_inactive.atr = A_NORMAL;
|
||||
dlg.inputbox.atr = A_NORMAL;
|
||||
dlg.inputbox_border.atr = A_NORMAL;
|
||||
dlg.searchbox.atr = A_NORMAL;
|
||||
dlg.searchbox_title.atr = A_BOLD;
|
||||
dlg.searchbox_border.atr = A_NORMAL;
|
||||
dlg.position_indicator.atr = A_BOLD;
|
||||
dlg.menubox.atr = A_NORMAL;
|
||||
dlg.menubox_border.atr = A_NORMAL;
|
||||
dlg.item.atr = A_NORMAL;
|
||||
dlg.item_selected.atr = A_REVERSE;
|
||||
dlg.tag.atr = A_BOLD;
|
||||
dlg.tag_selected.atr = A_REVERSE;
|
||||
dlg.tag_key.atr = A_BOLD;
|
||||
dlg.tag_key_selected.atr = A_REVERSE;
|
||||
dlg.check.atr = A_BOLD;
|
||||
dlg.check_selected.atr = A_REVERSE;
|
||||
dlg.uarrow.atr = A_BOLD;
|
||||
dlg.darrow.atr = A_BOLD;
|
||||
}
|
||||
|
||||
#define DLG_COLOR(dialog, f, b, h) \
|
||||
do { \
|
||||
dlg.dialog.fg = (f); \
|
||||
dlg.dialog.bg = (b); \
|
||||
dlg.dialog.hl = (h); \
|
||||
} while (0)
|
||||
|
||||
static void set_classic_theme(void)
|
||||
{
|
||||
DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true);
|
||||
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true);
|
||||
DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false);
|
||||
DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true);
|
||||
DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true);
|
||||
DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true);
|
||||
DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false);
|
||||
DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true);
|
||||
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false);
|
||||
DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true);
|
||||
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true);
|
||||
DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false);
|
||||
DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false);
|
||||
DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false);
|
||||
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true);
|
||||
DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true);
|
||||
DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true);
|
||||
DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false);
|
||||
DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true);
|
||||
DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false);
|
||||
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true);
|
||||
DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true);
|
||||
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true);
|
||||
DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true);
|
||||
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true);
|
||||
DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false);
|
||||
DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true);
|
||||
DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true);
|
||||
DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true);
|
||||
}
|
||||
|
||||
static void set_blackbg_theme(void)
|
||||
{
|
||||
DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true);
|
||||
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
|
||||
DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
|
||||
DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false);
|
||||
DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
|
||||
|
||||
DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false);
|
||||
DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false);
|
||||
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true);
|
||||
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false);
|
||||
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false);
|
||||
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true);
|
||||
|
||||
DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false);
|
||||
DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false);
|
||||
|
||||
DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false);
|
||||
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true);
|
||||
DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true);
|
||||
|
||||
DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false);
|
||||
|
||||
DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false);
|
||||
DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true);
|
||||
|
||||
DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false);
|
||||
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false);
|
||||
|
||||
DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false);
|
||||
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true);
|
||||
DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false);
|
||||
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true);
|
||||
|
||||
DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false);
|
||||
DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true);
|
||||
|
||||
DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
|
||||
DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
|
||||
}
|
||||
|
||||
static void set_bluetitle_theme(void)
|
||||
{
|
||||
set_classic_theme();
|
||||
DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true);
|
||||
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true);
|
||||
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true);
|
||||
DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true);
|
||||
DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true);
|
||||
DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true);
|
||||
DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Select color theme
|
||||
*/
|
||||
static int set_theme(const char *theme)
|
||||
{
|
||||
int use_color = 1;
|
||||
if (!theme)
|
||||
set_bluetitle_theme();
|
||||
else if (strcmp(theme, "classic") == 0)
|
||||
set_classic_theme();
|
||||
else if (strcmp(theme, "bluetitle") == 0)
|
||||
set_bluetitle_theme();
|
||||
else if (strcmp(theme, "blackbg") == 0)
|
||||
set_blackbg_theme();
|
||||
else if (strcmp(theme, "mono") == 0)
|
||||
use_color = 0;
|
||||
|
||||
return use_color;
|
||||
}
|
||||
|
||||
static void init_one_color(struct dialog_color *color)
|
||||
{
|
||||
static int pair = 0;
|
||||
|
||||
pair++;
|
||||
init_pair(pair, color->fg, color->bg);
|
||||
if (color->hl)
|
||||
color->atr = A_BOLD | COLOR_PAIR(pair);
|
||||
else
|
||||
color->atr = COLOR_PAIR(pair);
|
||||
}
|
||||
|
||||
static void init_dialog_colors(void)
|
||||
{
|
||||
init_one_color(&dlg.screen);
|
||||
init_one_color(&dlg.shadow);
|
||||
init_one_color(&dlg.dialog);
|
||||
init_one_color(&dlg.title);
|
||||
init_one_color(&dlg.border);
|
||||
init_one_color(&dlg.button_active);
|
||||
init_one_color(&dlg.button_inactive);
|
||||
init_one_color(&dlg.button_key_active);
|
||||
init_one_color(&dlg.button_key_inactive);
|
||||
init_one_color(&dlg.button_label_active);
|
||||
init_one_color(&dlg.button_label_inactive);
|
||||
init_one_color(&dlg.inputbox);
|
||||
init_one_color(&dlg.inputbox_border);
|
||||
init_one_color(&dlg.searchbox);
|
||||
init_one_color(&dlg.searchbox_title);
|
||||
init_one_color(&dlg.searchbox_border);
|
||||
init_one_color(&dlg.position_indicator);
|
||||
init_one_color(&dlg.menubox);
|
||||
init_one_color(&dlg.menubox_border);
|
||||
init_one_color(&dlg.item);
|
||||
init_one_color(&dlg.item_selected);
|
||||
init_one_color(&dlg.tag);
|
||||
init_one_color(&dlg.tag_selected);
|
||||
init_one_color(&dlg.tag_key);
|
||||
init_one_color(&dlg.tag_key_selected);
|
||||
init_one_color(&dlg.check);
|
||||
init_one_color(&dlg.check_selected);
|
||||
init_one_color(&dlg.uarrow);
|
||||
init_one_color(&dlg.darrow);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup for color display
|
||||
*/
|
||||
static void color_setup(const char *theme)
|
||||
{
|
||||
int use_color;
|
||||
|
||||
use_color = set_theme(theme);
|
||||
if (use_color && has_colors()) {
|
||||
start_color();
|
||||
init_dialog_colors();
|
||||
} else
|
||||
set_mono_theme();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set window to attribute 'attr'
|
||||
*/
|
||||
void attr_clear(WINDOW * win, int height, int width, chtype attr)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
wattrset(win, attr);
|
||||
for (i = 0; i < height; i++) {
|
||||
wmove(win, i, 0);
|
||||
for (j = 0; j < width; j++)
|
||||
waddch(win, ' ');
|
||||
}
|
||||
touchwin(win);
|
||||
}
|
||||
|
||||
void dialog_clear(void)
|
||||
{
|
||||
attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
|
||||
/* Display background title if it exists ... - SLH */
|
||||
if (dlg.backtitle != NULL) {
|
||||
int i;
|
||||
|
||||
wattrset(stdscr, dlg.screen.atr);
|
||||
mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
|
||||
wmove(stdscr, 1, 1);
|
||||
for (i = 1; i < COLS - 1; i++)
|
||||
waddch(stdscr, ACS_HLINE);
|
||||
}
|
||||
wnoutrefresh(stdscr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do some initialization for dialog
|
||||
*/
|
||||
int init_dialog(const char *backtitle)
|
||||
{
|
||||
int height, width;
|
||||
|
||||
initscr(); /* Init curses */
|
||||
getmaxyx(stdscr, height, width);
|
||||
if (height < 19 || width < 80) {
|
||||
endwin();
|
||||
return -ERRDISPLAYTOOSMALL;
|
||||
}
|
||||
|
||||
dlg.backtitle = backtitle;
|
||||
color_setup(getenv("MENUCONFIG_COLOR"));
|
||||
|
||||
keypad(stdscr, TRUE);
|
||||
cbreak();
|
||||
noecho();
|
||||
dialog_clear();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_dialog_backtitle(const char *backtitle)
|
||||
{
|
||||
dlg.backtitle = backtitle;
|
||||
}
|
||||
|
||||
/*
|
||||
* End using dialog functions.
|
||||
*/
|
||||
void end_dialog(int x, int y)
|
||||
{
|
||||
/* move cursor back to original position */
|
||||
move(y, x);
|
||||
refresh();
|
||||
endwin();
|
||||
}
|
||||
|
||||
/* Print the title of the dialog. Center the title and truncate
|
||||
* tile if wider than dialog (- 2 chars).
|
||||
**/
|
||||
void print_title(WINDOW *dialog, const char *title, int width)
|
||||
{
|
||||
if (title) {
|
||||
int tlen = MIN(width - 2, strlen(title));
|
||||
wattrset(dialog, dlg.title.atr);
|
||||
mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
|
||||
mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
|
||||
waddch(dialog, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a string of text in a window, automatically wrap around to the
|
||||
* next line if the string is too long to fit on one line. Newline
|
||||
* characters '\n' are replaced by spaces. We start on a new line
|
||||
* if there is no room for at least 4 nonblanks following a double-space.
|
||||
*/
|
||||
void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
|
||||
{
|
||||
int newl, cur_x, cur_y;
|
||||
int i, prompt_len, room, wlen;
|
||||
char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
|
||||
|
||||
strcpy(tempstr, prompt);
|
||||
|
||||
prompt_len = strlen(tempstr);
|
||||
|
||||
/*
|
||||
* Remove newlines
|
||||
*/
|
||||
for (i = 0; i < prompt_len; i++) {
|
||||
if (tempstr[i] == '\n')
|
||||
tempstr[i] = ' ';
|
||||
}
|
||||
|
||||
if (prompt_len <= width - x * 2) { /* If prompt is short */
|
||||
wmove(win, y, (width - prompt_len) / 2);
|
||||
waddstr(win, tempstr);
|
||||
} else {
|
||||
cur_x = x;
|
||||
cur_y = y;
|
||||
newl = 1;
|
||||
word = tempstr;
|
||||
while (word && *word) {
|
||||
sp = strchr(word, ' ');
|
||||
if (sp)
|
||||
*sp++ = 0;
|
||||
|
||||
/* Wrap to next line if either the word does not fit,
|
||||
or it is the first word of a new sentence, and it is
|
||||
short, and the next word does not fit. */
|
||||
room = width - cur_x;
|
||||
wlen = strlen(word);
|
||||
if (wlen > room ||
|
||||
(newl && wlen < 4 && sp
|
||||
&& wlen + 1 + strlen(sp) > room
|
||||
&& (!(sp2 = strchr(sp, ' '))
|
||||
|| wlen + 1 + (sp2 - sp) > room))) {
|
||||
cur_y++;
|
||||
cur_x = x;
|
||||
}
|
||||
wmove(win, cur_y, cur_x);
|
||||
waddstr(win, word);
|
||||
getyx(win, cur_y, cur_x);
|
||||
cur_x++;
|
||||
if (sp && *sp == ' ') {
|
||||
cur_x++; /* double space */
|
||||
while (*++sp == ' ') ;
|
||||
newl = 1;
|
||||
} else
|
||||
newl = 0;
|
||||
word = sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a button
|
||||
*/
|
||||
void print_button(WINDOW * win, const char *label, int y, int x, int selected)
|
||||
{
|
||||
int i, temp;
|
||||
|
||||
wmove(win, y, x);
|
||||
wattrset(win, selected ? dlg.button_active.atr
|
||||
: dlg.button_inactive.atr);
|
||||
waddstr(win, "<");
|
||||
temp = strspn(label, " ");
|
||||
label += temp;
|
||||
wattrset(win, selected ? dlg.button_label_active.atr
|
||||
: dlg.button_label_inactive.atr);
|
||||
for (i = 0; i < temp; i++)
|
||||
waddch(win, ' ');
|
||||
wattrset(win, selected ? dlg.button_key_active.atr
|
||||
: dlg.button_key_inactive.atr);
|
||||
waddch(win, label[0]);
|
||||
wattrset(win, selected ? dlg.button_label_active.atr
|
||||
: dlg.button_label_inactive.atr);
|
||||
waddstr(win, (char *)label + 1);
|
||||
wattrset(win, selected ? dlg.button_active.atr
|
||||
: dlg.button_inactive.atr);
|
||||
waddstr(win, ">");
|
||||
wmove(win, y, x + temp + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw a rectangular box with line drawing characters
|
||||
*/
|
||||
void
|
||||
draw_box(WINDOW * win, int y, int x, int height, int width,
|
||||
chtype box, chtype border)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
wattrset(win, 0);
|
||||
for (i = 0; i < height; i++) {
|
||||
wmove(win, y + i, x);
|
||||
for (j = 0; j < width; j++)
|
||||
if (!i && !j)
|
||||
waddch(win, border | ACS_ULCORNER);
|
||||
else if (i == height - 1 && !j)
|
||||
waddch(win, border | ACS_LLCORNER);
|
||||
else if (!i && j == width - 1)
|
||||
waddch(win, box | ACS_URCORNER);
|
||||
else if (i == height - 1 && j == width - 1)
|
||||
waddch(win, box | ACS_LRCORNER);
|
||||
else if (!i)
|
||||
waddch(win, border | ACS_HLINE);
|
||||
else if (i == height - 1)
|
||||
waddch(win, box | ACS_HLINE);
|
||||
else if (!j)
|
||||
waddch(win, border | ACS_VLINE);
|
||||
else if (j == width - 1)
|
||||
waddch(win, box | ACS_VLINE);
|
||||
else
|
||||
waddch(win, box | ' ');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw shadows along the right and bottom edge to give a more 3D look
|
||||
* to the boxes
|
||||
*/
|
||||
void draw_shadow(WINDOW * win, int y, int x, int height, int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (has_colors()) { /* Whether terminal supports color? */
|
||||
wattrset(win, dlg.shadow.atr);
|
||||
wmove(win, y + height, x + 2);
|
||||
for (i = 0; i < width; i++)
|
||||
waddch(win, winch(win) & A_CHARTEXT);
|
||||
for (i = y + 1; i < y + height + 1; i++) {
|
||||
wmove(win, i, x + width);
|
||||
waddch(win, winch(win) & A_CHARTEXT);
|
||||
waddch(win, winch(win) & A_CHARTEXT);
|
||||
}
|
||||
wnoutrefresh(win);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the position of the first alphabetic character in a string.
|
||||
*/
|
||||
int first_alpha(const char *string, const char *exempt)
|
||||
{
|
||||
int i, in_paren = 0, c;
|
||||
|
||||
for (i = 0; i < strlen(string); i++) {
|
||||
c = tolower(string[i]);
|
||||
|
||||
if (strchr("<[(", c))
|
||||
++in_paren;
|
||||
if (strchr(">])", c) && in_paren > 0)
|
||||
--in_paren;
|
||||
|
||||
if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ncurses uses ESC to detect escaped char sequences. This resutl in
|
||||
* a small timeout before ESC is actually delivered to the application.
|
||||
* lxdialog suggest <ESC> <ESC> which is correctly translated to two
|
||||
* times esc. But then we need to ignore the second esc to avoid stepping
|
||||
* out one menu too much. Filter away all escaped key sequences since
|
||||
* keypad(FALSE) turn off ncurses support for escape sequences - and thats
|
||||
* needed to make notimeout() do as expected.
|
||||
*/
|
||||
int on_key_esc(WINDOW *win)
|
||||
{
|
||||
int key;
|
||||
int key2;
|
||||
int key3;
|
||||
|
||||
nodelay(win, TRUE);
|
||||
keypad(win, FALSE);
|
||||
key = wgetch(win);
|
||||
key2 = wgetch(win);
|
||||
do {
|
||||
key3 = wgetch(win);
|
||||
} while (key3 != ERR);
|
||||
nodelay(win, FALSE);
|
||||
keypad(win, TRUE);
|
||||
if (key == KEY_ESC && key2 == ERR)
|
||||
return KEY_ESC;
|
||||
else if (key != ERR && key != KEY_ESC && key2 == ERR)
|
||||
ungetch(key);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* redraw screen in new size */
|
||||
int on_key_resize(void)
|
||||
{
|
||||
dialog_clear();
|
||||
return KEY_RESIZE;
|
||||
}
|
||||
|
||||
struct dialog_list *item_cur;
|
||||
struct dialog_list item_nil;
|
||||
struct dialog_list *item_head;
|
||||
|
||||
void item_reset(void)
|
||||
{
|
||||
struct dialog_list *p, *next;
|
||||
|
||||
for (p = item_head; p; p = next) {
|
||||
next = p->next;
|
||||
free(p);
|
||||
}
|
||||
item_head = NULL;
|
||||
item_cur = &item_nil;
|
||||
}
|
||||
|
||||
void item_make(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct dialog_list *p = malloc(sizeof(*p));
|
||||
|
||||
if (item_head)
|
||||
item_cur->next = p;
|
||||
else
|
||||
item_head = p;
|
||||
item_cur = p;
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void item_add_str(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
size_t avail;
|
||||
|
||||
avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
|
||||
avail, fmt, ap);
|
||||
item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void item_set_tag(char tag)
|
||||
{
|
||||
item_cur->node.tag = tag;
|
||||
}
|
||||
void item_set_data(void *ptr)
|
||||
{
|
||||
item_cur->node.data = ptr;
|
||||
}
|
||||
|
||||
void item_set_selected(int val)
|
||||
{
|
||||
item_cur->node.selected = val;
|
||||
}
|
||||
|
||||
int item_activate_selected(void)
|
||||
{
|
||||
item_foreach()
|
||||
if (item_is_selected())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *item_data(void)
|
||||
{
|
||||
return item_cur->node.data;
|
||||
}
|
||||
|
||||
char item_tag(void)
|
||||
{
|
||||
return item_cur->node.tag;
|
||||
}
|
||||
|
||||
int item_count(void)
|
||||
{
|
||||
int n = 0;
|
||||
struct dialog_list *p;
|
||||
|
||||
for (p = item_head; p; p = p->next)
|
||||
n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
void item_set(int n)
|
||||
{
|
||||
int i = 0;
|
||||
item_foreach()
|
||||
if (i++ == n)
|
||||
return;
|
||||
}
|
||||
|
||||
int item_n(void)
|
||||
{
|
||||
int n = 0;
|
||||
struct dialog_list *p;
|
||||
|
||||
for (p = item_head; p; p = p->next) {
|
||||
if (p == item_cur)
|
||||
return n;
|
||||
n++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *item_str(void)
|
||||
{
|
||||
return item_cur->node.str;
|
||||
}
|
||||
|
||||
int item_is_selected(void)
|
||||
{
|
||||
return (item_cur->node.selected != 0);
|
||||
}
|
||||
|
||||
int item_is_tag(char tag)
|
||||
{
|
||||
return (item_cur->node.tag == tag);
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* yesno.c -- implements the yes/no box
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
/*
|
||||
* Display termination buttons
|
||||
*/
|
||||
static void print_buttons(WINDOW * dialog, int height, int width, int selected)
|
||||
{
|
||||
int x = width / 2 - 10;
|
||||
int y = height - 2;
|
||||
|
||||
print_button(dialog, gettext(" Yes "), y, x, selected == 0);
|
||||
print_button(dialog, gettext(" No "), y, x + 13, selected == 1);
|
||||
|
||||
wmove(dialog, y, x + 1 + 13 * selected);
|
||||
wrefresh(dialog);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a dialog box with two buttons - Yes and No
|
||||
*/
|
||||
int dialog_yesno(const char *title, const char *prompt, int height, int width)
|
||||
{
|
||||
int i, x, y, key = 0, button = 0;
|
||||
WINDOW *dialog;
|
||||
|
||||
do_resize:
|
||||
if (getmaxy(stdscr) < (height + 4))
|
||||
return -ERRDISPLAYTOOSMALL;
|
||||
if (getmaxx(stdscr) < (width + 4))
|
||||
return -ERRDISPLAYTOOSMALL;
|
||||
|
||||
/* center dialog box on screen */
|
||||
x = (COLS - width) / 2;
|
||||
y = (LINES - height) / 2;
|
||||
|
||||
draw_shadow(stdscr, y, x, height, width);
|
||||
|
||||
dialog = newwin(height, width, y, x);
|
||||
keypad(dialog, TRUE);
|
||||
|
||||
draw_box(dialog, 0, 0, height, width,
|
||||
dlg.dialog.atr, dlg.border.atr);
|
||||
wattrset(dialog, dlg.border.atr);
|
||||
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
||||
for (i = 0; i < width - 2; i++)
|
||||
waddch(dialog, ACS_HLINE);
|
||||
wattrset(dialog, dlg.dialog.atr);
|
||||
waddch(dialog, ACS_RTEE);
|
||||
|
||||
print_title(dialog, title, width);
|
||||
|
||||
wattrset(dialog, dlg.dialog.atr);
|
||||
print_autowrap(dialog, prompt, width - 2, 1, 3);
|
||||
|
||||
print_buttons(dialog, height, width, 0);
|
||||
|
||||
while (key != KEY_ESC) {
|
||||
key = wgetch(dialog);
|
||||
switch (key) {
|
||||
case 'Y':
|
||||
case 'y':
|
||||
delwin(dialog);
|
||||
return 0;
|
||||
case 'N':
|
||||
case 'n':
|
||||
delwin(dialog);
|
||||
return 1;
|
||||
|
||||
case TAB:
|
||||
case KEY_LEFT:
|
||||
case KEY_RIGHT:
|
||||
button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button);
|
||||
|
||||
print_buttons(dialog, height, width, button);
|
||||
wrefresh(dialog);
|
||||
break;
|
||||
case ' ':
|
||||
case '\n':
|
||||
delwin(dialog);
|
||||
return button;
|
||||
case KEY_ESC:
|
||||
key = on_key_esc(dialog);
|
||||
break;
|
||||
case KEY_RESIZE:
|
||||
delwin(dialog);
|
||||
on_key_resize();
|
||||
goto do_resize;
|
||||
}
|
||||
}
|
||||
|
||||
delwin(dialog);
|
||||
return key; /* ESC pressed */
|
||||
}
|
|
@ -0,0 +1,931 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*
|
||||
* Introduced single menu mode (show all sub-menus in one large tree).
|
||||
* 2002-11-06 Petr Baudis <pasky@ucw.cz>
|
||||
*
|
||||
* i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
|
||||
#define LKC_DIRECT_LINK
|
||||
#include "lkc.h"
|
||||
#include "lxdialog/dialog.h"
|
||||
|
||||
static const char mconf_readme[] = N_(
|
||||
"Overview\n"
|
||||
"--------\n"
|
||||
"Some features may be built directly into coreinfo.\n"
|
||||
"Some may be made into loadable runtime modules. Some features\n"
|
||||
"may be completely removed altogether. There are also certain\n"
|
||||
"parameters which are not really features, but must be\n"
|
||||
"entered in as decimal or hexadecimal numbers or possibly text.\n"
|
||||
"\n"
|
||||
"Menu items beginning with following braces represent features that\n"
|
||||
" [ ] can be built in or removed\n"
|
||||
" < > can be built in, modularized or removed\n"
|
||||
" { } can be built in or modularized (selected by other feature)\n"
|
||||
" - - are selected by other feature,\n"
|
||||
"while *, M or whitespace inside braces means to build in, build as\n"
|
||||
"a module or to exclude the feature respectively.\n"
|
||||
"\n"
|
||||
"To change any of these features, highlight it with the cursor\n"
|
||||
"keys and press <Y> to build it in, <M> to make it a module or\n"
|
||||
"<N> to removed it. You may also press the <Space Bar> to cycle\n"
|
||||
"through the available options (ie. Y->N->M->Y).\n"
|
||||
"\n"
|
||||
"Some additional keyboard hints:\n"
|
||||
"\n"
|
||||
"Menus\n"
|
||||
"----------\n"
|
||||
"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
|
||||
" you wish to change or submenu wish to select and press <Enter>.\n"
|
||||
" Submenus are designated by \"--->\".\n"
|
||||
"\n"
|
||||
" Shortcut: Press the option's highlighted letter (hotkey).\n"
|
||||
" Pressing a hotkey more than once will sequence\n"
|
||||
" through all visible items which use that hotkey.\n"
|
||||
"\n"
|
||||
" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
|
||||
" unseen options into view.\n"
|
||||
"\n"
|
||||
"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
|
||||
" and press <ENTER>.\n"
|
||||
"\n"
|
||||
" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
|
||||
" using those letters. You may press a single <ESC>, but\n"
|
||||
" there is a delayed response which you may find annoying.\n"
|
||||
"\n"
|
||||
" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
|
||||
" <Exit> and <Help>\n"
|
||||
"\n"
|
||||
"o To get help with an item, use the cursor keys to highlight <Help>\n"
|
||||
" and Press <ENTER>.\n"
|
||||
"\n"
|
||||
" Shortcut: Press <H> or <?>.\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Radiolists (Choice lists)\n"
|
||||
"-----------\n"
|
||||
"o Use the cursor keys to select the option you wish to set and press\n"
|
||||
" <S> or the <SPACE BAR>.\n"
|
||||
"\n"
|
||||
" Shortcut: Press the first letter of the option you wish to set then\n"
|
||||
" press <S> or <SPACE BAR>.\n"
|
||||
"\n"
|
||||
"o To see available help for the item, use the cursor keys to highlight\n"
|
||||
" <Help> and Press <ENTER>.\n"
|
||||
"\n"
|
||||
" Shortcut: Press <H> or <?>.\n"
|
||||
"\n"
|
||||
" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
|
||||
" <Help>\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Data Entry\n"
|
||||
"-----------\n"
|
||||
"o Enter the requested information and press <ENTER>\n"
|
||||
" If you are entering hexadecimal values, it is not necessary to\n"
|
||||
" add the '0x' prefix to the entry.\n"
|
||||
"\n"
|
||||
"o For help, use the <TAB> or cursor keys to highlight the help option\n"
|
||||
" and press <ENTER>. You can try <TAB><H> as well.\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Text Box (Help Window)\n"
|
||||
"--------\n"
|
||||
"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
|
||||
" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
|
||||
" who are familiar with less and lynx.\n"
|
||||
"\n"
|
||||
"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Alternate Configuration Files\n"
|
||||
"-----------------------------\n"
|
||||
"Menuconfig supports the use of alternate configuration files for\n"
|
||||
"those who, for various reasons, find it necessary to switch\n"
|
||||
"between different configurations.\n"
|
||||
"\n"
|
||||
"At the end of the main menu you will find two options. One is\n"
|
||||
"for saving the current configuration to a file of your choosing.\n"
|
||||
"The other option is for loading a previously saved alternate\n"
|
||||
"configuration.\n"
|
||||
"\n"
|
||||
"Even if you don't use alternate configuration files, but you\n"
|
||||
"find during a Menuconfig session that you have completely messed\n"
|
||||
"up your settings, you may use the \"Load Alternate...\" option to\n"
|
||||
"restore your previously saved settings from \".config\" without\n"
|
||||
"restarting Menuconfig.\n"
|
||||
"\n"
|
||||
"Other information\n"
|
||||
"-----------------\n"
|
||||
"If you use Menuconfig in an XTERM window make sure you have your\n"
|
||||
"$TERM variable set to point to a xterm definition which supports color.\n"
|
||||
"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
|
||||
"display correctly in a RXVT window because rxvt displays only one\n"
|
||||
"intensity of color, bright.\n"
|
||||
"\n"
|
||||
"Menuconfig will display larger menus on screens or xterms which are\n"
|
||||
"set to display more than the standard 25 row by 80 column geometry.\n"
|
||||
"In order for this to work, the \"stty size\" command must be able to\n"
|
||||
"display the screen's current row and column geometry. I STRONGLY\n"
|
||||
"RECOMMEND that you make sure you do NOT have the shell variables\n"
|
||||
"LINES and COLUMNS exported into your environment. Some distributions\n"
|
||||
"export those variables via /etc/profile. Some ncurses programs can\n"
|
||||
"become confused when those variables (LINES & COLUMNS) don't reflect\n"
|
||||
"the true screen size.\n"
|
||||
"\n"
|
||||
"Optional personality available\n"
|
||||
"------------------------------\n"
|
||||
"If you prefer to have all of the options listed in a single\n"
|
||||
"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
|
||||
"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
|
||||
"\n"
|
||||
"make MENUCONFIG_MODE=single_menu menuconfig\n"
|
||||
"\n"
|
||||
"<Enter> will then unroll the appropriate category, or enfold it if it\n"
|
||||
"is already unrolled.\n"
|
||||
"\n"
|
||||
"Note that this mode can eventually be a little more CPU expensive\n"
|
||||
"(especially with a larger number of unrolled categories) than the\n"
|
||||
"default mode.\n"
|
||||
"\n"
|
||||
"Different color themes available\n"
|
||||
"--------------------------------\n"
|
||||
"It is possible to select different color themes using the variable\n"
|
||||
"MENUCONFIG_COLOR. To select a theme use:\n"
|
||||
"\n"
|
||||
"make MENUCONFIG_COLOR=<theme> menuconfig\n"
|
||||
"\n"
|
||||
"Available themes are\n"
|
||||
" mono => selects colors suitable for monochrome displays\n"
|
||||
" blackbg => selects a color scheme with black background\n"
|
||||
" classic => theme with blue background. The classic look\n"
|
||||
" bluetitle => a LCD friendly version of classic. (default)\n"
|
||||
"\n"),
|
||||
menu_instructions[] = N_(
|
||||
"Arrow keys navigate the menu. "
|
||||
"<Enter> selects submenus --->. "
|
||||
"Highlighted letters are hotkeys. "
|
||||
"Pressing <Y> includes, <N> excludes, <M> modularizes features. "
|
||||
"Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
|
||||
"Legend: [*] built-in [ ] excluded <M> module < > module capable"),
|
||||
radiolist_instructions[] = N_(
|
||||
"Use the arrow keys to navigate this window or "
|
||||
"press the hotkey of the item you wish to select "
|
||||
"followed by the <SPACE BAR>. "
|
||||
"Press <?> for additional information about this option."),
|
||||
inputbox_instructions_int[] = N_(
|
||||
"Please enter a decimal value. "
|
||||
"Fractions will not be accepted. "
|
||||
"Use the <TAB> key to move from the input field to the buttons below it."),
|
||||
inputbox_instructions_hex[] = N_(
|
||||
"Please enter a hexadecimal value. "
|
||||
"Use the <TAB> key to move from the input field to the buttons below it."),
|
||||
inputbox_instructions_string[] = N_(
|
||||
"Please enter a string value. "
|
||||
"Use the <TAB> key to move from the input field to the buttons below it."),
|
||||
setmod_text[] = N_(
|
||||
"This feature depends on another which has been configured as a module.\n"
|
||||
"As a result, this feature will be built as a module."),
|
||||
nohelp_text[] = N_(
|
||||
"There is no help available for this option.\n"),
|
||||
load_config_text[] = N_(
|
||||
"Enter the name of the configuration file you wish to load. "
|
||||
"Accept the name shown to restore the configuration you "
|
||||
"last retrieved. Leave blank to abort."),
|
||||
load_config_help[] = N_(
|
||||
"\n"
|
||||
"For various reasons, one may wish to keep several different\n"
|
||||
"configurations available on a single machine.\n"
|
||||
"\n"
|
||||
"If you have saved a previous configuration in a file other than the\n"
|
||||
"default, entering the name of the file here will allow you\n"
|
||||
"to modify that configuration.\n"
|
||||
"\n"
|
||||
"If you are uncertain, then you have probably never used alternate\n"
|
||||
"configuration files. You should therefor leave this blank to abort.\n"),
|
||||
save_config_text[] = N_(
|
||||
"Enter a filename to which this configuration should be saved "
|
||||
"as an alternate. Leave blank to abort."),
|
||||
save_config_help[] = N_(
|
||||
"\n"
|
||||
"For various reasons, one may wish to keep 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"
|
||||
"If you are uncertain what all this means then you should probably\n"
|
||||
"leave this blank.\n"),
|
||||
search_help[] = N_(
|
||||
"\n"
|
||||
"Search for CONFIG_ symbols and display their relations.\n"
|
||||
"Regular expressions are allowed.\n"
|
||||
"Example: search for \"^FOO\"\n"
|
||||
"Result:\n"
|
||||
"-----------------------------------------------------------------\n"
|
||||
"Symbol: FOO [=m]\n"
|
||||
"Prompt: Foo bus is used to drive the bar HW\n"
|
||||
"Defined at drivers/pci/Kconfig:47\n"
|
||||
"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
|
||||
"Location:\n"
|
||||
" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
|
||||
" -> PCI support (PCI [=y])\n"
|
||||
" -> PCI access mode (<choice> [=y])\n"
|
||||
"Selects: LIBCRC32\n"
|
||||
"Selected by: BAR\n"
|
||||
"-----------------------------------------------------------------\n"
|
||||
"o The line 'Prompt:' shows the text used in the menu structure for\n"
|
||||
" this CONFIG_ symbol\n"
|
||||
"o The 'Defined at' line tell at what file / line number the symbol\n"
|
||||
" is defined\n"
|
||||
"o The 'Depends on:' line tell what symbols needs to be defined for\n"
|
||||
" this symbol to be visible in the menu (selectable)\n"
|
||||
"o The 'Location:' lines tell where in the menu structure this symbol\n"
|
||||
" is located\n"
|
||||
" A location followed by a [=y] indicate that this is a selectable\n"
|
||||
" menu item - and current value is displayed inside brackets.\n"
|
||||
"o The 'Selects:' line tell what symbol will be automatically\n"
|
||||
" selected if this symbol is selected (y or m)\n"
|
||||
"o The 'Selected by' line tell what symbol has selected this symbol\n"
|
||||
"\n"
|
||||
"Only relevant lines are shown.\n"
|
||||
"\n\n"
|
||||
"Search examples:\n"
|
||||
"Examples: USB => find all CONFIG_ symbols containing USB\n"
|
||||
" ^USB => find all CONFIG_ symbols starting with USB\n"
|
||||
" USB$ => find all CONFIG_ symbols ending with USB\n"
|
||||
"\n");
|
||||
|
||||
static int indent;
|
||||
static struct menu *current_menu;
|
||||
static int child_count;
|
||||
static int single_menu_mode;
|
||||
|
||||
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_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 void get_prompt_str(struct gstr *r, struct property *prop)
|
||||
{
|
||||
int i, j;
|
||||
struct menu *submenu[8], *menu;
|
||||
|
||||
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)
|
||||
submenu[i++] = menu;
|
||||
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 (menu->sym) {
|
||||
str_printf(r, " (%s [=%s])", menu->sym->name ?
|
||||
menu->sym->name : _("<choice>"),
|
||||
sym_get_string_value(menu->sym));
|
||||
}
|
||||
str_append(r, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void get_symbol_str(struct gstr *r, struct symbol *sym)
|
||||
{
|
||||
bool hit;
|
||||
struct property *prop;
|
||||
|
||||
if (sym && sym->name)
|
||||
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
|
||||
sym_get_string_value(sym));
|
||||
for_all_prompts(sym, prop)
|
||||
get_prompt_str(r, prop);
|
||||
hit = false;
|
||||
for_all_properties(sym, prop, P_SELECT) {
|
||||
if (!hit) {
|
||||
str_append(r, " Selects: ");
|
||||
hit = true;
|
||||
} else
|
||||
str_printf(r, " && ");
|
||||
expr_gstr_print(prop->expr, r);
|
||||
}
|
||||
if (hit)
|
||||
str_append(r, "\n");
|
||||
if (sym->rev_dep.expr) {
|
||||
str_append(r, _(" Selected by: "));
|
||||
expr_gstr_print(sym->rev_dep.expr, r);
|
||||
str_append(r, "\n");
|
||||
}
|
||||
str_append(r, "\n\n");
|
||||
}
|
||||
|
||||
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 - coreinfo v%s Configuration"),
|
||||
config_filename, getenv("KERNELVERSION"));
|
||||
if (size >= sizeof(menu_backtitle))
|
||||
menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
|
||||
set_dialog_backtitle(menu_backtitle);
|
||||
|
||||
size = snprintf(filename, sizeof(filename), "%s", config_filename);
|
||||
if (size >= sizeof(filename))
|
||||
filename[sizeof(filename)-1] = '\0';
|
||||
}
|
||||
|
||||
|
||||
static void search_conf(void)
|
||||
{
|
||||
struct symbol **sym_arr;
|
||||
struct gstr res;
|
||||
char *dialog_input;
|
||||
int dres;
|
||||
again:
|
||||
dialog_clear();
|
||||
dres = dialog_inputbox(_("Search Configuration Parameter"),
|
||||
_("Enter CONFIG_ (sub)string to search for "
|
||||
"(with or without \"CONFIG\")"),
|
||||
10, 75, "");
|
||||
switch (dres) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
show_helptext(_("Search Configuration"), search_help);
|
||||
goto again;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* strip CONFIG_ if necessary */
|
||||
dialog_input = dialog_input_result;
|
||||
if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
|
||||
dialog_input += 7;
|
||||
|
||||
sym_arr = sym_re_search(dialog_input);
|
||||
res = get_relations_str(sym_arr);
|
||||
free(sym_arr);
|
||||
show_textbox(_("Search Results"), str_get(&res), 0, 0);
|
||||
str_free(&res);
|
||||
}
|
||||
|
||||
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_is_visible(menu))
|
||||
return;
|
||||
|
||||
sym = menu->sym;
|
||||
prop = menu->prompt;
|
||||
if (!sym) {
|
||||
if (prop && menu != current_menu) {
|
||||
const char *prompt = menu_get_prompt(menu);
|
||||
switch (prop->type) {
|
||||
case P_MENU:
|
||||
child_count++;
|
||||
prompt = _(prompt);
|
||||
if (single_menu_mode) {
|
||||
item_make("%s%*c%s",
|
||||
menu->data ? "-->" : "++>",
|
||||
indent + 1, ' ', prompt);
|
||||
} else
|
||||
item_make(" %*c%s --->", indent + 1, ' ', prompt);
|
||||
|
||||
item_set_tag('m');
|
||||
item_set_data(menu);
|
||||
if (single_menu_mode && menu->data)
|
||||
goto conf_childs;
|
||||
return;
|
||||
case P_COMMENT:
|
||||
if (prompt) {
|
||||
child_count++;
|
||||
item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt));
|
||||
item_set_tag(':');
|
||||
item_set_data(menu);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (prompt) {
|
||||
child_count++;
|
||||
item_make("---%*c%s", indent + 1, ' ', _(prompt));
|
||||
item_set_tag(':');
|
||||
item_set_data(menu);
|
||||
}
|
||||
}
|
||||
} else
|
||||
doint = 0;
|
||||
goto conf_childs;
|
||||
}
|
||||
|
||||
type = sym_get_type(sym);
|
||||
if (sym_is_choice(sym)) {
|
||||
struct symbol *def_sym = sym_get_choice_value(sym);
|
||||
struct menu *def_menu = NULL;
|
||||
|
||||
child_count++;
|
||||
for (child = menu->list; child; child = child->next) {
|
||||
if (menu_is_visible(child) && child->sym == def_sym)
|
||||
def_menu = child;
|
||||
}
|
||||
|
||||
val = sym_get_tristate_value(sym);
|
||||
if (sym_is_changable(sym)) {
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
item_make("[%c]", val == no ? ' ' : '*');
|
||||
break;
|
||||
case S_TRISTATE:
|
||||
switch (val) {
|
||||
case yes: ch = '*'; break;
|
||||
case mod: ch = 'M'; break;
|
||||
default: ch = ' '; break;
|
||||
}
|
||||
item_make("<%c>", ch);
|
||||
break;
|
||||
}
|
||||
item_set_tag('t');
|
||||
item_set_data(menu);
|
||||
} else {
|
||||
item_make(" ");
|
||||
item_set_tag(def_menu ? 't' : ':');
|
||||
item_set_data(menu);
|
||||
}
|
||||
|
||||
item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
|
||||
if (val == yes) {
|
||||
if (def_menu) {
|
||||
item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
|
||||
item_add_str(" --->");
|
||||
if (def_menu->list) {
|
||||
indent += 2;
|
||||
build_conf(def_menu);
|
||||
indent -= 2;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (menu == current_menu) {
|
||||
item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
|
||||
item_set_tag(':');
|
||||
item_set_data(menu);
|
||||
goto conf_childs;
|
||||
}
|
||||
child_count++;
|
||||
val = sym_get_tristate_value(sym);
|
||||
if (sym_is_choice_value(sym) && val == yes) {
|
||||
item_make(" ");
|
||||
item_set_tag(':');
|
||||
item_set_data(menu);
|
||||
} else {
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
if (sym_is_changable(sym))
|
||||
item_make("[%c]", val == no ? ' ' : '*');
|
||||
else
|
||||
item_make("-%c-", val == no ? ' ' : '*');
|
||||
item_set_tag('t');
|
||||
item_set_data(menu);
|
||||
break;
|
||||
case S_TRISTATE:
|
||||
switch (val) {
|
||||
case yes: ch = '*'; break;
|
||||
case mod: ch = 'M'; break;
|
||||
default: ch = ' '; break;
|
||||
}
|
||||
if (sym_is_changable(sym)) {
|
||||
if (sym->rev_dep.tri == mod)
|
||||
item_make("{%c}", ch);
|
||||
else
|
||||
item_make("<%c>", ch);
|
||||
} else
|
||||
item_make("-%c-", ch);
|
||||
item_set_tag('t');
|
||||
item_set_data(menu);
|
||||
break;
|
||||
default:
|
||||
tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
|
||||
item_make("(%s)", sym_get_string_value(sym));
|
||||
tmp = indent - tmp + 4;
|
||||
if (tmp < 0)
|
||||
tmp = 0;
|
||||
item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
|
||||
(sym_has_value(sym) || !sym_is_changable(sym)) ?
|
||||
"" : _(" (NEW)"));
|
||||
item_set_tag('s');
|
||||
item_set_data(menu);
|
||||
goto conf_childs;
|
||||
}
|
||||
}
|
||||
item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
|
||||
(sym_has_value(sym) || !sym_is_changable(sym)) ?
|
||||
"" : _(" (NEW)"));
|
||||
if (menu->prompt->type == P_MENU) {
|
||||
item_add_str(" --->");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
conf_childs:
|
||||
indent += doint;
|
||||
for (child = menu->list; child; child = child->next)
|
||||
build_conf(child);
|
||||
indent -= doint;
|
||||
}
|
||||
|
||||
static void conf(struct menu *menu)
|
||||
{
|
||||
struct menu *submenu;
|
||||
const char *prompt = menu_get_prompt(menu);
|
||||
struct symbol *sym;
|
||||
struct menu *active_menu = NULL;
|
||||
int res;
|
||||
int s_scroll = 0;
|
||||
|
||||
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');
|
||||
}
|
||||
dialog_clear();
|
||||
res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
|
||||
_(menu_instructions),
|
||||
active_menu, &s_scroll);
|
||||
if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
|
||||
break;
|
||||
if (!item_activate_selected())
|
||||
continue;
|
||||
if (!item_tag())
|
||||
continue;
|
||||
|
||||
submenu = item_data();
|
||||
active_menu = item_data();
|
||||
if (submenu)
|
||||
sym = submenu->sym;
|
||||
else
|
||||
sym = NULL;
|
||||
|
||||
switch (res) {
|
||||
case 0:
|
||||
switch (item_tag()) {
|
||||
case 'm':
|
||||
if (single_menu_mode)
|
||||
submenu->data = (void *) (long) !submenu->data;
|
||||
else
|
||||
conf(submenu);
|
||||
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);
|
||||
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
|
||||
show_helptext(_("README"), _(mconf_readme));
|
||||
break;
|
||||
case 3:
|
||||
if (item_is_tag('t')) {
|
||||
if (sym_set_tristate_value(sym, yes))
|
||||
break;
|
||||
if (sym_set_tristate_value(sym, mod))
|
||||
show_textbox(NULL, setmod_text, 6, 74);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (item_is_tag('t'))
|
||||
sym_set_tristate_value(sym, no);
|
||||
break;
|
||||
case 5:
|
||||
if (item_is_tag('t'))
|
||||
sym_set_tristate_value(sym, mod);
|
||||
break;
|
||||
case 6:
|
||||
if (item_is_tag('t'))
|
||||
sym_toggle_tristate_value(sym);
|
||||
else if (item_is_tag('m'))
|
||||
conf(submenu);
|
||||
break;
|
||||
case 7:
|
||||
search_conf();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void show_textbox(const char *title, const char *text, int r, int c)
|
||||
{
|
||||
dialog_clear();
|
||||
dialog_textbox(title, text, r, c);
|
||||
}
|
||||
|
||||
static void show_helptext(const char *title, const char *text)
|
||||
{
|
||||
show_textbox(title, text, 0, 0);
|
||||
}
|
||||
|
||||
static void show_help(struct menu *menu)
|
||||
{
|
||||
struct gstr help = str_new();
|
||||
struct symbol *sym = menu->sym;
|
||||
|
||||
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);
|
||||
}
|
||||
get_symbol_str(&help, sym);
|
||||
show_helptext(_(menu_get_prompt(menu)), str_get(&help));
|
||||
str_free(&help);
|
||||
}
|
||||
|
||||
static void conf_choice(struct menu *menu)
|
||||
{
|
||||
const char *prompt = _(menu_get_prompt(menu));
|
||||
struct menu *child;
|
||||
struct symbol *active;
|
||||
|
||||
active = sym_get_choice_value(menu->sym);
|
||||
while (1) {
|
||||
int res;
|
||||
int selected;
|
||||
item_reset();
|
||||
|
||||
current_menu = menu;
|
||||
for (child = menu->list; child; child = child->next) {
|
||||
if (!menu_is_visible(child))
|
||||
continue;
|
||||
item_make("%s", _(menu_get_prompt(child)));
|
||||
item_set_data(child);
|
||||
if (child->sym == active)
|
||||
item_set_selected(1);
|
||||
if (child->sym == sym_get_choice_value(menu->sym))
|
||||
item_set_tag('X');
|
||||
}
|
||||
dialog_clear();
|
||||
res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
|
||||
_(radiolist_instructions),
|
||||
15, 70, 6);
|
||||
selected = item_activate_selected();
|
||||
switch (res) {
|
||||
case 0:
|
||||
if (selected) {
|
||||
child = item_data();
|
||||
sym_set_tristate_value(child->sym, yes);
|
||||
}
|
||||
return;
|
||||
case 1:
|
||||
if (selected) {
|
||||
child = item_data();
|
||||
show_help(child);
|
||||
active = child->sym;
|
||||
} else
|
||||
show_help(menu);
|
||||
break;
|
||||
case KEY_ESC:
|
||||
return;
|
||||
case -ERRDISPLAYTOOSMALL:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void conf_string(struct menu *menu)
|
||||
{
|
||||
const char *prompt = menu_get_prompt(menu);
|
||||
|
||||
while (1) {
|
||||
int res;
|
||||
char *heading;
|
||||
|
||||
switch (sym_get_type(menu->sym)) {
|
||||
case S_INT:
|
||||
heading = _(inputbox_instructions_int);
|
||||
break;
|
||||
case S_HEX:
|
||||
heading = _(inputbox_instructions_hex);
|
||||
break;
|
||||
case S_STRING:
|
||||
heading = _(inputbox_instructions_string);
|
||||
break;
|
||||
default:
|
||||
heading = _("Internal mconf error!");
|
||||
}
|
||||
dialog_clear();
|
||||
res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
|
||||
heading, 10, 75,
|
||||
sym_get_string_value(menu->sym));
|
||||
switch (res) {
|
||||
case 0:
|
||||
if (sym_set_string_value(menu->sym, dialog_input_result))
|
||||
return;
|
||||
show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
|
||||
break;
|
||||
case 1:
|
||||
show_help(menu);
|
||||
break;
|
||||
case KEY_ESC:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void conf_load(void)
|
||||
{
|
||||
|
||||
while (1) {
|
||||
int res;
|
||||
dialog_clear();
|
||||
res = dialog_inputbox(NULL, load_config_text,
|
||||
11, 55, filename);
|
||||
switch(res) {
|
||||
case 0:
|
||||
if (!dialog_input_result[0])
|
||||
return;
|
||||
if (!conf_read(dialog_input_result)) {
|
||||
set_config_filename(dialog_input_result);
|
||||
sym_set_change_count(1);
|
||||
return;
|
||||
}
|
||||
show_textbox(NULL, _("File does not exist!"), 5, 38);
|
||||
break;
|
||||
case 1:
|
||||
show_helptext(_("Load Alternate Configuration"), load_config_help);
|
||||
break;
|
||||
case KEY_ESC:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void conf_save(void)
|
||||
{
|
||||
while (1) {
|
||||
int res;
|
||||
dialog_clear();
|
||||
res = dialog_inputbox(NULL, save_config_text,
|
||||
11, 55, filename);
|
||||
switch(res) {
|
||||
case 0:
|
||||
if (!dialog_input_result[0])
|
||||
return;
|
||||
if (!conf_write(dialog_input_result)) {
|
||||
set_config_filename(dialog_input_result);
|
||||
return;
|
||||
}
|
||||
show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
|
||||
break;
|
||||
case 1:
|
||||
show_helptext(_("Save Alternate Configuration"), save_config_help);
|
||||
break;
|
||||
case KEY_ESC:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int saved_x, saved_y;
|
||||
char *mode;
|
||||
int res;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
conf_parse(av[1]);
|
||||
conf_read(NULL);
|
||||
|
||||
mode = getenv("MENUCONFIG_MODE");
|
||||
if (mode) {
|
||||
if (!strcasecmp(mode, "single_menu"))
|
||||
single_menu_mode = 1;
|
||||
}
|
||||
|
||||
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"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
set_config_filename(conf_get_configname());
|
||||
do {
|
||||
conf(&rootmenu);
|
||||
dialog_clear();
|
||||
if (conf_get_changed())
|
||||
res = dialog_yesno(NULL,
|
||||
_("Do you wish to save your "
|
||||
"new configuration?\n"
|
||||
"<ESC><ESC> to continue."),
|
||||
6, 60);
|
||||
else
|
||||
res = -1;
|
||||
} 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 configuration.\n"
|
||||
"Your configuration changes were NOT saved."
|
||||
"\n\n"));
|
||||
return 1;
|
||||
}
|
||||
if (conf_write_autoconf()) {
|
||||
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
|
||||
return 1;
|
||||
}
|
||||
case -1:
|
||||
printf(_("\n\n"
|
||||
"*** End of coreinfo configuration.\n"
|
||||
"*** Execute 'make' to build or try 'make help'."
|
||||
"\n\n"));
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, _("\n\n"
|
||||
"Your configuration changes were NOT saved."
|
||||
"\n\n"));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LKC_DIRECT_LINK
|
||||
#include "lkc.h"
|
||||
|
||||
struct menu rootmenu;
|
||||
static struct menu **last_entry_ptr;
|
||||
|
||||
struct file *file_list;
|
||||
struct file *current_file;
|
||||
|
||||
void menu_warn(struct menu *menu, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void prop_warn(struct property *prop, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void menu_init(void)
|
||||
{
|
||||
current_entry = current_menu = &rootmenu;
|
||||
last_entry_ptr = &rootmenu.list;
|
||||
}
|
||||
|
||||
void menu_add_entry(struct symbol *sym)
|
||||
{
|
||||
struct menu *menu;
|
||||
|
||||
menu = malloc(sizeof(*menu));
|
||||
memset(menu, 0, sizeof(*menu));
|
||||
menu->sym = sym;
|
||||
menu->parent = current_menu;
|
||||
menu->file = current_file;
|
||||
menu->lineno = zconf_lineno();
|
||||
|
||||
*last_entry_ptr = menu;
|
||||
last_entry_ptr = &menu->next;
|
||||
current_entry = menu;
|
||||
}
|
||||
|
||||
void menu_end_entry(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct menu *menu_add_menu(void)
|
||||
{
|
||||
menu_end_entry();
|
||||
last_entry_ptr = ¤t_entry->list;
|
||||
return current_menu = current_entry;
|
||||
}
|
||||
|
||||
void menu_end_menu(void)
|
||||
{
|
||||
last_entry_ptr = ¤t_menu->next;
|
||||
current_menu = current_menu->parent;
|
||||
}
|
||||
|
||||
struct expr *menu_check_dep(struct expr *e)
|
||||
{
|
||||
if (!e)
|
||||
return e;
|
||||
|
||||
switch (e->type) {
|
||||
case E_NOT:
|
||||
e->left.expr = menu_check_dep(e->left.expr);
|
||||
break;
|
||||
case E_OR:
|
||||
case E_AND:
|
||||
e->left.expr = menu_check_dep(e->left.expr);
|
||||
e->right.expr = menu_check_dep(e->right.expr);
|
||||
break;
|
||||
case E_SYMBOL:
|
||||
/* change 'm' into 'm' && MODULES */
|
||||
if (e->left.sym == &symbol_mod)
|
||||
return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
void menu_add_dep(struct expr *dep)
|
||||
{
|
||||
current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
|
||||
}
|
||||
|
||||
void menu_set_type(int type)
|
||||
{
|
||||
struct symbol *sym = current_entry->sym;
|
||||
|
||||
if (sym->type == type)
|
||||
return;
|
||||
if (sym->type == S_UNKNOWN) {
|
||||
sym->type = type;
|
||||
return;
|
||||
}
|
||||
menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
|
||||
sym->name ? sym->name : "<choice>",
|
||||
sym_type_name(sym->type), sym_type_name(type));
|
||||
}
|
||||
|
||||
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
|
||||
{
|
||||
struct property *prop = prop_alloc(type, current_entry->sym);
|
||||
|
||||
prop->menu = current_entry;
|
||||
prop->expr = expr;
|
||||
prop->visible.expr = menu_check_dep(dep);
|
||||
|
||||
if (prompt) {
|
||||
if (isspace(*prompt)) {
|
||||
prop_warn(prop, "leading whitespace ignored");
|
||||
while (isspace(*prompt))
|
||||
prompt++;
|
||||
}
|
||||
if (current_entry->prompt)
|
||||
prop_warn(prop, "prompt redefined");
|
||||
current_entry->prompt = prop;
|
||||
}
|
||||
prop->text = prompt;
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
|
||||
{
|
||||
return menu_add_prop(type, prompt, NULL, dep);
|
||||
}
|
||||
|
||||
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
|
||||
{
|
||||
menu_add_prop(type, NULL, expr, dep);
|
||||
}
|
||||
|
||||
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
|
||||
{
|
||||
menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
|
||||
}
|
||||
|
||||
void menu_add_option(int token, char *arg)
|
||||
{
|
||||
struct property *prop;
|
||||
|
||||
switch (token) {
|
||||
case T_OPT_MODULES:
|
||||
prop = prop_alloc(P_DEFAULT, modules_sym);
|
||||
prop->expr = expr_alloc_symbol(current_entry->sym);
|
||||
break;
|
||||
case T_OPT_DEFCONFIG_LIST:
|
||||
if (!sym_defconfig_list)
|
||||
sym_defconfig_list = current_entry->sym;
|
||||
else if (sym_defconfig_list != current_entry->sym)
|
||||
zconf_error("trying to redefine defconfig symbol");
|
||||
break;
|
||||
case T_OPT_ENV:
|
||||
prop_add_env(arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int menu_range_valid_sym(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));
|
||||
}
|
||||
|
||||
void sym_check_prop(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
struct symbol *sym2;
|
||||
for (prop = sym->prop; prop; prop = prop->next) {
|
||||
switch (prop->type) {
|
||||
case P_DEFAULT:
|
||||
if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
|
||||
prop->expr->type != E_SYMBOL)
|
||||
prop_warn(prop,
|
||||
"default for config symbol '%'"
|
||||
" must be a single symbol", sym->name);
|
||||
break;
|
||||
case P_SELECT:
|
||||
sym2 = prop_get_symbol(prop);
|
||||
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
|
||||
prop_warn(prop,
|
||||
"config symbol '%s' uses select, but is "
|
||||
"not boolean or tristate", sym->name);
|
||||
else if (sym2->type != S_UNKNOWN &&
|
||||
sym2->type != S_BOOLEAN &&
|
||||
sym2->type != S_TRISTATE)
|
||||
prop_warn(prop,
|
||||
"'%s' has wrong type. 'select' only "
|
||||
"accept arguments of boolean and "
|
||||
"tristate type", sym2->name);
|
||||
break;
|
||||
case P_RANGE:
|
||||
if (sym->type != S_INT && sym->type != S_HEX)
|
||||
prop_warn(prop, "range is only allowed "
|
||||
"for int or hex symbols");
|
||||
if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
|
||||
!menu_range_valid_sym(sym, prop->expr->right.sym))
|
||||
prop_warn(prop, "range is invalid");
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void menu_finalize(struct menu *parent)
|
||||
{
|
||||
struct menu *menu, *last_menu;
|
||||
struct symbol *sym;
|
||||
struct property *prop;
|
||||
struct expr *parentdep, *basedep, *dep, *dep2, **ep;
|
||||
|
||||
sym = parent->sym;
|
||||
if (parent->list) {
|
||||
if (sym && sym_is_choice(sym)) {
|
||||
/* find the first choice value and find out choice type */
|
||||
for (menu = parent->list; menu; menu = menu->next) {
|
||||
if (menu->sym) {
|
||||
current_entry = parent;
|
||||
if (sym->type == S_UNKNOWN)
|
||||
menu_set_type(menu->sym->type);
|
||||
current_entry = menu;
|
||||
if (menu->sym->type == S_UNKNOWN)
|
||||
menu_set_type(sym->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
parentdep = expr_alloc_symbol(sym);
|
||||
} else if (parent->prompt)
|
||||
parentdep = parent->prompt->visible.expr;
|
||||
else
|
||||
parentdep = parent->dep;
|
||||
|
||||
for (menu = parent->list; menu; menu = menu->next) {
|
||||
basedep = expr_transform(menu->dep);
|
||||
basedep = expr_alloc_and(expr_copy(parentdep), basedep);
|
||||
basedep = expr_eliminate_dups(basedep);
|
||||
menu->dep = basedep;
|
||||
if (menu->sym)
|
||||
prop = menu->sym->prop;
|
||||
else
|
||||
prop = menu->prompt;
|
||||
for (; prop; prop = prop->next) {
|
||||
if (prop->menu != menu)
|
||||
continue;
|
||||
dep = expr_transform(prop->visible.expr);
|
||||
dep = expr_alloc_and(expr_copy(basedep), dep);
|
||||
dep = expr_eliminate_dups(dep);
|
||||
if (menu->sym && menu->sym->type != S_TRISTATE)
|
||||
dep = expr_trans_bool(dep);
|
||||
prop->visible.expr = dep;
|
||||
if (prop->type == P_SELECT) {
|
||||
struct symbol *es = prop_get_symbol(prop);
|
||||
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
|
||||
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (menu = parent->list; menu; menu = menu->next)
|
||||
menu_finalize(menu);
|
||||
} else if (sym) {
|
||||
basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
|
||||
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
|
||||
basedep = expr_eliminate_dups(expr_transform(basedep));
|
||||
last_menu = NULL;
|
||||
for (menu = parent->next; menu; menu = menu->next) {
|
||||
dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
|
||||
if (!expr_contains_symbol(dep, sym))
|
||||
break;
|
||||
if (expr_depends_symbol(dep, sym))
|
||||
goto next;
|
||||
dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
|
||||
dep = expr_eliminate_dups(expr_transform(dep));
|
||||
dep2 = expr_copy(basedep);
|
||||
expr_eliminate_eq(&dep, &dep2);
|
||||
expr_free(dep);
|
||||
if (!expr_is_yes(dep2)) {
|
||||
expr_free(dep2);
|
||||
break;
|
||||
}
|
||||
expr_free(dep2);
|
||||
next:
|
||||
menu_finalize(menu);
|
||||
menu->parent = parent;
|
||||
last_menu = menu;
|
||||
}
|
||||
if (last_menu) {
|
||||
parent->list = parent->next;
|
||||
parent->next = last_menu->next;
|
||||
last_menu->next = NULL;
|
||||
}
|
||||
}
|
||||
for (menu = parent->list; menu; menu = menu->next) {
|
||||
if (sym && sym_is_choice(sym) && menu->sym) {
|
||||
menu->sym->flags |= SYMBOL_CHOICEVAL;
|
||||
if (!menu->prompt)
|
||||
menu_warn(menu, "choice value must have a prompt");
|
||||
for (prop = menu->sym->prop; prop; prop = prop->next) {
|
||||
if (prop->type == P_PROMPT && prop->menu != menu) {
|
||||
prop_warn(prop, "choice values "
|
||||
"currently only support a "
|
||||
"single prompt");
|
||||
}
|
||||
if (prop->type == P_DEFAULT)
|
||||
prop_warn(prop, "defaults for choice "
|
||||
"values not supported");
|
||||
}
|
||||
current_entry = menu;
|
||||
if (menu->sym->type == S_UNKNOWN)
|
||||
menu_set_type(sym->type);
|
||||
/* Non-tristate choice values of tristate choices must
|
||||
* depend on the choice being set to Y. The choice
|
||||
* values' dependencies were propagated to their
|
||||
* properties above, so the change here must be re-
|
||||
* propagated. */
|
||||
if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
|
||||
basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
|
||||
basedep = expr_alloc_and(basedep, menu->dep);
|
||||
basedep = expr_eliminate_dups(basedep);
|
||||
menu->dep = basedep;
|
||||
for (prop = menu->sym->prop; prop; prop = prop->next) {
|
||||
if (prop->menu != menu)
|
||||
continue;
|
||||
dep = expr_alloc_and(expr_copy(basedep),
|
||||
prop->visible.expr);
|
||||
dep = expr_eliminate_dups(dep);
|
||||
dep = expr_trans_bool(dep);
|
||||
prop->visible.expr = dep;
|
||||
if (prop->type == P_SELECT) {
|
||||
struct symbol *es = prop_get_symbol(prop);
|
||||
dep2 = expr_alloc_symbol(menu->sym);
|
||||
dep = expr_alloc_and(dep2,
|
||||
expr_copy(dep));
|
||||
dep = expr_alloc_or(es->rev_dep.expr, dep);
|
||||
dep = expr_eliminate_dups(dep);
|
||||
es->rev_dep.expr = dep;
|
||||
}
|
||||
}
|
||||
}
|
||||
menu_add_symbol(P_CHOICE, sym, NULL);
|
||||
prop = sym_get_choice_prop(sym);
|
||||
for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
|
||||
;
|
||||
*ep = expr_alloc_one(E_LIST, NULL);
|
||||
(*ep)->right.sym = menu->sym;
|
||||
}
|
||||
if (menu->list && (!menu->prompt || !menu->prompt->text)) {
|
||||
for (last_menu = menu->list; ; last_menu = last_menu->next) {
|
||||
last_menu->parent = parent;
|
||||
if (!last_menu->next)
|
||||
break;
|
||||
}
|
||||
last_menu->next = menu->next;
|
||||
menu->next = menu->list;
|
||||
menu->list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sym && !(sym->flags & SYMBOL_WARNED)) {
|
||||
if (sym->type == S_UNKNOWN)
|
||||
menu_warn(parent, "config symbol defined without type");
|
||||
|
||||
if (sym_is_choice(sym) && !parent->prompt)
|
||||
menu_warn(parent, "choice must have a prompt");
|
||||
|
||||
/* Check properties connected to this symbol */
|
||||
sym_check_prop(sym);
|
||||
sym->flags |= SYMBOL_WARNED;
|
||||
}
|
||||
|
||||
if (sym && !sym_is_optional(sym) && parent->prompt) {
|
||||
sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
|
||||
expr_alloc_and(parent->prompt->visible.expr,
|
||||
expr_alloc_symbol(&symbol_mod)));
|
||||
}
|
||||
}
|
||||
|
||||
bool menu_is_visible(struct menu *menu)
|
||||
{
|
||||
struct menu *child;
|
||||
struct symbol *sym;
|
||||
tristate visible;
|
||||
|
||||
if (!menu->prompt)
|
||||
return false;
|
||||
sym = menu->sym;
|
||||
if (sym) {
|
||||
sym_calc_value(sym);
|
||||
visible = menu->prompt->visible.tri;
|
||||
} else
|
||||
visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
|
||||
|
||||
if (visible != no)
|
||||
return true;
|
||||
if (!sym || sym_get_tristate_value(menu->sym) == no)
|
||||
return false;
|
||||
|
||||
for (child = menu->list; child; child = child->next)
|
||||
if (menu_is_visible(child))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *menu_get_prompt(struct menu *menu)
|
||||
{
|
||||
if (menu->prompt)
|
||||
return menu->prompt->text;
|
||||
else if (menu->sym)
|
||||
return menu->sym->name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct menu *menu_get_root_menu(struct menu *menu)
|
||||
{
|
||||
return &rootmenu;
|
||||
}
|
||||
|
||||
struct menu *menu_get_parent_menu(struct menu *menu)
|
||||
{
|
||||
enum prop_type type;
|
||||
|
||||
for (; menu != &rootmenu; menu = menu->parent) {
|
||||
type = menu->prompt ? menu->prompt->type : 0;
|
||||
if (type == P_MENU)
|
||||
break;
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
bool menu_has_help(struct menu *menu)
|
||||
{
|
||||
return menu->help != NULL;
|
||||
}
|
||||
|
||||
const char *menu_get_help(struct menu *menu)
|
||||
{
|
||||
if (menu->help)
|
||||
return menu->help;
|
||||
else
|
||||
return "";
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <qlistview.h>
|
||||
#if QT_VERSION >= 300
|
||||
#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
|
||||
|
||||
class ConfigView;
|
||||
class ConfigList;
|
||||
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);
|
||||
};
|
||||
|
||||
enum colIdx {
|
||||
promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
|
||||
};
|
||||
enum listMode {
|
||||
singleMode, menuMode, symbolMode, fullMode, listMode
|
||||
};
|
||||
|
||||
class ConfigList : public QListView {
|
||||
Q_OBJECT
|
||||
typedef class QListView Parent;
|
||||
public:
|
||||
ConfigList(ConfigView* p, const char *name = 0);
|
||||
void reinit(void);
|
||||
ConfigView* parent(void) const
|
||||
{
|
||||
return (ConfigView*)Parent::parent();
|
||||
}
|
||||
ConfigItem* findConfigItem(struct menu *);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void contentsMousePressEvent(QMouseEvent *e);
|
||||
void contentsMouseReleaseEvent(QMouseEvent *e);
|
||||
void contentsMouseMoveEvent(QMouseEvent *e);
|
||||
void contentsMouseDoubleClickEvent(QMouseEvent *e);
|
||||
void focusInEvent(QFocusEvent *e);
|
||||
void contextMenuEvent(QContextMenuEvent *e);
|
||||
|
||||
public slots:
|
||||
void setRootMenu(struct menu *menu);
|
||||
|
||||
void updateList(ConfigItem *item);
|
||||
void setValue(ConfigItem* item, tristate val);
|
||||
void changeValue(ConfigItem* item);
|
||||
void updateSelection(void);
|
||||
void saveSettings(void);
|
||||
signals:
|
||||
void menuChanged(struct menu *menu);
|
||||
void menuSelected(struct menu *menu);
|
||||
void parentSelected(void);
|
||||
void gotFocus(struct menu *);
|
||||
|
||||
public:
|
||||
void updateListAll(void)
|
||||
{
|
||||
updateAll = true;
|
||||
updateList(NULL);
|
||||
updateAll = false;
|
||||
}
|
||||
ConfigList* listView()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
ConfigItem* firstChild() const
|
||||
{
|
||||
return (ConfigItem *)Parent::firstChild();
|
||||
}
|
||||
int mapIdx(colIdx idx)
|
||||
{
|
||||
return colMap[idx];
|
||||
}
|
||||
void addColumn(colIdx idx, const QString& label)
|
||||
{
|
||||
colMap[idx] = Parent::addColumn(label);
|
||||
colRevMap[colMap[idx]] = idx;
|
||||
}
|
||||
void removeColumn(colIdx idx)
|
||||
{
|
||||
int col = colMap[idx];
|
||||
if (col >= 0) {
|
||||
Parent::removeColumn(col);
|
||||
colRevMap[col] = colMap[idx] = -1;
|
||||
}
|
||||
}
|
||||
void setAllOpen(bool open);
|
||||
void setParentMenu(void);
|
||||
|
||||
template <class P>
|
||||
void updateMenuList(P*, struct menu*);
|
||||
|
||||
bool updateAll;
|
||||
|
||||
QPixmap symbolYesPix, symbolModPix, symbolNoPix;
|
||||
QPixmap choiceYesPix, choiceNoPix;
|
||||
QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
|
||||
|
||||
bool showAll, showName, showRange, showData;
|
||||
enum listMode mode;
|
||||
struct menu *rootEntry;
|
||||
QColorGroup disabledColorGroup;
|
||||
QColorGroup inactivedColorGroup;
|
||||
QPopupMenu* headerPopup;
|
||||
|
||||
private:
|
||||
int colMap[colNr];
|
||||
int colRevMap[colNr];
|
||||
};
|
||||
|
||||
class ConfigItem : public QListViewItem {
|
||||
typedef class QListViewItem Parent;
|
||||
public:
|
||||
ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v)
|
||||
: Parent(parent, after), menu(m), visible(v), goParent(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
|
||||
: Parent(parent, after), menu(m), visible(v), goParent(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
ConfigItem(QListView *parent, ConfigItem *after, bool v)
|
||||
: Parent(parent, after), 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();
|
||||
}
|
||||
ConfigItem* firstChild() const
|
||||
{
|
||||
return (ConfigItem *)Parent::firstChild();
|
||||
}
|
||||
ConfigItem* nextSibling() const
|
||||
{
|
||||
return (ConfigItem *)Parent::nextSibling();
|
||||
}
|
||||
void setText(colIdx idx, const QString& text)
|
||||
{
|
||||
Parent::setText(listView()->mapIdx(idx), text);
|
||||
}
|
||||
QString text(colIdx idx) const
|
||||
{
|
||||
return Parent::text(listView()->mapIdx(idx));
|
||||
}
|
||||
void setPixmap(colIdx idx, const QPixmap& pm)
|
||||
{
|
||||
Parent::setPixmap(listView()->mapIdx(idx), pm);
|
||||
}
|
||||
const QPixmap* pixmap(colIdx idx) const
|
||||
{
|
||||
return Parent::pixmap(listView()->mapIdx(idx));
|
||||
}
|
||||
void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
|
||||
|
||||
ConfigItem* nextItem;
|
||||
struct menu *menu;
|
||||
bool visible;
|
||||
bool goParent;
|
||||
};
|
||||
|
||||
class ConfigLineEdit : public QLineEdit {
|
||||
Q_OBJECT
|
||||
typedef class QLineEdit Parent;
|
||||
public:
|
||||
ConfigLineEdit(ConfigView* parent);
|
||||
ConfigView* parent(void) const
|
||||
{
|
||||
return (ConfigView*)Parent::parent();
|
||||
}
|
||||
void show(ConfigItem *i);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
|
||||
public:
|
||||
ConfigItem *item;
|
||||
};
|
||||
|
||||
class ConfigView : public QVBox {
|
||||
Q_OBJECT
|
||||
typedef class QVBox 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);
|
||||
signals:
|
||||
void showAllChanged(bool);
|
||||
void showNameChanged(bool);
|
||||
void showRangeChanged(bool);
|
||||
void showDataChanged(bool);
|
||||
public:
|
||||
ConfigList* list;
|
||||
ConfigLineEdit* lineEdit;
|
||||
|
||||
static ConfigView* viewList;
|
||||
ConfigView* nextView;
|
||||
};
|
||||
|
||||
class ConfigInfoView : public QTextBrowser {
|
||||
Q_OBJECT
|
||||
typedef class QTextBrowser Parent;
|
||||
public:
|
||||
ConfigInfoView(QWidget* parent, const char *name = 0);
|
||||
bool showDebug(void) const { return _showDebug; }
|
||||
|
||||
public slots:
|
||||
void setInfo(struct menu *menu);
|
||||
void saveSettings(void);
|
||||
void setSource(const QString& name);
|
||||
void setShowDebug(bool);
|
||||
|
||||
signals:
|
||||
void showDebugChanged(bool);
|
||||
void menuSelected(struct menu *);
|
||||
|
||||
protected:
|
||||
void symbolInfo(void);
|
||||
void menuInfo(void);
|
||||
QString debug_info(struct symbol *sym);
|
||||
static QString print_filter(const QString &str);
|
||||
static void expr_print_help(void *data, struct symbol *sym, const char *str);
|
||||
QPopupMenu* createPopupMenu(const QPoint& pos);
|
||||
void contentsContextMenuEvent(QContextMenuEvent *e);
|
||||
|
||||
struct symbol *sym;
|
||||
struct menu *menu;
|
||||
bool _showDebug;
|
||||
};
|
||||
|
||||
class ConfigSearchWindow : public QDialog {
|
||||
Q_OBJECT
|
||||
typedef class QDialog Parent;
|
||||
public:
|
||||
ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0);
|
||||
|
||||
public slots:
|
||||
void saveSettings(void);
|
||||
void search(void);
|
||||
|
||||
protected:
|
||||
QLineEdit* editField;
|
||||
QPushButton* searchButton;
|
||||
QSplitter* split;
|
||||
ConfigView* list;
|
||||
ConfigInfoView* info;
|
||||
|
||||
struct symbol **result;
|
||||
};
|
||||
|
||||
class ConfigMainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
static QAction *saveAction;
|
||||
static void conf_changed(void);
|
||||
public:
|
||||
ConfigMainWindow(void);
|
||||
public slots:
|
||||
void changeMenu(struct menu *);
|
||||
void setMenuLink(struct menu *);
|
||||
void listFocusChanged(void);
|
||||
void goBack(void);
|
||||
void loadConfig(void);
|
||||
void saveConfig(void);
|
||||
void saveConfigAs(void);
|
||||
void searchConfig(void);
|
||||
void showSingleView(void);
|
||||
void showSplitView(void);
|
||||
void showFullView(void);
|
||||
void showIntro(void);
|
||||
void showAbout(void);
|
||||
void saveSettings(void);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *e);
|
||||
|
||||
ConfigSearchWindow *searchWindow;
|
||||
ConfigView *menuView;
|
||||
ConfigList *menuList;
|
||||
ConfigView *configView;
|
||||
ConfigList *configList;
|
||||
ConfigInfoView *helpText;
|
||||
QToolBar *toolBar;
|
||||
QAction *backAction;
|
||||
QSplitter* split1;
|
||||
QSplitter* split2;
|
||||
};
|
|
@ -0,0 +1,917 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define LKC_DIRECT_LINK
|
||||
#include "lkc.h"
|
||||
|
||||
struct symbol symbol_yes = {
|
||||
.name = "y",
|
||||
.curr = { "y", yes },
|
||||
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
||||
}, symbol_mod = {
|
||||
.name = "m",
|
||||
.curr = { "m", mod },
|
||||
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
||||
}, symbol_no = {
|
||||
.name = "n",
|
||||
.curr = { "n", no },
|
||||
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
||||
}, symbol_empty = {
|
||||
.name = "",
|
||||
.curr = { "", no },
|
||||
.flags = SYMBOL_VALID,
|
||||
};
|
||||
|
||||
struct symbol *sym_defconfig_list;
|
||||
struct symbol *modules_sym;
|
||||
tristate modules_val;
|
||||
|
||||
struct expr *sym_env_list;
|
||||
|
||||
void sym_add_default(struct symbol *sym, const char *def)
|
||||
{
|
||||
struct property *prop = prop_alloc(P_DEFAULT, sym);
|
||||
|
||||
prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
|
||||
}
|
||||
|
||||
void sym_init(void)
|
||||
{
|
||||
struct symbol *sym;
|
||||
struct utsname uts;
|
||||
static bool inited = false;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = true;
|
||||
|
||||
uname(&uts);
|
||||
|
||||
sym = sym_lookup("UNAME_RELEASE", 0);
|
||||
sym->type = S_STRING;
|
||||
sym->flags |= SYMBOL_AUTO;
|
||||
sym_add_default(sym, uts.release);
|
||||
}
|
||||
|
||||
enum symbol_type sym_get_type(struct symbol *sym)
|
||||
{
|
||||
enum symbol_type type = sym->type;
|
||||
|
||||
if (type == S_TRISTATE) {
|
||||
if (sym_is_choice_value(sym) && sym->visible == yes)
|
||||
type = S_BOOLEAN;
|
||||
else if (modules_val == no)
|
||||
type = S_BOOLEAN;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
const char *sym_type_name(enum symbol_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
return "boolean";
|
||||
case S_TRISTATE:
|
||||
return "tristate";
|
||||
case S_INT:
|
||||
return "integer";
|
||||
case S_HEX:
|
||||
return "hex";
|
||||
case S_STRING:
|
||||
return "string";
|
||||
case S_UNKNOWN:
|
||||
return "unknown";
|
||||
case S_OTHER:
|
||||
break;
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
|
||||
struct property *sym_get_choice_prop(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
|
||||
for_all_choices(sym, prop)
|
||||
return prop;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct property *sym_get_env_prop(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
|
||||
for_all_properties(sym, prop, P_ENV)
|
||||
return prop;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct property *sym_get_default_prop(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
|
||||
for_all_defaults(sym, prop) {
|
||||
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
||||
if (prop->visible.tri != no)
|
||||
return prop;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct property *sym_get_range_prop(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
|
||||
for_all_properties(sym, prop, P_RANGE) {
|
||||
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
||||
if (prop->visible.tri != no)
|
||||
return prop;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int sym_get_range_val(struct symbol *sym, int base)
|
||||
{
|
||||
sym_calc_value(sym);
|
||||
switch (sym->type) {
|
||||
case S_INT:
|
||||
base = 10;
|
||||
break;
|
||||
case S_HEX:
|
||||
base = 16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return strtol(sym->curr.val, NULL, base);
|
||||
}
|
||||
|
||||
static void sym_validate_range(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
int base, val, val2;
|
||||
char str[64];
|
||||
|
||||
switch (sym->type) {
|
||||
case S_INT:
|
||||
base = 10;
|
||||
break;
|
||||
case S_HEX:
|
||||
base = 16;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
prop = sym_get_range_prop(sym);
|
||||
if (!prop)
|
||||
return;
|
||||
val = strtol(sym->curr.val, NULL, base);
|
||||
val2 = sym_get_range_val(prop->expr->left.sym, base);
|
||||
if (val >= val2) {
|
||||
val2 = sym_get_range_val(prop->expr->right.sym, base);
|
||||
if (val <= val2)
|
||||
return;
|
||||
}
|
||||
if (sym->type == S_INT)
|
||||
sprintf(str, "%d", val2);
|
||||
else
|
||||
sprintf(str, "0x%x", val2);
|
||||
sym->curr.val = strdup(str);
|
||||
}
|
||||
|
||||
static void sym_calc_visibility(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
tristate tri;
|
||||
|
||||
/* any prompt visible? */
|
||||
tri = no;
|
||||
for_all_prompts(sym, prop) {
|
||||
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
||||
tri = EXPR_OR(tri, prop->visible.tri);
|
||||
}
|
||||
if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
|
||||
tri = yes;
|
||||
if (sym->visible != tri) {
|
||||
sym->visible = tri;
|
||||
sym_set_changed(sym);
|
||||
}
|
||||
if (sym_is_choice_value(sym))
|
||||
return;
|
||||
tri = no;
|
||||
if (sym->rev_dep.expr)
|
||||
tri = expr_calc_value(sym->rev_dep.expr);
|
||||
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
||||
tri = yes;
|
||||
if (sym->rev_dep.tri != tri) {
|
||||
sym->rev_dep.tri = tri;
|
||||
sym_set_changed(sym);
|
||||
}
|
||||
}
|
||||
|
||||
static struct symbol *sym_calc_choice(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) {
|
||||
sym_calc_visibility(def_sym);
|
||||
if (def_sym->visible != no)
|
||||
return def_sym;
|
||||
}
|
||||
|
||||
/* no choice? reset tristate value */
|
||||
sym->curr.tri = no;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sym_calc_value(struct symbol *sym)
|
||||
{
|
||||
struct symbol_value newval, oldval;
|
||||
struct property *prop;
|
||||
struct expr *e;
|
||||
|
||||
if (!sym)
|
||||
return;
|
||||
|
||||
if (sym->flags & SYMBOL_VALID)
|
||||
return;
|
||||
sym->flags |= SYMBOL_VALID;
|
||||
|
||||
oldval = sym->curr;
|
||||
|
||||
switch (sym->type) {
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
case S_STRING:
|
||||
newval = symbol_empty.curr;
|
||||
break;
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
newval = symbol_no.curr;
|
||||
break;
|
||||
default:
|
||||
sym->curr.val = sym->name;
|
||||
sym->curr.tri = no;
|
||||
return;
|
||||
}
|
||||
if (!sym_is_choice_value(sym))
|
||||
sym->flags &= ~SYMBOL_WRITE;
|
||||
|
||||
sym_calc_visibility(sym);
|
||||
|
||||
/* set default if recursively called */
|
||||
sym->curr = newval;
|
||||
|
||||
switch (sym_get_type(sym)) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
if (sym_is_choice_value(sym) && sym->visible == yes) {
|
||||
prop = sym_get_choice_prop(sym);
|
||||
newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
|
||||
} else {
|
||||
if (sym->visible != no) {
|
||||
/* if the symbol is visible use the user value
|
||||
* if available, otherwise try the default value
|
||||
*/
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
if (sym_has_value(sym)) {
|
||||
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
|
||||
sym->visible);
|
||||
goto calc_newval;
|
||||
}
|
||||
}
|
||||
if (sym->rev_dep.tri != no)
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
if (!sym_is_choice(sym)) {
|
||||
prop = sym_get_default_prop(sym);
|
||||
if (prop) {
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
newval.tri = EXPR_AND(expr_calc_value(prop->expr),
|
||||
prop->visible.tri);
|
||||
}
|
||||
}
|
||||
calc_newval:
|
||||
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
|
||||
}
|
||||
if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
||||
newval.tri = yes;
|
||||
break;
|
||||
case S_STRING:
|
||||
case S_HEX:
|
||||
case S_INT:
|
||||
if (sym->visible != no) {
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
if (sym_has_value(sym)) {
|
||||
newval.val = sym->def[S_DEF_USER].val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop = sym_get_default_prop(sym);
|
||||
if (prop) {
|
||||
struct symbol *ds = prop_get_symbol(prop);
|
||||
if (ds) {
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
sym_calc_value(ds);
|
||||
newval.val = ds->curr.val;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if (sym->flags & SYMBOL_AUTO)
|
||||
sym->flags &= ~SYMBOL_WRITE;
|
||||
|
||||
sym->curr = newval;
|
||||
if (sym_is_choice(sym) && newval.tri == yes)
|
||||
sym->curr.val = sym_calc_choice(sym);
|
||||
sym_validate_range(sym);
|
||||
|
||||
if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
|
||||
sym_set_changed(sym);
|
||||
if (modules_sym == sym) {
|
||||
sym_set_all_changed();
|
||||
modules_val = modules_sym->curr.tri;
|
||||
}
|
||||
}
|
||||
|
||||
if (sym_is_choice(sym)) {
|
||||
struct symbol *choice_sym;
|
||||
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)
|
||||
sym_set_changed(choice_sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sym_clear_all_valid(void)
|
||||
{
|
||||
struct symbol *sym;
|
||||
int i;
|
||||
|
||||
for_all_symbols(i, sym)
|
||||
sym->flags &= ~SYMBOL_VALID;
|
||||
sym_add_change_count(1);
|
||||
if (modules_sym)
|
||||
sym_calc_value(modules_sym);
|
||||
}
|
||||
|
||||
void sym_set_changed(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
|
||||
sym->flags |= SYMBOL_CHANGED;
|
||||
for (prop = sym->prop; prop; prop = prop->next) {
|
||||
if (prop->menu)
|
||||
prop->menu->flags |= MENU_CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
void sym_set_all_changed(void)
|
||||
{
|
||||
struct symbol *sym;
|
||||
int i;
|
||||
|
||||
for_all_symbols(i, sym)
|
||||
sym_set_changed(sym);
|
||||
}
|
||||
|
||||
bool sym_tristate_within_range(struct symbol *sym, tristate val)
|
||||
{
|
||||
int type = sym_get_type(sym);
|
||||
|
||||
if (sym->visible == no)
|
||||
return false;
|
||||
|
||||
if (type != S_BOOLEAN && type != S_TRISTATE)
|
||||
return false;
|
||||
|
||||
if (type == S_BOOLEAN && val == mod)
|
||||
return false;
|
||||
if (sym->visible <= sym->rev_dep.tri)
|
||||
return false;
|
||||
if (sym_is_choice_value(sym) && sym->visible == yes)
|
||||
return val == yes;
|
||||
return val >= sym->rev_dep.tri && val <= sym->visible;
|
||||
}
|
||||
|
||||
bool sym_set_tristate_value(struct symbol *sym, tristate val)
|
||||
{
|
||||
tristate oldval = sym_get_tristate_value(sym);
|
||||
|
||||
if (oldval != val && !sym_tristate_within_range(sym, val))
|
||||
return false;
|
||||
|
||||
if (!(sym->flags & SYMBOL_DEF_USER)) {
|
||||
sym->flags |= SYMBOL_DEF_USER;
|
||||
sym_set_changed(sym);
|
||||
}
|
||||
/*
|
||||
* setting a choice value also resets the new flag of the choice
|
||||
* symbol and all other choice values.
|
||||
*/
|
||||
if (sym_is_choice_value(sym) && val == yes) {
|
||||
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
|
||||
struct property *prop;
|
||||
struct expr *e;
|
||||
|
||||
cs->def[S_DEF_USER].val = sym;
|
||||
cs->flags |= SYMBOL_DEF_USER;
|
||||
prop = sym_get_choice_prop(cs);
|
||||
for (e = prop->expr; e; e = e->left.expr) {
|
||||
if (e->right.sym->visible != no)
|
||||
e->right.sym->flags |= SYMBOL_DEF_USER;
|
||||
}
|
||||
}
|
||||
|
||||
sym->def[S_DEF_USER].tri = val;
|
||||
if (oldval != val)
|
||||
sym_clear_all_valid();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
tristate sym_toggle_tristate_value(struct symbol *sym)
|
||||
{
|
||||
tristate oldval, newval;
|
||||
|
||||
oldval = newval = sym_get_tristate_value(sym);
|
||||
do {
|
||||
switch (newval) {
|
||||
case no:
|
||||
newval = mod;
|
||||
break;
|
||||
case mod:
|
||||
newval = yes;
|
||||
break;
|
||||
case yes:
|
||||
newval = no;
|
||||
break;
|
||||
}
|
||||
if (sym_set_tristate_value(sym, newval))
|
||||
break;
|
||||
} while (oldval != newval);
|
||||
return newval;
|
||||
}
|
||||
|
||||
bool sym_string_valid(struct symbol *sym, const char *str)
|
||||
{
|
||||
signed char ch;
|
||||
|
||||
switch (sym->type) {
|
||||
case S_STRING:
|
||||
return true;
|
||||
case S_INT:
|
||||
ch = *str++;
|
||||
if (ch == '-')
|
||||
ch = *str++;
|
||||
if (!isdigit(ch))
|
||||
return false;
|
||||
if (ch == '0' && *str != 0)
|
||||
return false;
|
||||
while ((ch = *str++)) {
|
||||
if (!isdigit(ch))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case S_HEX:
|
||||
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
|
||||
str += 2;
|
||||
ch = *str++;
|
||||
do {
|
||||
if (!isxdigit(ch))
|
||||
return false;
|
||||
} while ((ch = *str++));
|
||||
return true;
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
switch (str[0]) {
|
||||
case 'y': case 'Y':
|
||||
case 'm': case 'M':
|
||||
case 'n': case 'N':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool sym_string_within_range(struct symbol *sym, const char *str)
|
||||
{
|
||||
struct property *prop;
|
||||
int val;
|
||||
|
||||
switch (sym->type) {
|
||||
case S_STRING:
|
||||
return sym_string_valid(sym, str);
|
||||
case S_INT:
|
||||
if (!sym_string_valid(sym, str))
|
||||
return false;
|
||||
prop = sym_get_range_prop(sym);
|
||||
if (!prop)
|
||||
return true;
|
||||
val = strtol(str, NULL, 10);
|
||||
return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
|
||||
val <= sym_get_range_val(prop->expr->right.sym, 10);
|
||||
case S_HEX:
|
||||
if (!sym_string_valid(sym, str))
|
||||
return false;
|
||||
prop = sym_get_range_prop(sym);
|
||||
if (!prop)
|
||||
return true;
|
||||
val = strtol(str, NULL, 16);
|
||||
return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
|
||||
val <= sym_get_range_val(prop->expr->right.sym, 16);
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
switch (str[0]) {
|
||||
case 'y': case 'Y':
|
||||
return sym_tristate_within_range(sym, yes);
|
||||
case 'm': case 'M':
|
||||
return sym_tristate_within_range(sym, mod);
|
||||
case 'n': case 'N':
|
||||
return sym_tristate_within_range(sym, no);
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool sym_set_string_value(struct symbol *sym, const char *newval)
|
||||
{
|
||||
const char *oldval;
|
||||
char *val;
|
||||
int size;
|
||||
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
switch (newval[0]) {
|
||||
case 'y': case 'Y':
|
||||
return sym_set_tristate_value(sym, yes);
|
||||
case 'm': case 'M':
|
||||
return sym_set_tristate_value(sym, mod);
|
||||
case 'n': case 'N':
|
||||
return sym_set_tristate_value(sym, no);
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if (!sym_string_within_range(sym, newval))
|
||||
return false;
|
||||
|
||||
if (!(sym->flags & SYMBOL_DEF_USER)) {
|
||||
sym->flags |= SYMBOL_DEF_USER;
|
||||
sym_set_changed(sym);
|
||||
}
|
||||
|
||||
oldval = sym->def[S_DEF_USER].val;
|
||||
size = strlen(newval) + 1;
|
||||
if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
|
||||
size += 2;
|
||||
sym->def[S_DEF_USER].val = val = malloc(size);
|
||||
*val++ = '0';
|
||||
*val++ = 'x';
|
||||
} else if (!oldval || strcmp(oldval, newval))
|
||||
sym->def[S_DEF_USER].val = val = malloc(size);
|
||||
else
|
||||
return true;
|
||||
|
||||
strcpy(val, newval);
|
||||
free((void *)oldval);
|
||||
sym_clear_all_valid();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *sym_get_string_value(struct symbol *sym)
|
||||
{
|
||||
tristate val;
|
||||
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
val = sym_get_tristate_value(sym);
|
||||
switch (val) {
|
||||
case no:
|
||||
return "n";
|
||||
case mod:
|
||||
return "m";
|
||||
case yes:
|
||||
return "y";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
return (const char *)sym->curr.val;
|
||||
}
|
||||
|
||||
bool sym_is_changable(struct symbol *sym)
|
||||
{
|
||||
return sym->visible > sym->rev_dep.tri;
|
||||
}
|
||||
|
||||
struct symbol *sym_lookup(const char *name, int isconst)
|
||||
{
|
||||
struct symbol *symbol;
|
||||
const char *ptr;
|
||||
char *new_name;
|
||||
int hash = 0;
|
||||
|
||||
if (name) {
|
||||
if (name[0] && !name[1]) {
|
||||
switch (name[0]) {
|
||||
case 'y': return &symbol_yes;
|
||||
case 'm': return &symbol_mod;
|
||||
case 'n': return &symbol_no;
|
||||
}
|
||||
}
|
||||
for (ptr = name; *ptr; ptr++)
|
||||
hash += *ptr;
|
||||
hash &= 0xff;
|
||||
|
||||
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
|
||||
if (!strcmp(symbol->name, name)) {
|
||||
if ((isconst && symbol->flags & SYMBOL_CONST) ||
|
||||
(!isconst && !(symbol->flags & SYMBOL_CONST)))
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
new_name = strdup(name);
|
||||
} else {
|
||||
new_name = NULL;
|
||||
hash = 256;
|
||||
}
|
||||
|
||||
symbol = malloc(sizeof(*symbol));
|
||||
memset(symbol, 0, sizeof(*symbol));
|
||||
symbol->name = new_name;
|
||||
symbol->type = S_UNKNOWN;
|
||||
if (isconst)
|
||||
symbol->flags |= SYMBOL_CONST;
|
||||
|
||||
symbol->next = symbol_hash[hash];
|
||||
symbol_hash[hash] = symbol;
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
struct symbol *sym_find(const char *name)
|
||||
{
|
||||
struct symbol *symbol = NULL;
|
||||
const char *ptr;
|
||||
int hash = 0;
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
if (name[0] && !name[1]) {
|
||||
switch (name[0]) {
|
||||
case 'y': return &symbol_yes;
|
||||
case 'm': return &symbol_mod;
|
||||
case 'n': return &symbol_no;
|
||||
}
|
||||
}
|
||||
for (ptr = name; *ptr; ptr++)
|
||||
hash += *ptr;
|
||||
hash &= 0xff;
|
||||
|
||||
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
|
||||
if (!strcmp(symbol->name, name) &&
|
||||
!(symbol->flags & SYMBOL_CONST))
|
||||
break;
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
struct symbol **sym_re_search(const char *pattern)
|
||||
{
|
||||
struct symbol *sym, **sym_arr = NULL;
|
||||
int i, cnt, size;
|
||||
regex_t re;
|
||||
|
||||
cnt = size = 0;
|
||||
/* Skip if empty */
|
||||
if (strlen(pattern) == 0)
|
||||
return NULL;
|
||||
if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
|
||||
return NULL;
|
||||
|
||||
for_all_symbols(i, sym) {
|
||||
if (sym->flags & SYMBOL_CONST || !sym->name)
|
||||
continue;
|
||||
if (regexec(&re, sym->name, 0, NULL, 0))
|
||||
continue;
|
||||
if (cnt + 1 >= size) {
|
||||
void *tmp = sym_arr;
|
||||
size += 16;
|
||||
sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
|
||||
if (!sym_arr) {
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
sym_arr[cnt++] = sym;
|
||||
}
|
||||
if (sym_arr)
|
||||
sym_arr[cnt] = NULL;
|
||||
regfree(&re);
|
||||
|
||||
return sym_arr;
|
||||
}
|
||||
|
||||
|
||||
struct symbol *sym_check_deps(struct symbol *sym);
|
||||
|
||||
static struct symbol *sym_check_expr_deps(struct expr *e)
|
||||
{
|
||||
struct symbol *sym;
|
||||
|
||||
if (!e)
|
||||
return NULL;
|
||||
switch (e->type) {
|
||||
case E_OR:
|
||||
case E_AND:
|
||||
sym = sym_check_expr_deps(e->left.expr);
|
||||
if (sym)
|
||||
return sym;
|
||||
return sym_check_expr_deps(e->right.expr);
|
||||
case E_NOT:
|
||||
return sym_check_expr_deps(e->left.expr);
|
||||
case E_EQUAL:
|
||||
case E_UNEQUAL:
|
||||
sym = sym_check_deps(e->left.sym);
|
||||
if (sym)
|
||||
return sym;
|
||||
return sym_check_deps(e->right.sym);
|
||||
case E_SYMBOL:
|
||||
return sym_check_deps(e->left.sym);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("Oops! How to check %d?\n", e->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* return NULL when dependencies are OK */
|
||||
struct symbol *sym_check_deps(struct symbol *sym)
|
||||
{
|
||||
struct symbol *sym2;
|
||||
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);
|
||||
return sym;
|
||||
}
|
||||
if (sym->flags & SYMBOL_CHECKED)
|
||||
return NULL;
|
||||
|
||||
sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
|
||||
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
|
||||
if (sym2)
|
||||
goto out;
|
||||
|
||||
for (prop = sym->prop; prop; prop = prop->next) {
|
||||
if (prop->type == P_CHOICE || prop->type == P_SELECT)
|
||||
continue;
|
||||
sym2 = sym_check_expr_deps(prop->visible.expr);
|
||||
if (sym2)
|
||||
goto out;
|
||||
if (prop->type != P_DEFAULT || sym_is_choice(sym))
|
||||
continue;
|
||||
sym2 = sym_check_expr_deps(prop->expr);
|
||||
if (sym2)
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (sym2)
|
||||
fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": "");
|
||||
sym->flags &= ~SYMBOL_CHECK;
|
||||
return sym2;
|
||||
}
|
||||
|
||||
struct property *prop_alloc(enum prop_type type, struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
struct property **propp;
|
||||
|
||||
prop = malloc(sizeof(*prop));
|
||||
memset(prop, 0, sizeof(*prop));
|
||||
prop->type = type;
|
||||
prop->sym = sym;
|
||||
prop->file = current_file;
|
||||
prop->lineno = zconf_lineno();
|
||||
|
||||
/* append property to the prop list of symbol */
|
||||
if (sym) {
|
||||
for (propp = &sym->prop; *propp; propp = &(*propp)->next)
|
||||
;
|
||||
*propp = prop;
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
struct symbol *prop_get_symbol(struct property *prop)
|
||||
{
|
||||
if (prop->expr && (prop->expr->type == E_SYMBOL ||
|
||||
prop->expr->type == E_LIST))
|
||||
return prop->expr->left.sym;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *prop_get_type_name(enum prop_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case P_PROMPT:
|
||||
return "prompt";
|
||||
case P_ENV:
|
||||
return "env";
|
||||
case P_COMMENT:
|
||||
return "comment";
|
||||
case P_MENU:
|
||||
return "menu";
|
||||
case P_DEFAULT:
|
||||
return "default";
|
||||
case P_CHOICE:
|
||||
return "choice";
|
||||
case P_SELECT:
|
||||
return "select";
|
||||
case P_RANGE:
|
||||
return "range";
|
||||
case P_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void prop_add_env(const char *env)
|
||||
{
|
||||
struct symbol *sym, *sym2;
|
||||
struct property *prop;
|
||||
char *p;
|
||||
|
||||
sym = current_entry->sym;
|
||||
sym->flags |= SYMBOL_AUTO;
|
||||
for_all_properties(sym, prop, P_ENV) {
|
||||
sym2 = prop_get_symbol(prop);
|
||||
if (strcmp(sym2->name, env))
|
||||
menu_warn(current_entry, "redefining environment symbol from %s",
|
||||
sym2->name);
|
||||
return;
|
||||
}
|
||||
|
||||
prop = prop_alloc(P_ENV, sym);
|
||||
prop->expr = expr_alloc_symbol(sym_lookup(env, 1));
|
||||
|
||||
sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
|
||||
sym_env_list->right.sym = sym;
|
||||
|
||||
p = getenv(env);
|
||||
if (p)
|
||||
sym_add_default(sym, p);
|
||||
else
|
||||
menu_warn(current_entry, "environment variable %s undefined", env);
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
|
||||
*
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "lkc.h"
|
||||
|
||||
/* file already present in list? If not add it */
|
||||
struct file *file_lookup(const char *name)
|
||||
{
|
||||
struct file *file;
|
||||
|
||||
for (file = file_list; file; file = file->next) {
|
||||
if (!strcmp(name, file->name))
|
||||
return file;
|
||||
}
|
||||
|
||||
file = malloc(sizeof(*file));
|
||||
memset(file, 0, sizeof(*file));
|
||||
file->name = strdup(name);
|
||||
file->next = file_list;
|
||||
file_list = file;
|
||||
return file;
|
||||
}
|
||||
|
||||
/* write a dependency file as used by kbuild to track dependencies */
|
||||
int file_write_dep(const char *name)
|
||||
{
|
||||
struct symbol *sym, *env_sym;
|
||||
struct expr *e;
|
||||
struct file *file;
|
||||
FILE *out;
|
||||
|
||||
if (!name)
|
||||
name = ".kconfig.d";
|
||||
out = fopen("..config.tmp", "w");
|
||||
if (!out)
|
||||
return 1;
|
||||
fprintf(out, "deps_config := \\\n");
|
||||
for (file = file_list; file; file = file->next) {
|
||||
if (file->next)
|
||||
fprintf(out, "\t%s \\\n", file->name);
|
||||
else
|
||||
fprintf(out, "\t%s\n", file->name);
|
||||
}
|
||||
fprintf(out, "\nbuild/auto.conf: \\\n"
|
||||
"\t$(deps_config)\n\n");
|
||||
|
||||
expr_list_for_each_sym(sym_env_list, e, sym) {
|
||||
struct property *prop;
|
||||
const char *value;
|
||||
|
||||
prop = sym_get_env_prop(sym);
|
||||
env_sym = prop_get_symbol(prop);
|
||||
if (!env_sym)
|
||||
continue;
|
||||
value = getenv(env_sym->name);
|
||||
if (!value)
|
||||
value = "";
|
||||
fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value);
|
||||
fprintf(out, "build/auto.conf: FORCE\n");
|
||||
fprintf(out, "endif\n");
|
||||
}
|
||||
|
||||
fprintf(out, "\n$(deps_config): ;\n");
|
||||
fclose(out);
|
||||
rename("..config.tmp", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate initial growable sting */
|
||||
struct gstr str_new(void)
|
||||
{
|
||||
struct gstr gs;
|
||||
gs.s = malloc(sizeof(char) * 64);
|
||||
gs.len = 16;
|
||||
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)
|
||||
{
|
||||
if (gs->s)
|
||||
free(gs->s);
|
||||
gs->s = NULL;
|
||||
gs->len = 0;
|
||||
}
|
||||
|
||||
/* Append to growable string */
|
||||
void str_append(struct gstr *gs, const char *s)
|
||||
{
|
||||
size_t l;
|
||||
if (s) {
|
||||
l = strlen(gs->s) + strlen(s) + 1;
|
||||
if (l > gs->len) {
|
||||
gs->s = realloc(gs->s, l);
|
||||
gs->len = l;
|
||||
}
|
||||
strcat(gs->s, s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Append printf formatted string to growable string */
|
||||
void str_printf(struct gstr *gs, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char s[10000]; /* big enough... */
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(s, sizeof(s), fmt, ap);
|
||||
str_append(gs, s);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Retrieve value of growable string */
|
||||
const char *str_get(struct gstr *gs)
|
||||
{
|
||||
return gs->s;
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
%language=ANSI-C
|
||||
%define hash-function-name kconf_id_hash
|
||||
%define lookup-function-name kconf_id_lookup
|
||||
%define string-pool-name kconf_id_strings
|
||||
%compare-strncmp
|
||||
%enum
|
||||
%pic
|
||||
%struct-type
|
||||
|
||||
struct kconf_id;
|
||||
|
||||
%%
|
||||
mainmenu, T_MAINMENU, TF_COMMAND
|
||||
menu, T_MENU, TF_COMMAND
|
||||
endmenu, T_ENDMENU, TF_COMMAND
|
||||
source, T_SOURCE, TF_COMMAND
|
||||
choice, T_CHOICE, TF_COMMAND
|
||||
endchoice, T_ENDCHOICE, TF_COMMAND
|
||||
comment, T_COMMENT, TF_COMMAND
|
||||
config, T_CONFIG, TF_COMMAND
|
||||
menuconfig, T_MENUCONFIG, TF_COMMAND
|
||||
help, T_HELP, TF_COMMAND
|
||||
if, T_IF, TF_COMMAND|TF_PARAM
|
||||
endif, T_ENDIF, TF_COMMAND
|
||||
depends, T_DEPENDS, TF_COMMAND
|
||||
optional, T_OPTIONAL, TF_COMMAND
|
||||
default, T_DEFAULT, TF_COMMAND, S_UNKNOWN
|
||||
prompt, T_PROMPT, TF_COMMAND
|
||||
tristate, T_TYPE, TF_COMMAND, S_TRISTATE
|
||||
def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE
|
||||
bool, T_TYPE, TF_COMMAND, S_BOOLEAN
|
||||
boolean, T_TYPE, TF_COMMAND, S_BOOLEAN
|
||||
def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN
|
||||
int, T_TYPE, TF_COMMAND, S_INT
|
||||
hex, T_TYPE, TF_COMMAND, S_HEX
|
||||
string, T_TYPE, TF_COMMAND, S_STRING
|
||||
select, T_SELECT, TF_COMMAND
|
||||
range, T_RANGE, TF_COMMAND
|
||||
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
|
||||
%%
|
|
@ -0,0 +1,237 @@
|
|||
/* ANSI-C code produced by gperf version 3.0.3 */
|
||||
/* Command-line: gperf */
|
||||
/* Computed positions: -k'1,3' */
|
||||
|
||||
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
||||
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
|
||||
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
|
||||
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
|
||||
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
|
||||
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
|
||||
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
|
||||
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
|
||||
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
|
||||
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
|
||||
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
|
||||
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
|
||||
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
|
||||
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
|
||||
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
|
||||
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
|
||||
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
|
||||
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
|
||||
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
|
||||
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
|
||||
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
|
||||
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
|
||||
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
|
||||
/* The character set is not based on ISO-646. */
|
||||
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
|
||||
#endif
|
||||
|
||||
struct kconf_id;
|
||||
/* maximum key range = 47, duplicates = 0 */
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static unsigned int
|
||||
kconf_id_hash (register const char *str, register unsigned int len)
|
||||
{
|
||||
static 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
|
||||
};
|
||||
register int hval = len;
|
||||
|
||||
switch (hval)
|
||||
{
|
||||
default:
|
||||
hval += asso_values[(unsigned char)str[2]];
|
||||
/*FALLTHROUGH*/
|
||||
case 2:
|
||||
case 1:
|
||||
hval += asso_values[(unsigned char)str[0]];
|
||||
break;
|
||||
}
|
||||
return hval;
|
||||
}
|
||||
|
||||
struct kconf_id_strings_t
|
||||
{
|
||||
char kconf_id_strings_str2[sizeof("on")];
|
||||
char kconf_id_strings_str3[sizeof("env")];
|
||||
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_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_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_str27[sizeof("modules")];
|
||||
char kconf_id_strings_str28[sizeof("tristate")];
|
||||
char kconf_id_strings_str29[sizeof("menu")];
|
||||
char kconf_id_strings_str31[sizeof("source")];
|
||||
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")];
|
||||
};
|
||||
static struct kconf_id_strings_t kconf_id_strings_contents =
|
||||
{
|
||||
"on",
|
||||
"env",
|
||||
"endif",
|
||||
"option",
|
||||
"endmenu",
|
||||
"optional",
|
||||
"endchoice",
|
||||
"range",
|
||||
"choice",
|
||||
"default",
|
||||
"def_bool",
|
||||
"help",
|
||||
"bool",
|
||||
"config",
|
||||
"def_tristate",
|
||||
"boolean",
|
||||
"defconfig_list",
|
||||
"string",
|
||||
"if",
|
||||
"int",
|
||||
"select",
|
||||
"modules",
|
||||
"tristate",
|
||||
"menu",
|
||||
"source",
|
||||
"comment",
|
||||
"hex",
|
||||
"menuconfig",
|
||||
"prompt",
|
||||
"depends",
|
||||
"mainmenu"
|
||||
};
|
||||
#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#ifdef __GNUC_STDC_INLINE__
|
||||
__attribute__ ((__gnu_inline__))
|
||||
#endif
|
||||
#endif
|
||||
struct kconf_id *
|
||||
kconf_id_lookup (register const char *str, register unsigned int len)
|
||||
{
|
||||
enum
|
||||
{
|
||||
TOTAL_KEYWORDS = 31,
|
||||
MIN_WORD_LENGTH = 2,
|
||||
MAX_WORD_LENGTH = 14,
|
||||
MIN_HASH_VALUE = 2,
|
||||
MAX_HASH_VALUE = 48
|
||||
};
|
||||
|
||||
static 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},
|
||||
{-1},
|
||||
{(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},
|
||||
{(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},
|
||||
{-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},
|
||||
{-1}, {-1},
|
||||
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND},
|
||||
{(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},
|
||||
{(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},
|
||||
{(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},
|
||||
{-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},
|
||||
{-1},
|
||||
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND}
|
||||
};
|
||||
|
||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||
{
|
||||
register int key = kconf_id_hash (str, len);
|
||||
|
||||
if (key <= MAX_HASH_VALUE && key >= 0)
|
||||
{
|
||||
register int o = wordlist[key].name;
|
||||
if (o >= 0)
|
||||
{
|
||||
register const char *s = o + kconf_id_strings;
|
||||
|
||||
if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
|
||||
return &wordlist[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,355 @@
|
|||
%option backup nostdinit noyywrap never-interactive full ecs
|
||||
%option 8bit backup nodefault perf-report perf-report
|
||||
%x COMMAND HELP STRING PARAM
|
||||
%{
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LKC_DIRECT_LINK
|
||||
#include "lkc.h"
|
||||
|
||||
#define START_STRSIZE 16
|
||||
|
||||
static struct {
|
||||
struct file *file;
|
||||
int lineno;
|
||||
} current_pos;
|
||||
|
||||
static char *text;
|
||||
static int text_size, text_asize;
|
||||
|
||||
struct buffer {
|
||||
struct buffer *parent;
|
||||
YY_BUFFER_STATE state;
|
||||
};
|
||||
|
||||
struct buffer *current_buf;
|
||||
|
||||
static int last_ts, first_ts;
|
||||
|
||||
static void zconf_endhelp(void);
|
||||
static void zconf_endfile(void);
|
||||
|
||||
void new_string(void)
|
||||
{
|
||||
text = malloc(START_STRSIZE);
|
||||
text_asize = START_STRSIZE;
|
||||
text_size = 0;
|
||||
*text = 0;
|
||||
}
|
||||
|
||||
void append_string(const char *str, int size)
|
||||
{
|
||||
int new_size = text_size + size + 1;
|
||||
if (new_size > text_asize) {
|
||||
new_size += START_STRSIZE - 1;
|
||||
new_size &= -START_STRSIZE;
|
||||
text = realloc(text, new_size);
|
||||
text_asize = new_size;
|
||||
}
|
||||
memcpy(text + text_size, str, size);
|
||||
text_size += size;
|
||||
text[text_size] = 0;
|
||||
}
|
||||
|
||||
void alloc_string(const char *str, int size)
|
||||
{
|
||||
text = malloc(size + 1);
|
||||
memcpy(text, str, size);
|
||||
text[size] = 0;
|
||||
}
|
||||
%}
|
||||
|
||||
ws [ \n\t]
|
||||
n [A-Za-z0-9_]
|
||||
|
||||
%%
|
||||
int str = 0;
|
||||
int ts, i;
|
||||
|
||||
[ \t]*#.*\n |
|
||||
[ \t]*\n {
|
||||
current_file->lineno++;
|
||||
return T_EOL;
|
||||
}
|
||||
[ \t]*#.*
|
||||
|
||||
|
||||
[ \t]+ {
|
||||
BEGIN(COMMAND);
|
||||
}
|
||||
|
||||
. {
|
||||
unput(yytext[0]);
|
||||
BEGIN(COMMAND);
|
||||
}
|
||||
|
||||
|
||||
<COMMAND>{
|
||||
{n}+ {
|
||||
struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
|
||||
BEGIN(PARAM);
|
||||
current_pos.file = current_file;
|
||||
current_pos.lineno = current_file->lineno;
|
||||
if (id && id->flags & TF_COMMAND) {
|
||||
zconflval.id = id;
|
||||
return id->token;
|
||||
}
|
||||
alloc_string(yytext, yyleng);
|
||||
zconflval.string = text;
|
||||
return T_WORD;
|
||||
}
|
||||
.
|
||||
\n {
|
||||
BEGIN(INITIAL);
|
||||
current_file->lineno++;
|
||||
return T_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
<PARAM>{
|
||||
"&&" return T_AND;
|
||||
"||" return T_OR;
|
||||
"(" return T_OPEN_PAREN;
|
||||
")" return T_CLOSE_PAREN;
|
||||
"!" return T_NOT;
|
||||
"=" return T_EQUAL;
|
||||
"!=" return T_UNEQUAL;
|
||||
\"|\' {
|
||||
str = yytext[0];
|
||||
new_string();
|
||||
BEGIN(STRING);
|
||||
}
|
||||
\n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
|
||||
--- /* ignore */
|
||||
({n}|[-/.])+ {
|
||||
struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
|
||||
if (id && id->flags & TF_PARAM) {
|
||||
zconflval.id = id;
|
||||
return id->token;
|
||||
}
|
||||
alloc_string(yytext, yyleng);
|
||||
zconflval.string = text;
|
||||
return T_WORD;
|
||||
}
|
||||
#.* /* comment */
|
||||
\\\n current_file->lineno++;
|
||||
.
|
||||
<<EOF>> {
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
<STRING>{
|
||||
[^'"\\\n]+/\n {
|
||||
append_string(yytext, yyleng);
|
||||
zconflval.string = text;
|
||||
return T_WORD_QUOTE;
|
||||
}
|
||||
[^'"\\\n]+ {
|
||||
append_string(yytext, yyleng);
|
||||
}
|
||||
\\.?/\n {
|
||||
append_string(yytext + 1, yyleng - 1);
|
||||
zconflval.string = text;
|
||||
return T_WORD_QUOTE;
|
||||
}
|
||||
\\.? {
|
||||
append_string(yytext + 1, yyleng - 1);
|
||||
}
|
||||
\'|\" {
|
||||
if (str == yytext[0]) {
|
||||
BEGIN(PARAM);
|
||||
zconflval.string = text;
|
||||
return T_WORD_QUOTE;
|
||||
} else
|
||||
append_string(yytext, 1);
|
||||
}
|
||||
\n {
|
||||
printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
|
||||
current_file->lineno++;
|
||||
BEGIN(INITIAL);
|
||||
return T_EOL;
|
||||
}
|
||||
<<EOF>> {
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
<HELP>{
|
||||
[ \t]+ {
|
||||
ts = 0;
|
||||
for (i = 0; i < yyleng; i++) {
|
||||
if (yytext[i] == '\t')
|
||||
ts = (ts & ~7) + 8;
|
||||
else
|
||||
ts++;
|
||||
}
|
||||
last_ts = ts;
|
||||
if (first_ts) {
|
||||
if (ts < first_ts) {
|
||||
zconf_endhelp();
|
||||
return T_HELPTEXT;
|
||||
}
|
||||
ts -= first_ts;
|
||||
while (ts > 8) {
|
||||
append_string(" ", 8);
|
||||
ts -= 8;
|
||||
}
|
||||
append_string(" ", ts);
|
||||
}
|
||||
}
|
||||
[ \t]*\n/[^ \t\n] {
|
||||
current_file->lineno++;
|
||||
zconf_endhelp();
|
||||
return T_HELPTEXT;
|
||||
}
|
||||
[ \t]*\n {
|
||||
current_file->lineno++;
|
||||
append_string("\n", 1);
|
||||
}
|
||||
[^ \t\n].* {
|
||||
while (yyleng) {
|
||||
if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
|
||||
break;
|
||||
yyleng--;
|
||||
}
|
||||
append_string(yytext, yyleng);
|
||||
if (!first_ts)
|
||||
first_ts = last_ts;
|
||||
}
|
||||
<<EOF>> {
|
||||
zconf_endhelp();
|
||||
return T_HELPTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
<<EOF>> {
|
||||
if (current_file) {
|
||||
zconf_endfile();
|
||||
return T_EOL;
|
||||
}
|
||||
fclose(yyin);
|
||||
yyterminate();
|
||||
}
|
||||
|
||||
%%
|
||||
void zconf_starthelp(void)
|
||||
{
|
||||
new_string();
|
||||
last_ts = first_ts = 0;
|
||||
BEGIN(HELP);
|
||||
}
|
||||
|
||||
static void zconf_endhelp(void)
|
||||
{
|
||||
zconflval.string = text;
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to open specified file with following names:
|
||||
* ./name
|
||||
* $(srctree)/name
|
||||
* The latter is used when srctree is separate from objtree
|
||||
* when compiling the kernel.
|
||||
* Return NULL if file is not found.
|
||||
*/
|
||||
FILE *zconf_fopen(const char *name)
|
||||
{
|
||||
char *env, fullname[PATH_MAX+1];
|
||||
FILE *f;
|
||||
|
||||
f = fopen(name, "r");
|
||||
if (!f && name != NULL && name[0] != '/') {
|
||||
env = getenv(SRCTREE);
|
||||
if (env) {
|
||||
sprintf(fullname, "%s/%s", env, name);
|
||||
f = fopen(fullname, "r");
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void zconf_initscan(const char *name)
|
||||
{
|
||||
yyin = zconf_fopen(name);
|
||||
if (!yyin) {
|
||||
printf("can't find file %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
current_buf = malloc(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 *file = file_lookup(name);
|
||||
struct buffer *buf = malloc(sizeof(*buf));
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
|
||||
current_buf->state = YY_CURRENT_BUFFER;
|
||||
yyin = zconf_fopen(name);
|
||||
if (!yyin) {
|
||||
printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), 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("recursive scan (%s)?\n", name);
|
||||
exit(1);
|
||||
}
|
||||
if (file->flags & FILE_SCANNED) {
|
||||
printf("file %s already scanned?\n", name);
|
||||
exit(1);
|
||||
}
|
||||
file->flags |= FILE_BUSY;
|
||||
file->lineno = 1;
|
||||
file->parent = current_file;
|
||||
current_file = file;
|
||||
}
|
||||
|
||||
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;
|
||||
if (parent) {
|
||||
fclose(yyin);
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
yy_switch_to_buffer(parent->state);
|
||||
}
|
||||
free(current_buf);
|
||||
current_buf = parent;
|
||||
}
|
||||
|
||||
int zconf_lineno(void)
|
||||
{
|
||||
return current_pos.lineno;
|
||||
}
|
||||
|
||||
char *zconf_curname(void)
|
||||
{
|
||||
return current_pos.file ? current_pos.file->name : "<none>";
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,703 @@
|
|||
%{
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define LKC_DIRECT_LINK
|
||||
#include "lkc.h"
|
||||
|
||||
#include "zconf.hash.c"
|
||||
|
||||
#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
|
||||
|
||||
#define PRINTD 0x0001
|
||||
#define DEBUG_PARSE 0x0002
|
||||
|
||||
int cdebug = PRINTD;
|
||||
|
||||
extern int zconflex(void);
|
||||
static void zconfprint(const char *err, ...);
|
||||
static void zconf_error(const char *err, ...);
|
||||
static void zconferror(const char *err);
|
||||
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
|
||||
|
||||
struct symbol *symbol_hash[257];
|
||||
|
||||
static struct menu *current_menu, *current_entry;
|
||||
|
||||
#define YYDEBUG 0
|
||||
#if YYDEBUG
|
||||
#define YYERROR_VERBOSE
|
||||
#endif
|
||||
%}
|
||||
%expect 26
|
||||
|
||||
%union
|
||||
{
|
||||
char *string;
|
||||
struct file *file;
|
||||
struct symbol *symbol;
|
||||
struct expr *expr;
|
||||
struct menu *menu;
|
||||
struct kconf_id *id;
|
||||
}
|
||||
|
||||
%token <id>T_MAINMENU
|
||||
%token <id>T_MENU
|
||||
%token <id>T_ENDMENU
|
||||
%token <id>T_SOURCE
|
||||
%token <id>T_CHOICE
|
||||
%token <id>T_ENDCHOICE
|
||||
%token <id>T_COMMENT
|
||||
%token <id>T_CONFIG
|
||||
%token <id>T_MENUCONFIG
|
||||
%token <id>T_HELP
|
||||
%token <string> T_HELPTEXT
|
||||
%token <id>T_IF
|
||||
%token <id>T_ENDIF
|
||||
%token <id>T_DEPENDS
|
||||
%token <id>T_OPTIONAL
|
||||
%token <id>T_PROMPT
|
||||
%token <id>T_TYPE
|
||||
%token <id>T_DEFAULT
|
||||
%token <id>T_SELECT
|
||||
%token <id>T_RANGE
|
||||
%token <id>T_OPTION
|
||||
%token <id>T_ON
|
||||
%token <string> T_WORD
|
||||
%token <string> T_WORD_QUOTE
|
||||
%token T_UNEQUAL
|
||||
%token T_CLOSE_PAREN
|
||||
%token T_OPEN_PAREN
|
||||
%token T_EOL
|
||||
|
||||
%left T_OR
|
||||
%left T_AND
|
||||
%left T_EQUAL T_UNEQUAL
|
||||
%nonassoc T_NOT
|
||||
|
||||
%type <string> prompt
|
||||
%type <symbol> symbol
|
||||
%type <expr> expr
|
||||
%type <expr> if_expr
|
||||
%type <id> end
|
||||
%type <id> option_name
|
||||
%type <menu> if_entry menu_entry choice_entry
|
||||
%type <string> symbol_option_arg
|
||||
|
||||
%destructor {
|
||||
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
|
||||
$$->file->name, $$->lineno);
|
||||
if (current_menu == $$)
|
||||
menu_end_menu();
|
||||
} if_entry menu_entry choice_entry
|
||||
|
||||
%%
|
||||
input: 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
|
||||
{
|
||||
zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
|
||||
}
|
||||
| stmt_list error T_EOL { zconf_error("invalid statement"); }
|
||||
;
|
||||
|
||||
option_name:
|
||||
T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
|
||||
;
|
||||
|
||||
common_stmt:
|
||||
T_EOL
|
||||
| if_stmt
|
||||
| comment_stmt
|
||||
| config_stmt
|
||||
| menuconfig_stmt
|
||||
| source_stmt
|
||||
;
|
||||
|
||||
option_error:
|
||||
T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
|
||||
| error T_EOL { zconf_error("invalid option"); }
|
||||
;
|
||||
|
||||
|
||||
/* config/menuconfig entry */
|
||||
|
||||
config_entry_start: T_CONFIG T_WORD T_EOL
|
||||
{
|
||||
struct symbol *sym = sym_lookup($2, 0);
|
||||
sym->flags |= SYMBOL_OPTIONAL;
|
||||
menu_add_entry(sym);
|
||||
printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||
};
|
||||
|
||||
config_stmt: config_entry_start config_option_list
|
||||
{
|
||||
menu_end_entry();
|
||||
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
|
||||
{
|
||||
struct symbol *sym = sym_lookup($2, 0);
|
||||
sym->flags |= SYMBOL_OPTIONAL;
|
||||
menu_add_entry(sym);
|
||||
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||
};
|
||||
|
||||
menuconfig_stmt: menuconfig_entry_start config_option_list
|
||||
{
|
||||
if (current_entry->prompt)
|
||||
current_entry->prompt->type = P_MENU;
|
||||
else
|
||||
zconfprint("warning: menuconfig statement without prompt");
|
||||
menu_end_entry();
|
||||
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
config_option_list:
|
||||
/* empty */
|
||||
| config_option_list config_option
|
||||
| config_option_list symbol_option
|
||||
| config_option_list depends
|
||||
| config_option_list help
|
||||
| config_option_list option_error
|
||||
| config_option_list T_EOL
|
||||
;
|
||||
|
||||
config_option: T_TYPE prompt_stmt_opt T_EOL
|
||||
{
|
||||
menu_set_type($1->stype);
|
||||
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
|
||||
zconf_curname(), zconf_lineno(),
|
||||
$1->stype);
|
||||
};
|
||||
|
||||
config_option: T_PROMPT prompt if_expr T_EOL
|
||||
{
|
||||
menu_add_prompt(P_PROMPT, $2, $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
config_option: T_DEFAULT expr if_expr T_EOL
|
||||
{
|
||||
menu_add_expr(P_DEFAULT, $2, $3);
|
||||
if ($1->stype != S_UNKNOWN)
|
||||
menu_set_type($1->stype);
|
||||
printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
|
||||
zconf_curname(), zconf_lineno(),
|
||||
$1->stype);
|
||||
};
|
||||
|
||||
config_option: T_SELECT T_WORD if_expr T_EOL
|
||||
{
|
||||
menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
config_option: T_RANGE symbol symbol if_expr T_EOL
|
||||
{
|
||||
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
|
||||
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
symbol_option: T_OPTION symbol_option_list T_EOL
|
||||
;
|
||||
|
||||
symbol_option_list:
|
||||
/* empty */
|
||||
| symbol_option_list T_WORD symbol_option_arg
|
||||
{
|
||||
struct kconf_id *id = kconf_id_lookup($2, strlen($2));
|
||||
if (id && id->flags & TF_OPTION)
|
||||
menu_add_option(id->token, $3);
|
||||
else
|
||||
zconfprint("warning: ignoring unknown option %s", $2);
|
||||
free($2);
|
||||
};
|
||||
|
||||
symbol_option_arg:
|
||||
/* empty */ { $$ = NULL; }
|
||||
| T_EQUAL prompt { $$ = $2; }
|
||||
;
|
||||
|
||||
/* choice entry */
|
||||
|
||||
choice: T_CHOICE T_EOL
|
||||
{
|
||||
struct symbol *sym = sym_lookup(NULL, 0);
|
||||
sym->flags |= SYMBOL_CHOICE;
|
||||
menu_add_entry(sym);
|
||||
menu_add_expr(P_CHOICE, NULL, NULL);
|
||||
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
choice_entry: choice choice_option_list
|
||||
{
|
||||
$$ = menu_add_menu();
|
||||
};
|
||||
|
||||
choice_end: end
|
||||
{
|
||||
if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
|
||||
menu_end_menu();
|
||||
printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
|
||||
}
|
||||
};
|
||||
|
||||
choice_stmt: choice_entry choice_block choice_end
|
||||
;
|
||||
|
||||
choice_option_list:
|
||||
/* empty */
|
||||
| choice_option_list choice_option
|
||||
| choice_option_list depends
|
||||
| choice_option_list help
|
||||
| choice_option_list T_EOL
|
||||
| choice_option_list option_error
|
||||
;
|
||||
|
||||
choice_option: T_PROMPT prompt if_expr T_EOL
|
||||
{
|
||||
menu_add_prompt(P_PROMPT, $2, $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
choice_option: T_TYPE prompt_stmt_opt T_EOL
|
||||
{
|
||||
if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
|
||||
menu_set_type($1->stype);
|
||||
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
|
||||
zconf_curname(), zconf_lineno(),
|
||||
$1->stype);
|
||||
} else
|
||||
YYERROR;
|
||||
};
|
||||
|
||||
choice_option: T_OPTIONAL T_EOL
|
||||
{
|
||||
current_entry->sym->flags |= SYMBOL_OPTIONAL;
|
||||
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
choice_option: T_DEFAULT T_WORD if_expr T_EOL
|
||||
{
|
||||
if ($1->stype == S_UNKNOWN) {
|
||||
menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:default\n",
|
||||
zconf_curname(), zconf_lineno());
|
||||
} else
|
||||
YYERROR;
|
||||
};
|
||||
|
||||
choice_block:
|
||||
/* empty */
|
||||
| choice_block common_stmt
|
||||
;
|
||||
|
||||
/* if entry */
|
||||
|
||||
if_entry: T_IF expr nl
|
||||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
|
||||
menu_add_entry(NULL);
|
||||
menu_add_dep($2);
|
||||
$$ = menu_add_menu();
|
||||
};
|
||||
|
||||
if_end: end
|
||||
{
|
||||
if (zconf_endtoken($1, T_IF, T_ENDIF)) {
|
||||
menu_end_menu();
|
||||
printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
|
||||
}
|
||||
};
|
||||
|
||||
if_stmt: if_entry if_block if_end
|
||||
;
|
||||
|
||||
if_block:
|
||||
/* empty */
|
||||
| if_block common_stmt
|
||||
| if_block menu_stmt
|
||||
| if_block choice_stmt
|
||||
;
|
||||
|
||||
/* menu entry */
|
||||
|
||||
menu: T_MENU prompt T_EOL
|
||||
{
|
||||
menu_add_entry(NULL);
|
||||
menu_add_prompt(P_MENU, $2, NULL);
|
||||
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
menu_entry: menu depends_list
|
||||
{
|
||||
$$ = menu_add_menu();
|
||||
};
|
||||
|
||||
menu_end: end
|
||||
{
|
||||
if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
|
||||
menu_end_menu();
|
||||
printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
|
||||
}
|
||||
};
|
||||
|
||||
menu_stmt: menu_entry menu_block menu_end
|
||||
;
|
||||
|
||||
menu_block:
|
||||
/* empty */
|
||||
| menu_block common_stmt
|
||||
| menu_block menu_stmt
|
||||
| menu_block choice_stmt
|
||||
;
|
||||
|
||||
source_stmt: T_SOURCE prompt T_EOL
|
||||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||
zconf_nextfile($2);
|
||||
};
|
||||
|
||||
/* comment entry */
|
||||
|
||||
comment: T_COMMENT prompt T_EOL
|
||||
{
|
||||
menu_add_entry(NULL);
|
||||
menu_add_prompt(P_COMMENT, $2, NULL);
|
||||
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
comment_stmt: comment depends_list
|
||||
{
|
||||
menu_end_entry();
|
||||
};
|
||||
|
||||
/* help option */
|
||||
|
||||
help_start: T_HELP T_EOL
|
||||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
|
||||
zconf_starthelp();
|
||||
};
|
||||
|
||||
help: help_start T_HELPTEXT
|
||||
{
|
||||
current_entry->help = $2;
|
||||
};
|
||||
|
||||
/* depends option */
|
||||
|
||||
depends_list:
|
||||
/* empty */
|
||||
| depends_list depends
|
||||
| depends_list T_EOL
|
||||
| depends_list option_error
|
||||
;
|
||||
|
||||
depends: T_DEPENDS T_ON expr T_EOL
|
||||
{
|
||||
menu_add_dep($3);
|
||||
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
/* prompt statement */
|
||||
|
||||
prompt_stmt_opt:
|
||||
/* empty */
|
||||
| prompt if_expr
|
||||
{
|
||||
menu_add_prompt(P_PROMPT, $1, $2);
|
||||
};
|
||||
|
||||
prompt: T_WORD
|
||||
| T_WORD_QUOTE
|
||||
;
|
||||
|
||||
end: T_ENDMENU T_EOL { $$ = $1; }
|
||||
| T_ENDCHOICE T_EOL { $$ = $1; }
|
||||
| T_ENDIF T_EOL { $$ = $1; }
|
||||
;
|
||||
|
||||
nl:
|
||||
T_EOL
|
||||
| nl T_EOL
|
||||
;
|
||||
|
||||
if_expr: /* empty */ { $$ = NULL; }
|
||||
| T_IF expr { $$ = $2; }
|
||||
;
|
||||
|
||||
expr: symbol { $$ = expr_alloc_symbol($1); }
|
||||
| symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
|
||||
| symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
|
||||
| T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
|
||||
| T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
|
||||
| expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
|
||||
| expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
|
||||
;
|
||||
|
||||
symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
|
||||
| T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
void conf_parse(const char *name)
|
||||
{
|
||||
struct symbol *sym;
|
||||
int i;
|
||||
|
||||
zconf_initscan(name);
|
||||
|
||||
sym_init();
|
||||
menu_init();
|
||||
modules_sym = sym_lookup(NULL, 0);
|
||||
modules_sym->type = S_BOOLEAN;
|
||||
modules_sym->flags |= SYMBOL_AUTO;
|
||||
rootmenu.prompt = menu_add_prompt(P_MENU, "coreinfo Configuration", NULL);
|
||||
|
||||
#if YYDEBUG
|
||||
if (getenv("ZCONF_DEBUG"))
|
||||
zconfdebug = 1;
|
||||
#endif
|
||||
zconfparse();
|
||||
if (zconfnerrs)
|
||||
exit(1);
|
||||
if (!modules_sym->prop) {
|
||||
struct property *prop;
|
||||
|
||||
prop = prop_alloc(P_DEFAULT, modules_sym);
|
||||
prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
|
||||
}
|
||||
menu_finalize(&rootmenu);
|
||||
for_all_symbols(i, sym) {
|
||||
if (sym_check_deps(sym))
|
||||
zconfnerrs++;
|
||||
}
|
||||
if (zconfnerrs)
|
||||
exit(1);
|
||||
sym_set_change_count(1);
|
||||
}
|
||||
|
||||
const char *zconf_tokenname(int token)
|
||||
{
|
||||
switch (token) {
|
||||
case T_MENU: return "menu";
|
||||
case T_ENDMENU: return "endmenu";
|
||||
case T_CHOICE: return "choice";
|
||||
case T_ENDCHOICE: return "endchoice";
|
||||
case T_IF: return "if";
|
||||
case T_ENDIF: return "endif";
|
||||
case T_DEPENDS: return "depends";
|
||||
}
|
||||
return "<token>";
|
||||
}
|
||||
|
||||
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
|
||||
{
|
||||
if (id->token != endtoken) {
|
||||
zconf_error("unexpected '%s' within %s block",
|
||||
kconf_id_strings + id->name, zconf_tokenname(starttoken));
|
||||
zconfnerrs++;
|
||||
return false;
|
||||
}
|
||||
if (current_menu->file != current_file) {
|
||||
zconf_error("'%s' in different file than '%s'",
|
||||
kconf_id_strings + id->name, zconf_tokenname(starttoken));
|
||||
fprintf(stderr, "%s:%d: location of the '%s'\n",
|
||||
current_menu->file->name, current_menu->lineno,
|
||||
zconf_tokenname(starttoken));
|
||||
zconfnerrs++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void zconfprint(const char *err, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
|
||||
va_start(ap, err);
|
||||
vfprintf(stderr, err, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void zconf_error(const char *err, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
zconfnerrs++;
|
||||
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
|
||||
va_start(ap, err);
|
||||
vfprintf(stderr, err, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void zconferror(const char *err)
|
||||
{
|
||||
#if YYDEBUG
|
||||
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_quoted_string(FILE *out, const char *str)
|
||||
{
|
||||
const char *p;
|
||||
int len;
|
||||
|
||||
putc('"', out);
|
||||
while ((p = strchr(str, '"'))) {
|
||||
len = p - str;
|
||||
if (len)
|
||||
fprintf(out, "%.*s", len, str);
|
||||
fputs("\\\"", out);
|
||||
str = p + 1;
|
||||
}
|
||||
fputs(str, out);
|
||||
putc('"', out);
|
||||
}
|
||||
|
||||
void print_symbol(FILE *out, struct menu *menu)
|
||||
{
|
||||
struct symbol *sym = menu->sym;
|
||||
struct property *prop;
|
||||
|
||||
if (sym_is_choice(sym))
|
||||
fprintf(out, "choice\n");
|
||||
else
|
||||
fprintf(out, "config %s\n", sym->name);
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
fputs(" boolean\n", out);
|
||||
break;
|
||||
case S_TRISTATE:
|
||||
fputs(" tristate\n", out);
|
||||
break;
|
||||
case S_STRING:
|
||||
fputs(" string\n", out);
|
||||
break;
|
||||
case S_INT:
|
||||
fputs(" integer\n", out);
|
||||
break;
|
||||
case S_HEX:
|
||||
fputs(" hex\n", out);
|
||||
break;
|
||||
default:
|
||||
fputs(" ???\n", out);
|
||||
break;
|
||||
}
|
||||
for (prop = sym->prop; prop; prop = prop->next) {
|
||||
if (prop->menu != menu)
|
||||
continue;
|
||||
switch (prop->type) {
|
||||
case P_PROMPT:
|
||||
fputs(" prompt ", out);
|
||||
print_quoted_string(out, prop->text);
|
||||
if (!expr_is_yes(prop->visible.expr)) {
|
||||
fputs(" if ", out);
|
||||
expr_fprint(prop->visible.expr, out);
|
||||
}
|
||||
fputc('\n', out);
|
||||
break;
|
||||
case P_DEFAULT:
|
||||
fputs( " default ", out);
|
||||
expr_fprint(prop->expr, out);
|
||||
if (!expr_is_yes(prop->visible.expr)) {
|
||||
fputs(" if ", out);
|
||||
expr_fprint(prop->visible.expr, out);
|
||||
}
|
||||
fputc('\n', out);
|
||||
break;
|
||||
case P_CHOICE:
|
||||
fputs(" #choice value\n", out);
|
||||
break;
|
||||
default:
|
||||
fprintf(out, " unknown prop %d!\n", prop->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (menu->help) {
|
||||
int len = strlen(menu->help);
|
||||
while (menu->help[--len] == '\n')
|
||||
menu->help[len] = 0;
|
||||
fprintf(out, " help\n%s\n", menu->help);
|
||||
}
|
||||
fputc('\n', out);
|
||||
}
|
||||
|
||||
void zconfdump(FILE *out)
|
||||
{
|
||||
struct property *prop;
|
||||
struct symbol *sym;
|
||||
struct menu *menu;
|
||||
|
||||
menu = rootmenu.list;
|
||||
while (menu) {
|
||||
if ((sym = menu->sym))
|
||||
print_symbol(out, menu);
|
||||
else if ((prop = menu->prompt)) {
|
||||
switch (prop->type) {
|
||||
case P_COMMENT:
|
||||
fputs("\ncomment ", out);
|
||||
print_quoted_string(out, prop->text);
|
||||
fputs("\n", out);
|
||||
break;
|
||||
case P_MENU:
|
||||
fputs("\nmenu ", out);
|
||||
print_quoted_string(out, prop->text);
|
||||
fputs("\n", out);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
if (!expr_is_yes(prop->visible.expr)) {
|
||||
fputs(" depends ", out);
|
||||
expr_fprint(prop->visible.expr, out);
|
||||
fputc('\n', out);
|
||||
}
|
||||
fputs("\n", out);
|
||||
}
|
||||
|
||||
if (menu->list)
|
||||
menu = menu->list;
|
||||
else if (menu->next)
|
||||
menu = menu->next;
|
||||
else while ((menu = menu->parent)) {
|
||||
if (menu->prompt && menu->prompt->type == P_MENU)
|
||||
fputs("\nendmenu\n", out);
|
||||
if (menu->next) {
|
||||
menu = menu->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "lex.zconf.c"
|
||||
#include "util.c"
|
||||
#include "confdata.c"
|
||||
#include "expr.c"
|
||||
#include "symbol.c"
|
||||
#include "menu.c"
|
Loading…
Reference in New Issue