aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Kbuild11
-rw-r--r--scripts/Kbuild.include148
-rw-r--r--scripts/Makefile.build338
-rw-r--r--scripts/Makefile.host156
-rw-r--r--scripts/Makefile.lib165
-rw-r--r--scripts/basic/Makefile18
-rw-r--r--scripts/basic/docproc.c398
-rw-r--r--scripts/basic/fixdep.c393
-rw-r--r--scripts/basic/split-include.c226
-rw-r--r--scripts/kconfig/Makefile254
-rw-r--r--scripts/kconfig/POTFILES.in5
-rw-r--r--scripts/kconfig/conf.c612
-rw-r--r--scripts/kconfig/confdata.c560
-rw-r--r--scripts/kconfig/expr.c1099
-rw-r--r--scripts/kconfig/expr.h194
-rw-r--r--scripts/kconfig/gconf.c1645
-rw-r--r--scripts/kconfig/gconf.glade648
-rw-r--r--scripts/kconfig/images.c326
-rw-r--r--scripts/kconfig/kconfig_load.c35
-rw-r--r--scripts/kconfig/kxgettext.c227
-rw-r--r--scripts/kconfig/lex.zconf.c_shipped2317
-rw-r--r--scripts/kconfig/lkc.h147
-rw-r--r--scripts/kconfig/lkc_proto.h41
-rw-r--r--scripts/kconfig/lxdialog/BIG.FAT.WARNING4
-rw-r--r--scripts/kconfig/lxdialog/Makefile21
-rw-r--r--scripts/kconfig/lxdialog/check-lxdialog.sh84
-rw-r--r--scripts/kconfig/lxdialog/checklist.c333
-rw-r--r--scripts/kconfig/lxdialog/colors.h154
-rw-r--r--scripts/kconfig/lxdialog/dialog.h177
-rw-r--r--scripts/kconfig/lxdialog/inputbox.c224
-rw-r--r--scripts/kconfig/lxdialog/lxdialog.c204
-rw-r--r--scripts/kconfig/lxdialog/menubox.c426
-rw-r--r--scripts/kconfig/lxdialog/msgbox.c71
-rw-r--r--scripts/kconfig/lxdialog/textbox.c533
-rw-r--r--scripts/kconfig/lxdialog/util.c362
-rw-r--r--scripts/kconfig/lxdialog/yesno.c102
-rw-r--r--scripts/kconfig/mconf.c1098
-rw-r--r--scripts/kconfig/menu.c397
-rw-r--r--scripts/kconfig/qconf.cc1426
-rw-r--r--scripts/kconfig/qconf.h263
-rw-r--r--scripts/kconfig/symbol.c882
-rw-r--r--scripts/kconfig/util.c109
-rw-r--r--scripts/kconfig/zconf.gperf43
-rw-r--r--scripts/kconfig/zconf.hash.c_shipped231
-rw-r--r--scripts/kconfig/zconf.l350
-rw-r--r--scripts/kconfig/zconf.tab.c_shipped2173
-rw-r--r--scripts/kconfig/zconf.y681
-rwxr-xr-xscripts/mkconfigs51
-rwxr-xr-xscripts/trylink18
-rw-r--r--scripts/usage.c8
-rwxr-xr-x[-rw-r--r--]scripts/usage_compressed14
51 files changed, 20395 insertions, 7 deletions
diff --git a/scripts/Kbuild b/scripts/Kbuild
new file mode 100644
index 000000000..80c60733e
--- /dev/null
+++ b/scripts/Kbuild
@@ -0,0 +1,11 @@
1###
2# scripts contains sources for various helper programs used throughout
3# the kernel for the build process.
4# ---------------------------------------------------------------------------
5
6hostprogs-y += usage
7
8always := $(hostprogs-y)
9
10# Let clean descend into subdirs
11subdir- += basic kconfig
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
new file mode 100644
index 000000000..b0d067be7
--- /dev/null
+++ b/scripts/Kbuild.include
@@ -0,0 +1,148 @@
1####
2# kbuild: Generic definitions
3
4# Convinient variables
5comma := ,
6squote := '
7empty :=
8space := $(empty) $(empty)
9
10###
11# The temporary file to save gcc -MD generated dependencies must not
12# contain a comma
13depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
14
15###
16# Escape single quote for use in echo statements
17escsq = $(subst $(squote),'\$(squote)',$1)
18
19###
20# filechk is used to check if the content of a generated file is updated.
21# Sample usage:
22# define filechk_sample
23# echo $KERNELRELEASE
24# endef
25# version.h : Makefile
26# $(call filechk,sample)
27# The rule defined shall write to stdout the content of the new file.
28# The existing file will be compared with the new one.
29# - If no file exist it is created
30# - If the content differ the new file is used
31# - If they are equal no change, and no timestamp update
32# - stdin is piped in from the first prerequisite ($<) so one has
33# to specify a valid file as first prerequisite (often the kbuild file)
34define filechk
35 $(Q)set -e; \
36 echo ' CHK $@'; \
37 mkdir -p $(dir $@); \
38 $(filechk_$(1)) < $< > $@.tmp; \
39 if [ -r $@ ] && cmp -s $@ $@.tmp; then \
40 rm -f $@.tmp; \
41 else \
42 echo ' UPD $@'; \
43 mv -f $@.tmp $@; \
44 fi
45endef
46
47######
48# gcc support functions
49# See documentation in Documentation/kbuild/makefiles.txt
50
51# as-option
52# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
53
54as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
55 -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
56 else echo "$(2)"; fi ;)
57
58# cc-option
59# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
60
61cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
62 > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
63
64# cc-option-yn
65# Usage: flag := $(call cc-option-yn, -march=winchip-c6)
66cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
67 > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
68
69# cc-option-align
70# Prefix align with either -falign or -malign
71cc-option-align = $(subst -functions=0,,\
72 $(call cc-option,-falign-functions=0,-malign-functions=0))
73
74# cc-version
75# Usage gcc-ver := $(call cc-version, $(CC))
76cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
77 $(if $(1), $(1), $(CC)))
78
79# cc-ifversion
80# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
81cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
82 echo $(3); fi;)
83
84###
85# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
86# Usage:
87# $(Q)$(MAKE) $(build)=dir
88build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
89
90# Prefix -I with $(srctree) if it is not an absolute path
91addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
92# Find all -I options and call addtree
93flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
94
95# If quiet is set, only print short version of command
96cmd = @$(echo-cmd) $(cmd_$(1))
97
98# Add $(obj)/ for paths that is not absolute
99objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
100
101###
102# if_changed - execute command if any prerequisite is newer than
103# target, or command line has changed
104# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies
105# including used config symbols
106# if_changed_rule - as if_changed but execute rule instead
107# See Documentation/kbuild/makefiles.txt for more info
108
109ifneq ($(KBUILD_NOCMDDEP),1)
110# Check if both arguments has same arguments. Result in empty string if equal
111# User may override this check using make KBUILD_NOCMDDEP=1
112arg-check = $(strip $(filter-out $(1), $(2)) $(filter-out $(2), $(1)) )
113endif
114
115# echo command. Short version is $(quiet) equals quiet, otherwise full command
116echo-cmd = $(if $($(quiet)cmd_$(1)), \
117 echo ' $(call escsq,$($(quiet)cmd_$(1)))';)
118
119make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
120
121# function to only execute the passed command if necessary
122# >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
123# note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars
124#
125if_changed = $(if $(strip $(filter-out $(PHONY),$?) \
126 $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
127 @set -e; \
128 $(echo-cmd) $(cmd_$(1)); \
129 echo 'cmd_$@ := $(make-cmd)' > $(@D)/.$(@F).cmd)
130
131# execute the command and also postprocess generated .d dependencies
132# file
133if_changed_dep = $(if $(strip $(filter-out $(PHONY),$?) \
134 $(filter-out FORCE $(wildcard $^),$^) \
135 $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
136 @set -e; \
137 $(echo-cmd) $(cmd_$(1)); \
138 scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(@D)/.$(@F).tmp; \
139 rm -f $(depfile); \
140 mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
141
142# Usage: $(call if_changed_rule,foo)
143# will check if $(cmd_foo) changed, or any of the prequisites changed,
144# and if so will execute $(rule_foo)
145if_changed_rule = $(if $(strip $(filter-out $(PHONY),$?) \
146 $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
147 @set -e; \
148 $(rule_$(1)))
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
new file mode 100644
index 000000000..e48e60da3
--- /dev/null
+++ b/scripts/Makefile.build
@@ -0,0 +1,338 @@
1# ==========================================================================
2# Building
3# ==========================================================================
4
5src := $(obj)
6
7PHONY := __build
8__build:
9
10# Read .config if it exist, otherwise ignore
11-include .config
12
13include scripts/Kbuild.include
14
15# The filename Kbuild has precedence over Makefile
16kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
17include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
18
19include scripts/Makefile.lib
20
21ifdef host-progs
22ifneq ($(hostprogs-y),$(host-progs))
23$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!)
24hostprogs-y += $(host-progs)
25endif
26endif
27
28# Do not include host rules unles needed
29ifneq ($(hostprogs-y)$(hostprogs-m),)
30include scripts/Makefile.host
31endif
32
33ifneq ($(KBUILD_SRC),)
34# Create output directory if not already present
35_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
36
37# Create directories for object files if directory does not exist
38# Needed when obj-y := dir/file.o syntax is used
39_dummy := $(foreach d,$(obj-dirs), $(shell [ -d $(d) ] || mkdir -p $(d)))
40endif
41
42
43ifdef EXTRA_TARGETS
44$(warning kbuild: $(obj)/Makefile - Usage of EXTRA_TARGETS is obsolete in 2.6. Please fix!)
45endif
46
47ifdef build-targets
48$(warning kbuild: $(obj)/Makefile - Usage of build-targets is obsolete in 2.6. Please fix!)
49endif
50
51ifdef export-objs
52$(warning kbuild: $(obj)/Makefile - Usage of export-objs is obsolete in 2.6. Please fix!)
53endif
54
55ifdef O_TARGET
56$(warning kbuild: $(obj)/Makefile - Usage of O_TARGET := $(O_TARGET) is obsolete in 2.6. Please fix!)
57endif
58
59ifdef L_TARGET
60$(error kbuild: $(obj)/Makefile - Use of L_TARGET is replaced by lib-y in 2.6. Please fix!)
61endif
62
63ifdef list-multi
64$(warning kbuild: $(obj)/Makefile - list-multi := $(list-multi) is obsolete in 2.6. Please fix!)
65endif
66
67ifndef obj
68$(warning kbuild: Makefile.build is included improperly)
69endif
70
71# ===========================================================================
72
73ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
74lib-target := $(obj)/lib.a
75endif
76
77ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),)
78builtin-target := $(obj)/built-in.o
79endif
80
81# We keep a list of all modules in $(MODVERDIR)
82
83__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
84 $(if $(KBUILD_MODULES),$(obj-m)) \
85 $(subdir-ym) $(always)
86 @:
87
88# Linus' kernel sanity checking tool
89ifneq ($(KBUILD_CHECKSRC),0)
90 ifeq ($(KBUILD_CHECKSRC),2)
91 quiet_cmd_force_checksrc = CHECK $<
92 cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
93 else
94 quiet_cmd_checksrc = CHECK $<
95 cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
96 endif
97endif
98
99
100# Compile C sources (.c)
101# ---------------------------------------------------------------------------
102
103# Default is built-in, unless we know otherwise
104modkern_cflags := $(CFLAGS_KERNEL)
105quiet_modtag := $(empty) $(empty)
106
107$(real-objs-m) : modkern_cflags := $(CFLAGS_MODULE)
108$(real-objs-m:.o=.i) : modkern_cflags := $(CFLAGS_MODULE)
109$(real-objs-m:.o=.s) : modkern_cflags := $(CFLAGS_MODULE)
110$(real-objs-m:.o=.lst): modkern_cflags := $(CFLAGS_MODULE)
111
112$(real-objs-m) : quiet_modtag := [M]
113$(real-objs-m:.o=.i) : quiet_modtag := [M]
114$(real-objs-m:.o=.s) : quiet_modtag := [M]
115$(real-objs-m:.o=.lst): quiet_modtag := [M]
116
117$(obj-m) : quiet_modtag := [M]
118
119# Default for not multi-part modules
120modname = $(*F)
121
122$(multi-objs-m) : modname = $(modname-multi)
123$(multi-objs-m:.o=.i) : modname = $(modname-multi)
124$(multi-objs-m:.o=.s) : modname = $(modname-multi)
125$(multi-objs-m:.o=.lst) : modname = $(modname-multi)
126$(multi-objs-y) : modname = $(modname-multi)
127$(multi-objs-y:.o=.i) : modname = $(modname-multi)
128$(multi-objs-y:.o=.s) : modname = $(modname-multi)
129$(multi-objs-y:.o=.lst) : modname = $(modname-multi)
130
131quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
132cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
133
134%.s: %.c FORCE
135 $(call if_changed_dep,cc_s_c)
136
137quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@
138cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $<
139
140%.i: %.c FORCE
141 $(call if_changed_dep,cc_i_c)
142
143# C (.c) files
144# The C file is compiled and updated dependency information is generated.
145# (See cmd_cc_o_c + relevant part of rule_cc_o_c)
146
147quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
148
149ifndef CONFIG_MODVERSIONS
150cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
151
152else
153# When module versioning is enabled the following steps are executed:
154# o compile a .tmp_<file>.o from <file>.c
155# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
156# not export symbols, we just rename .tmp_<file>.o to <file>.o and
157# are done.
158# o otherwise, we calculate symbol versions using the good old
159# genksyms on the preprocessed source and postprocess them in a way
160# that they are usable as a linker script
161# o generate <file>.o from .tmp_<file>.o using the linker to
162# replace the unresolved symbols __crc_exported_symbol with
163# the actual value of the checksum generated by genksyms
164
165cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
166cmd_modversions = \
167 if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
168 $(CPP) -D__GENKSYMS__ $(c_flags) $< \
169 | $(GENKSYMS) -a $(ARCH) \
170 > $(@D)/.tmp_$(@F:.o=.ver); \
171 \
172 $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
173 -T $(@D)/.tmp_$(@F:.o=.ver); \
174 rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
175 else \
176 mv -f $(@D)/.tmp_$(@F) $@; \
177 fi;
178endif
179
180define rule_cc_o_c
181 $(call echo-cmd,checksrc) $(cmd_checksrc) \
182 $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \
183 $(cmd_modversions) \
184 scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > $(@D)/.$(@F).tmp; \
185 rm -f $(depfile); \
186 mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
187endef
188
189# Built-in and composite module parts
190
191%.o: %.c FORCE
192 $(call cmd,force_checksrc)
193 $(call if_changed_rule,cc_o_c)
194
195# Single-part modules are special since we need to mark them in $(MODVERDIR)
196
197$(single-used-m): %.o: %.c FORCE
198 $(call cmd,force_checksrc)
199 $(call if_changed_rule,cc_o_c)
200 @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
201
202quiet_cmd_cc_lst_c = MKLST $@
203 cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
204 $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
205 System.map $(OBJDUMP) > $@
206
207%.lst: %.c FORCE
208 $(call if_changed_dep,cc_lst_c)
209
210# Compile assembler sources (.S)
211# ---------------------------------------------------------------------------
212
213modkern_aflags := $(AFLAGS_KERNEL)
214
215$(real-objs-m) : modkern_aflags := $(AFLAGS_MODULE)
216$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE)
217
218quiet_cmd_as_s_S = CPP $(quiet_modtag) $@
219cmd_as_s_S = $(CPP) $(a_flags) -o $@ $<
220
221%.s: %.S FORCE
222 $(call if_changed_dep,as_s_S)
223
224quiet_cmd_as_o_S = AS $(quiet_modtag) $@
225cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
226
227%.o: %.S FORCE
228 $(call if_changed_dep,as_o_S)
229
230targets += $(real-objs-y) $(real-objs-m) $(lib-y)
231targets += $(extra-y) $(MAKECMDGOALS) $(always)
232
233# Linker scripts preprocessor (.lds.S -> .lds)
234# ---------------------------------------------------------------------------
235quiet_cmd_cpp_lds_S = LDS $@
236 cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<
237
238%.lds: %.lds.S FORCE
239 $(call if_changed_dep,cpp_lds_S)
240
241# Build the compiled-in targets
242# ---------------------------------------------------------------------------
243
244# To build objects in subdirs, we need to descend into the directories
245$(sort $(subdir-obj-y)): $(subdir-ym) ;
246
247#
248# Rule to compile a set of .o files into one .o file
249#
250ifdef builtin-target
251quiet_cmd_link_o_target = LD $@
252# If the list of objects to link is empty, just create an empty built-in.o
253cmd_link_o_target = $(if $(strip $(obj-y)),\
254 $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\
255 rm -f $@; $(AR) rcs $@)
256
257$(builtin-target): $(obj-y) FORCE
258 $(call if_changed,link_o_target)
259
260targets += $(builtin-target)
261endif # builtin-target
262
263#
264# Rule to compile a set of .o files into one .a file
265#
266ifdef lib-target
267quiet_cmd_link_l_target = AR $@
268cmd_link_l_target = rm -f $@; $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-y)
269
270$(lib-target): $(lib-y) FORCE
271 $(call if_changed,link_l_target)
272
273targets += $(lib-target)
274endif
275
276#
277# Rule to link composite objects
278#
279# Composite objects are specified in kbuild makefile as follows:
280# <composite-object>-objs := <list of .o files>
281# or
282# <composite-object>-y := <list of .o files>
283link_multi_deps = \
284$(filter $(addprefix $(obj)/, \
285$($(subst $(obj)/,,$(@:.o=-objs))) \
286$($(subst $(obj)/,,$(@:.o=-y)))), $^)
287
288quiet_cmd_link_multi-y = LD $@
289cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps)
290
291quiet_cmd_link_multi-m = LD [M] $@
292cmd_link_multi-m = $(LD) $(ld_flags) $(LDFLAGS_MODULE) -o $@ $(link_multi_deps)
293
294# We would rather have a list of rules like
295# foo.o: $(foo-objs)
296# but that's not so easy, so we rather make all composite objects depend
297# on the set of all their parts
298$(multi-used-y) : %.o: $(multi-objs-y) FORCE
299 $(call if_changed,link_multi-y)
300
301$(multi-used-m) : %.o: $(multi-objs-m) FORCE
302 $(call if_changed,link_multi-m)
303 @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
304
305targets += $(multi-used-y) $(multi-used-m)
306
307
308# Descending
309# ---------------------------------------------------------------------------
310
311PHONY += $(subdir-ym)
312$(subdir-ym):
313 $(Q)$(MAKE) $(build)=$@
314
315# Add FORCE to the prequisites of a target to force it to be always rebuilt.
316# ---------------------------------------------------------------------------
317
318PHONY += FORCE
319
320FORCE:
321
322# Read all saved command lines and dependencies for the $(targets) we
323# may be building above, using $(if_changed{,_dep}). As an
324# optimization, we don't need to read them if the target does not
325# exist, we will rebuild anyway in that case.
326
327targets := $(wildcard $(sort $(targets)))
328cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
329
330ifneq ($(cmd_files),)
331 include $(cmd_files)
332endif
333
334
335# Declare the contents of the .PHONY variable as phony. We keep that
336# information in a variable se we can use it in if_changed and friends.
337
338.PHONY: $(PHONY)
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
new file mode 100644
index 000000000..2d519704b
--- /dev/null
+++ b/scripts/Makefile.host
@@ -0,0 +1,156 @@
1# ==========================================================================
2# Building binaries on the host system
3# Binaries are used during the compilation of the kernel, for example
4# to preprocess a data file.
5#
6# Both C and C++ is supported, but preferred language is C for such utilities.
7#
8# Samle syntax (see Documentation/kbuild/makefile.txt for reference)
9# hostprogs-y := bin2hex
10# Will compile bin2hex.c and create an executable named bin2hex
11#
12# hostprogs-y := lxdialog
13# lxdialog-objs := checklist.o lxdialog.o
14# Will compile lxdialog.c and checklist.c, and then link the executable
15# lxdialog, based on checklist.o and lxdialog.o
16#
17# hostprogs-y := qconf
18# qconf-cxxobjs := qconf.o
19# qconf-objs := menu.o
20# Will compile qconf as a C++ program, and menu as a C program.
21# They are linked as C++ code to the executable qconf
22
23# hostprogs-y := conf
24# conf-objs := conf.o libkconfig.so
25# libkconfig-objs := expr.o type.o
26# Will create a shared library named libkconfig.so that consist of
27# expr.o and type.o (they are both compiled as C code and the object file
28# are made as position independent code).
29# conf.c is compiled as a c program, and conf.o is linked together with
30# libkconfig.so as the executable conf.
31# Note: Shared libraries consisting of C++ files are not supported
32
33__hostprogs := $(sort $(hostprogs-y)$(hostprogs-m))
34
35# hostprogs-y := tools/build may have been specified. Retreive directory
36obj-dirs += $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
37obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs))))
38
39
40# C code
41# Executables compiled from a single .c file
42host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m)))
43
44# C executables linked based on several .o files
45host-cmulti := $(foreach m,$(__hostprogs),\
46 $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
47
48# Object (.o) files compiled from .c files
49host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
50
51# C++ code
52# C++ executables compiled from at least on .cc file
53# and zero or more .c files
54host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m)))
55
56# C++ Object (.o) files compiled from .cc files
57host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
58
59# Shared libaries (only .c supported)
60# Shared libraries (.so) - all .so files referenced in "xxx-objs"
61host-cshlib := $(sort $(filter %.so, $(host-cobjs)))
62# Remove .so files from "xxx-objs"
63host-cobjs := $(filter-out %.so,$(host-cobjs))
64
65#Object (.o) files used by the shared libaries
66host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
67
68__hostprogs := $(addprefix $(obj)/,$(__hostprogs))
69host-csingle := $(addprefix $(obj)/,$(host-csingle))
70host-cmulti := $(addprefix $(obj)/,$(host-cmulti))
71host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
72host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
73host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
74host-cshlib := $(addprefix $(obj)/,$(host-cshlib))
75host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs))
76obj-dirs := $(addprefix $(obj)/,$(obj-dirs))
77
78#####
79# Handle options to gcc. Support building with separate output directory
80
81_hostc_flags = $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS_$(*F).o)
82_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o)
83
84ifeq ($(KBUILD_SRC),)
85__hostc_flags = $(_hostc_flags)
86__hostcxx_flags = $(_hostcxx_flags)
87else
88__hostc_flags = -I$(obj) $(call flags,_hostc_flags)
89__hostcxx_flags = -I$(obj) $(call flags,_hostcxx_flags)
90endif
91
92hostc_flags = -Wp,-MD,$(depfile) $(__hostc_flags)
93hostcxx_flags = -Wp,-MD,$(depfile) $(__hostcxx_flags)
94
95#####
96# Compile programs on the host
97
98# Create executable from a single .c file
99# host-csingle -> Executable
100quiet_cmd_host-csingle = HOSTCC $@
101 cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \
102 $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
103$(host-csingle): %: %.c FORCE
104 $(call if_changed_dep,host-csingle)
105
106# Link an executable based on list of .o files, all plain c
107# host-cmulti -> executable
108quiet_cmd_host-cmulti = HOSTLD $@
109 cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
110 $(addprefix $(obj)/,$($(@F)-objs)) \
111 $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
112$(host-cmulti): %: $(host-cobjs) $(host-cshlib) FORCE
113 $(call if_changed,host-cmulti)
114
115# Create .o file from a single .c file
116# host-cobjs -> .o
117quiet_cmd_host-cobjs = HOSTCC $@
118 cmd_host-cobjs = $(HOSTCC) $(hostc_flags) -c -o $@ $<
119$(host-cobjs): %.o: %.c FORCE
120 $(call if_changed_dep,host-cobjs)
121
122# Link an executable based on list of .o files, a mixture of .c and .cc
123# host-cxxmulti -> executable
124quiet_cmd_host-cxxmulti = HOSTLD $@
125 cmd_host-cxxmulti = $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
126 $(foreach o,objs cxxobjs,\
127 $(addprefix $(obj)/,$($(@F)-$(o)))) \
128 $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
129$(host-cxxmulti): %: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
130 $(call if_changed,host-cxxmulti)
131
132# Create .o file from a single .cc (C++) file
133quiet_cmd_host-cxxobjs = HOSTCXX $@
134 cmd_host-cxxobjs = $(HOSTCXX) $(hostcxx_flags) -c -o $@ $<
135$(host-cxxobjs): %.o: %.cc FORCE
136 $(call if_changed_dep,host-cxxobjs)
137
138# Compile .c file, create position independent .o file
139# host-cshobjs -> .o
140quiet_cmd_host-cshobjs = HOSTCC -fPIC $@
141 cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
142$(host-cshobjs): %.o: %.c FORCE
143 $(call if_changed_dep,host-cshobjs)
144
145# Link a shared library, based on position independent .o files
146# *.o -> .so shared library (host-cshlib)
147quiet_cmd_host-cshlib = HOSTLLD -shared $@
148 cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
149 $(addprefix $(obj)/,$($(@F:.so=-objs))) \
150 $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
151$(host-cshlib): %: $(host-cshobjs) FORCE
152 $(call if_changed,host-cshlib)
153
154targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
155 $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs)
156
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
new file mode 100644
index 000000000..2cb4935e8
--- /dev/null
+++ b/scripts/Makefile.lib
@@ -0,0 +1,165 @@
1# Backward compatibility - to be removed...
2extra-y += $(EXTRA_TARGETS)
3# Figure out what we need to build from the various variables
4# ===========================================================================
5
6# When an object is listed to be built compiled-in and modular,
7# only build the compiled-in version
8
9obj-m := $(filter-out $(obj-y),$(obj-m))
10
11# Libraries are always collected in one lib file.
12# Filter out objects already built-in
13
14lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))
15
16
17# Handle objects in subdirs
18# ---------------------------------------------------------------------------
19# o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o
20# and add the directory to the list of dirs to descend into: $(subdir-y)
21# o if we encounter foo/ in $(obj-m), remove it from $(obj-m)
22# and add the directory to the list of dirs to descend into: $(subdir-m)
23
24__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
25subdir-y += $(__subdir-y)
26__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
27subdir-m += $(__subdir-m)
28obj-y := $(patsubst %/, %/built-in.o, $(obj-y))
29obj-m := $(filter-out %/, $(obj-m))
30
31# Subdirectories we need to descend into
32
33subdir-ym := $(sort $(subdir-y) $(subdir-m))
34
35# if $(foo-objs) exists, foo.o is a composite object
36multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
37multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
38multi-used := $(multi-used-y) $(multi-used-m)
39single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m)))
40
41# Build list of the parts of our composite objects, our composite
42# objects depend on those (obviously)
43multi-objs-y := $(foreach m, $(multi-used-y), $($(m:.o=-objs)) $($(m:.o=-y)))
44multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y)))
45multi-objs := $(multi-objs-y) $(multi-objs-m)
46
47# $(subdir-obj-y) is the list of objects in $(obj-y) which do not live
48# in the local directory
49subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)))
50
51# $(obj-dirs) is a list of directories that contain object files
52obj-dirs := $(dir $(multi-objs) $(subdir-obj-y))
53
54# Replace multi-part objects by their individual parts, look at local dir only
55real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y)
56real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
57
58# Add subdir path
59
60extra-y := $(addprefix $(obj)/,$(extra-y))
61always := $(addprefix $(obj)/,$(always))
62targets := $(addprefix $(obj)/,$(targets))
63obj-y := $(addprefix $(obj)/,$(obj-y))
64obj-m := $(addprefix $(obj)/,$(obj-m))
65lib-y := $(addprefix $(obj)/,$(lib-y))
66subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y))
67real-objs-y := $(addprefix $(obj)/,$(real-objs-y))
68real-objs-m := $(addprefix $(obj)/,$(real-objs-m))
69single-used-m := $(addprefix $(obj)/,$(single-used-m))
70multi-used-y := $(addprefix $(obj)/,$(multi-used-y))
71multi-used-m := $(addprefix $(obj)/,$(multi-used-m))
72multi-objs-y := $(addprefix $(obj)/,$(multi-objs-y))
73multi-objs-m := $(addprefix $(obj)/,$(multi-objs-m))
74subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
75obj-dirs := $(addprefix $(obj)/,$(obj-dirs))
76
77# These flags are needed for modversions and compiling, so we define them here
78# already
79# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will
80# end up in (or would, if it gets compiled in)
81# Note: It's possible that one object gets potentially linked into more
82# than one module. In that case KBUILD_MODNAME will be set to foo_bar,
83# where foo and bar are the name of the modules.
84name-fix = $(subst $(comma),_,$(subst -,_,$1))
85basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(*F)))"
86modname_flags = $(if $(filter 1,$(words $(modname))),\
87 -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
88
89_c_flags = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o)
90_a_flags = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
91_cpp_flags = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F))
92
93# If building the kernel in a separate objtree expand all occurrences
94# of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
95
96ifeq ($(KBUILD_SRC),)
97__c_flags = $(_c_flags)
98__a_flags = $(_a_flags)
99__cpp_flags = $(_cpp_flags)
100else
101
102# -I$(obj) locates generated .h files
103# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files
104# and locates generated .h files
105# FIXME: Replace both with specific CFLAGS* statements in the makefiles
106__c_flags = $(call addtree,-I$(obj)) $(call flags,_c_flags)
107__a_flags = $(call flags,_a_flags)
108__cpp_flags = $(call flags,_cpp_flags)
109endif
110
111c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
112 $(__c_flags) $(modkern_cflags) \
113 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
114
115a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
116 $(__a_flags) $(modkern_aflags)
117
118cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
119
120ld_flags = $(LDFLAGS) $(EXTRA_LDFLAGS)
121
122# Finds the multi-part object the current object will be linked into
123modname-multi = $(sort $(foreach m,$(multi-used),\
124 $(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=))))
125
126# Shipped files
127# ===========================================================================
128
129quiet_cmd_shipped = SHIPPED $@
130cmd_shipped = cat $< > $@
131
132$(obj)/%:: $(src)/%_shipped
133 $(call cmd,shipped)
134
135# Commands useful for building a boot image
136# ===========================================================================
137#
138# Use as following:
139#
140# target: source(s) FORCE
141# $(if_changed,ld/objcopy/gzip)
142#
143# and add target to EXTRA_TARGETS so that we know we have to
144# read in the saved command line
145
146# Linking
147# ---------------------------------------------------------------------------
148
149quiet_cmd_ld = LD $@
150cmd_ld = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) \
151 $(filter-out FORCE,$^) -o $@
152
153# Objcopy
154# ---------------------------------------------------------------------------
155
156quiet_cmd_objcopy = OBJCOPY $@
157cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
158
159# Gzip
160# ---------------------------------------------------------------------------
161
162quiet_cmd_gzip = GZIP $@
163cmd_gzip = gzip -f -9 < $< > $@
164
165
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
new file mode 100644
index 000000000..f22e94c3a
--- /dev/null
+++ b/scripts/basic/Makefile
@@ -0,0 +1,18 @@
1###
2# Makefile.basic list the most basic programs used during the build process.
3# The programs listed herein is what is needed to do the basic stuff,
4# such as splitting .config and fix dependency file.
5# This initial step is needed to avoid files to be recompiled
6# when kernel configuration changes (which is what happens when
7# .config is included by main Makefile.
8# ---------------------------------------------------------------------------
9# fixdep: Used to generate dependency information during build process
10# split-include: Divide all config symbols up in a number of files in
11# include/config/...
12# docproc: Used in Documentation/docbook
13
14hostprogs-y := fixdep split-include docproc
15always := $(hostprogs-y)
16
17# fixdep is needed to compile other host programs
18$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c
new file mode 100644
index 000000000..cb02baa63
--- /dev/null
+++ b/scripts/basic/docproc.c
@@ -0,0 +1,398 @@
1/*
2 * docproc is a simple preprocessor for the template files
3 * used as placeholders for the kernel internal documentation.
4 * docproc is used for documentation-frontend and
5 * dependency-generator.
6 * The two usages have in common that they require
7 * some knowledge of the .tmpl syntax, therefore they
8 * are kept together.
9 *
10 * documentation-frontend
11 * Scans the template file and call kernel-doc for
12 * all occurrences of ![EIF]file
13 * Beforehand each referenced file are scanned for
14 * any exported sympols "EXPORT_SYMBOL()" statements.
15 * This is used to create proper -function and
16 * -nofunction arguments in calls to kernel-doc.
17 * Usage: docproc doc file.tmpl
18 *
19 * dependency-generator:
20 * Scans the template file and list all files
21 * referenced in a format recognized by make.
22 * Usage: docproc depend file.tmpl
23 * Writes dependency information to stdout
24 * in the following format:
25 * file.tmpl src.c src2.c
26 * The filenames are obtained from the following constructs:
27 * !Efilename
28 * !Ifilename
29 * !Dfilename
30 * !Ffilename
31 *
32 */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <ctype.h>
38#include <unistd.h>
39#include <limits.h>
40#include <sys/types.h>
41#include <sys/wait.h>
42
43/* exitstatus is used to keep track of any failing calls to kernel-doc,
44 * but execution continues. */
45int exitstatus = 0;
46
47typedef void DFL(char *);
48DFL *defaultline;
49
50typedef void FILEONLY(char * file);
51FILEONLY *internalfunctions;
52FILEONLY *externalfunctions;
53FILEONLY *symbolsonly;
54
55typedef void FILELINE(char * file, char * line);
56FILELINE * singlefunctions;
57FILELINE * entity_system;
58
59#define MAXLINESZ 2048
60#define MAXFILES 250
61#define KERNELDOCPATH "scripts/"
62#define KERNELDOC "kernel-doc"
63#define DOCBOOK "-docbook"
64#define FUNCTION "-function"
65#define NOFUNCTION "-nofunction"
66
67void usage (void)
68{
69 fprintf(stderr, "Usage: docproc {doc|depend} file\n");
70 fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
71 fprintf(stderr, "doc: frontend when generating kernel documentation\n");
72 fprintf(stderr, "depend: generate list of files referenced within file\n");
73}
74
75/*
76 * Execute kernel-doc with parameters givin in svec
77 */
78void exec_kernel_doc(char **svec)
79{
80 pid_t pid;
81 int ret;
82 char real_filename[PATH_MAX + 1];
83 /* Make sure output generated so far are flushed */
84 fflush(stdout);
85 switch(pid=fork()) {
86 case -1:
87 perror("fork");
88 exit(1);
89 case 0:
90 memset(real_filename, 0, sizeof(real_filename));
91 strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
92 strncat(real_filename, KERNELDOCPATH KERNELDOC,
93 PATH_MAX - strlen(real_filename));
94 execvp(real_filename, svec);
95 fprintf(stderr, "exec ");
96 perror(real_filename);
97 exit(1);
98 default:
99 waitpid(pid, &ret ,0);
100 }
101 if (WIFEXITED(ret))
102 exitstatus |= WEXITSTATUS(ret);
103 else
104 exitstatus = 0xff;
105}
106
107/* Types used to create list of all exported symbols in a number of files */
108struct symbols
109{
110 char *name;
111};
112
113struct symfile
114{
115 char *filename;
116 struct symbols *symbollist;
117 int symbolcnt;
118};
119
120struct symfile symfilelist[MAXFILES];
121int symfilecnt = 0;
122
123void add_new_symbol(struct symfile *sym, char * symname)
124{
125 sym->symbollist =
126 realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
127 sym->symbollist[sym->symbolcnt++].name = strdup(symname);
128}
129
130/* Add a filename to the list */
131struct symfile * add_new_file(char * filename)
132{
133 symfilelist[symfilecnt++].filename = strdup(filename);
134 return &symfilelist[symfilecnt - 1];
135}
136/* Check if file already are present in the list */
137struct symfile * filename_exist(char * filename)
138{
139 int i;
140 for (i=0; i < symfilecnt; i++)
141 if (strcmp(symfilelist[i].filename, filename) == 0)
142 return &symfilelist[i];
143 return NULL;
144}
145
146/*
147 * List all files referenced within the template file.
148 * Files are separated by tabs.
149 */
150void adddep(char * file) { printf("\t%s", file); }
151void adddep2(char * file, char * line) { line = line; adddep(file); }
152void noaction(char * line) { line = line; }
153void noaction2(char * file, char * line) { file = file; line = line; }
154
155/* Echo the line without further action */
156void printline(char * line) { printf("%s", line); }
157
158/*
159 * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL
160 * in filename.
161 * All symbols located are stored in symfilelist.
162 */
163void find_export_symbols(char * filename)
164{
165 FILE * fp;
166 struct symfile *sym;
167 char line[MAXLINESZ];
168 if (filename_exist(filename) == NULL) {
169 char real_filename[PATH_MAX + 1];
170 memset(real_filename, 0, sizeof(real_filename));
171 strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
172 strncat(real_filename, filename,
173 PATH_MAX - strlen(real_filename));
174 sym = add_new_file(filename);
175 fp = fopen(real_filename, "r");
176 if (fp == NULL)
177 {
178 fprintf(stderr, "docproc: ");
179 perror(real_filename);
180 }
181 while(fgets(line, MAXLINESZ, fp)) {
182 char *p;
183 char *e;
184 if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
185 ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
186 /* Skip EXPORT_SYMBOL{_GPL} */
187 while (isalnum(*p) || *p == '_')
188 p++;
189 /* Remove paranteses and additional ws */
190 while (isspace(*p))
191 p++;
192 if (*p != '(')
193 continue; /* Syntax error? */
194 else
195 p++;
196 while (isspace(*p))
197 p++;
198 e = p;
199 while (isalnum(*e) || *e == '_')
200 e++;
201 *e = '\0';
202 add_new_symbol(sym, p);
203 }
204 }
205 fclose(fp);
206 }
207}
208
209/*
210 * Document all external or internal functions in a file.
211 * Call kernel-doc with following parameters:
212 * kernel-doc -docbook -nofunction function_name1 filename
213 * function names are obtained from all the the src files
214 * by find_export_symbols.
215 * intfunc uses -nofunction
216 * extfunc uses -function
217 */
218void docfunctions(char * filename, char * type)
219{
220 int i,j;
221 int symcnt = 0;
222 int idx = 0;
223 char **vec;
224
225 for (i=0; i <= symfilecnt; i++)
226 symcnt += symfilelist[i].symbolcnt;
227 vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*));
228 if (vec == NULL) {
229 perror("docproc: ");
230 exit(1);
231 }
232 vec[idx++] = KERNELDOC;
233 vec[idx++] = DOCBOOK;
234 for (i=0; i < symfilecnt; i++) {
235 struct symfile * sym = &symfilelist[i];
236 for (j=0; j < sym->symbolcnt; j++) {
237 vec[idx++] = type;
238 vec[idx++] = sym->symbollist[j].name;
239 }
240 }
241 vec[idx++] = filename;
242 vec[idx] = NULL;
243 printf("<!-- %s -->\n", filename);
244 exec_kernel_doc(vec);
245 fflush(stdout);
246 free(vec);
247}
248void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); }
249void extfunc(char * filename) { docfunctions(filename, FUNCTION); }
250
251/*
252 * Document spåecific function(s) in a file.
253 * Call kernel-doc with the following parameters:
254 * kernel-doc -docbook -function function1 [-function function2]
255 */
256void singfunc(char * filename, char * line)
257{
258 char *vec[200]; /* Enough for specific functions */
259 int i, idx = 0;
260 int startofsym = 1;
261 vec[idx++] = KERNELDOC;
262 vec[idx++] = DOCBOOK;
263
264 /* Split line up in individual parameters preceeded by FUNCTION */
265 for (i=0; line[i]; i++) {
266 if (isspace(line[i])) {
267 line[i] = '\0';
268 startofsym = 1;
269 continue;
270 }
271 if (startofsym) {
272 startofsym = 0;
273 vec[idx++] = FUNCTION;
274 vec[idx++] = &line[i];
275 }
276 }
277 vec[idx++] = filename;
278 vec[idx] = NULL;
279 exec_kernel_doc(vec);
280}
281
282/*
283 * Parse file, calling action specific functions for:
284 * 1) Lines containing !E
285 * 2) Lines containing !I
286 * 3) Lines containing !D
287 * 4) Lines containing !F
288 * 5) Default lines - lines not matching the above
289 */
290void parse_file(FILE *infile)
291{
292 char line[MAXLINESZ];
293 char * s;
294 while(fgets(line, MAXLINESZ, infile)) {
295 if (line[0] == '!') {
296 s = line + 2;
297 switch (line[1]) {
298 case 'E':
299 while (*s && !isspace(*s)) s++;
300 *s = '\0';
301 externalfunctions(line+2);
302 break;
303 case 'I':
304 while (*s && !isspace(*s)) s++;
305 *s = '\0';
306 internalfunctions(line+2);
307 break;
308 case 'D':
309 while (*s && !isspace(*s)) s++;
310 *s = '\0';
311 symbolsonly(line+2);
312 break;
313 case 'F':
314 /* filename */
315 while (*s && !isspace(*s)) s++;
316 *s++ = '\0';
317 /* function names */
318 while (isspace(*s))
319 s++;
320 singlefunctions(line +2, s);
321 break;
322 default:
323 defaultline(line);
324 }
325 }
326 else {
327 defaultline(line);
328 }
329 }
330 fflush(stdout);
331}
332
333
334int main(int argc, char *argv[])
335{
336 FILE * infile;
337 if (argc != 3) {
338 usage();
339 exit(1);
340 }
341 /* Open file, exit on error */
342 infile = fopen(argv[2], "r");
343 if (infile == NULL) {
344 fprintf(stderr, "docproc: ");
345 perror(argv[2]);
346 exit(2);
347 }
348
349 if (strcmp("doc", argv[1]) == 0)
350 {
351 /* Need to do this in two passes.
352 * First pass is used to collect all symbols exported
353 * in the various files.
354 * Second pass generate the documentation.
355 * This is required because function are declared
356 * and exported in different files :-((
357 */
358 /* Collect symbols */
359 defaultline = noaction;
360 internalfunctions = find_export_symbols;
361 externalfunctions = find_export_symbols;
362 symbolsonly = find_export_symbols;
363 singlefunctions = noaction2;
364 parse_file(infile);
365
366 /* Rewind to start from beginning of file again */
367 fseek(infile, 0, SEEK_SET);
368 defaultline = printline;
369 internalfunctions = intfunc;
370 externalfunctions = extfunc;
371 symbolsonly = printline;
372 singlefunctions = singfunc;
373
374 parse_file(infile);
375 }
376 else if (strcmp("depend", argv[1]) == 0)
377 {
378 /* Create first part of dependency chain
379 * file.tmpl */
380 printf("%s\t", argv[2]);
381 defaultline = noaction;
382 internalfunctions = adddep;
383 externalfunctions = adddep;
384 symbolsonly = adddep;
385 singlefunctions = adddep2;
386 parse_file(infile);
387 printf("\n");
388 }
389 else
390 {
391 fprintf(stderr, "Unknown option: %s\n", argv[1]);
392 exit(1);
393 }
394 fclose(infile);
395 fflush(stdout);
396 return exitstatus;
397}
398
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
new file mode 100644
index 000000000..cc2c6541b
--- /dev/null
+++ b/scripts/basic/fixdep.c
@@ -0,0 +1,393 @@
1/*
2 * "Optimize" a list of dependencies as spit out by gcc -MD
3 * for the kernel build
4 * ===========================================================================
5 *
6 * Author Kai Germaschewski
7 * Copyright 2002 by Kai Germaschewski <kai.germaschewski@gmx.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 *
13 * Introduction:
14 *
15 * gcc produces a very nice and correct list of dependencies which
16 * tells make when to remake a file.
17 *
18 * To use this list as-is however has the drawback that virtually
19 * every file in the kernel includes <linux/config.h> which then again
20 * includes <linux/autoconf.h>
21 *
22 * If the user re-runs make *config, linux/autoconf.h will be
23 * regenerated. make notices that and will rebuild every file which
24 * includes autoconf.h, i.e. basically all files. This is extremely
25 * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
26 *
27 * So we play the same trick that "mkdep" played before. We replace
28 * the dependency on linux/autoconf.h by a dependency on every config
29 * option which is mentioned in any of the listed prequisites.
30 *
31 * To be exact, split-include populates a tree in include/config/,
32 * e.g. include/config/his/driver.h, which contains the #define/#undef
33 * for the CONFIG_HIS_DRIVER option.
34 *
35 * So if the user changes his CONFIG_HIS_DRIVER option, only the objects
36 * which depend on "include/linux/config/his/driver.h" will be rebuilt,
37 * so most likely only his driver ;-)
38 *
39 * The idea above dates, by the way, back to Michael E Chastain, AFAIK.
40 *
41 * So to get dependencies right, there are two issues:
42 * o if any of the files the compiler read changed, we need to rebuild
43 * o if the command line given to the compile the file changed, we
44 * better rebuild as well.
45 *
46 * The former is handled by using the -MD output, the later by saving
47 * the command line used to compile the old object and comparing it
48 * to the one we would now use.
49 *
50 * Again, also this idea is pretty old and has been discussed on
51 * kbuild-devel a long time ago. I don't have a sensibly working
52 * internet connection right now, so I rather don't mention names
53 * without double checking.
54 *
55 * This code here has been based partially based on mkdep.c, which
56 * says the following about its history:
57 *
58 * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
59 * This is a C version of syncdep.pl by Werner Almesberger.
60 *
61 *
62 * It is invoked as
63 *
64 * fixdep <depfile> <target> <cmdline>
65 *
66 * and will read the dependency file <depfile>
67 *
68 * The transformed dependency snipped is written to stdout.
69 *
70 * It first generates a line
71 *
72 * cmd_<target> = <cmdline>
73 *
74 * and then basically copies the .<target>.d file to stdout, in the
75 * process filtering out the dependency on linux/autoconf.h and adding
76 * dependencies on include/config/my/option.h for every
77 * CONFIG_MY_OPTION encountered in any of the prequisites.
78 *
79 * It will also filter out all the dependencies on *.ver. We need
80 * to make sure that the generated version checksum are globally up
81 * to date before even starting the recursive build, so it's too late
82 * at this point anyway.
83 *
84 * The algorithm to grep for "CONFIG_..." is bit unusual, but should
85 * be fast ;-) We don't even try to really parse the header files, but
86 * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
87 * be picked up as well. It's not a problem with respect to
88 * correctness, since that can only give too many dependencies, thus
89 * we cannot miss a rebuild. Since people tend to not mention totally
90 * unrelated CONFIG_ options all over the place, it's not an
91 * efficiency problem either.
92 *
93 * (Note: it'd be easy to port over the complete mkdep state machine,
94 * but I don't think the added complexity is worth it)
95 */
96/*
97 * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto
98 * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not
99 * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as
100 * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h,
101 * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that
102 * those files will have correct dependencies.
103 */
104
105#include <sys/types.h>
106#include <sys/stat.h>
107#include <sys/mman.h>
108#include <unistd.h>
109#include <fcntl.h>
110#include <string.h>
111#include <stdlib.h>
112#include <stdio.h>
113#include <limits.h>
114#include <ctype.h>
115#include <arpa/inet.h>
116
117#define INT_CONF ntohl(0x434f4e46)
118#define INT_ONFI ntohl(0x4f4e4649)
119#define INT_NFIG ntohl(0x4e464947)
120#define INT_FIG_ ntohl(0x4649475f)
121
122char *target;
123char *depfile;
124char *cmdline;
125
126void usage(void)
127
128{
129 fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
130 exit(1);
131}
132
133/*
134 * Print out the commandline prefixed with cmd_<target filename> :=
135 */
136void print_cmdline(void)
137{
138 printf("cmd_%s := %s\n\n", target, cmdline);
139}
140
141char * str_config = NULL;
142int size_config = 0;
143int len_config = 0;
144
145/*
146 * Grow the configuration string to a desired length.
147 * Usually the first growth is plenty.
148 */
149void grow_config(int len)
150{
151 while (len_config + len > size_config) {
152 if (size_config == 0)
153 size_config = 2048;
154 str_config = realloc(str_config, size_config *= 2);
155 if (str_config == NULL)
156 { perror("fixdep:malloc"); exit(1); }
157 }
158}
159
160
161
162/*
163 * Lookup a value in the configuration string.
164 */
165int is_defined_config(const char * name, int len)
166{
167 const char * pconfig;
168 const char * plast = str_config + len_config - len;
169 for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
170 if (pconfig[ -1] == '\n'
171 && pconfig[len] == '\n'
172 && !memcmp(pconfig, name, len))
173 return 1;
174 }
175 return 0;
176}
177
178/*
179 * Add a new value to the configuration string.
180 */
181void define_config(const char * name, int len)
182{
183 grow_config(len + 1);
184
185 memcpy(str_config+len_config, name, len);
186 len_config += len;
187 str_config[len_config++] = '\n';
188}
189
190/*
191 * Clear the set of configuration strings.
192 */
193void clear_config(void)
194{
195 len_config = 0;
196 define_config("", 0);
197}
198
199/*
200 * Record the use of a CONFIG_* word.
201 */
202void use_config(char *m, int slen)
203{
204 char s[PATH_MAX];
205 char *p;
206
207 if (is_defined_config(m, slen))
208 return;
209
210 define_config(m, slen);
211
212 memcpy(s, m, slen); s[slen] = 0;
213
214 for (p = s; p < s + slen; p++) {
215 if (*p == '_')
216 *p = '/';
217 else
218 *p = tolower((int)*p);
219 }
220 printf(" $(wildcard include/config/%s.h) \\\n", s);
221}
222
223void parse_config_file(char *map, size_t len)
224{
225 int *end = (int *) (map + len);
226 /* start at +1, so that p can never be < map */
227 int *m = (int *) map + 1;
228 char *p, *q;
229
230 for (; m < end; m++) {
231 if (*m == INT_CONF) { p = (char *) m ; goto conf; }
232 if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
233 if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
234 if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
235 continue;
236 conf:
237 if (p > map + len - 7)
238 continue;
239 if (memcmp(p, "CONFIG_", 7))
240 continue;
241 for (q = p + 7; q < map + len; q++) {
242 if (!(isalnum(*q) || *q == '_'))
243 goto found;
244 }
245 continue;
246
247 found:
248 use_config(p+7, q-p-7);
249 }
250}
251
252/* test is s ends in sub */
253int strrcmp(char *s, char *sub)
254{
255 int slen = strlen(s);
256 int sublen = strlen(sub);
257
258 if (sublen > slen)
259 return 1;
260
261 return memcmp(s + slen - sublen, sub, sublen);
262}
263
264void do_config_file(char *filename)
265{
266 struct stat st;
267 int fd;
268 void *map;
269
270 fd = open(filename, O_RDONLY);
271 if (fd < 0) {
272 fprintf(stderr, "fixdep: ");
273 perror(filename);
274 exit(2);
275 }
276 fstat(fd, &st);
277 if (st.st_size == 0) {
278 close(fd);
279 return;
280 }
281 map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
282 if ((long) map == -1) {
283 perror("fixdep: mmap");
284 close(fd);
285 return;
286 }
287
288 parse_config_file(map, st.st_size);
289
290 munmap(map, st.st_size);
291
292 close(fd);
293}
294
295void parse_dep_file(void *map, size_t len)
296{
297 char *m = map;
298 char *end = m + len;
299 char *p;
300 char s[PATH_MAX];
301
302 p = strchr(m, ':');
303 if (!p) {
304 fprintf(stderr, "fixdep: parse error\n");
305 exit(1);
306 }
307 memcpy(s, m, p-m); s[p-m] = 0;
308 printf("deps_%s := \\\n", target);
309 m = p+1;
310
311 clear_config();
312
313 while (m < end) {
314 while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
315 m++;
316 p = m;
317 while (p < end && *p != ' ') p++;
318 if (p == end) {
319 do p--; while (!isalnum(*p));
320 p++;
321 }
322 memcpy(s, m, p-m); s[p-m] = 0;
323 if (strrcmp(s, "include/autoconf.h") &&
324 strrcmp(s, "arch/um/include/uml-config.h") &&
325 strrcmp(s, ".ver")) {
326 printf(" %s \\\n", s);
327 do_config_file(s);
328 }
329 m = p + 1;
330 }
331 printf("\n%s: $(deps_%s)\n\n", target, target);
332 printf("$(deps_%s):\n", target);
333}
334
335void print_deps(void)
336{
337 struct stat st;
338 int fd;
339 void *map;
340
341 fd = open(depfile, O_RDONLY);
342 if (fd < 0) {
343 fprintf(stderr, "fixdep: ");
344 perror(depfile);
345 exit(2);
346 }
347 fstat(fd, &st);
348 if (st.st_size == 0) {
349 fprintf(stderr,"fixdep: %s is empty\n",depfile);
350 close(fd);
351 return;
352 }
353 map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
354 if ((long) map == -1) {
355 perror("fixdep: mmap");
356 close(fd);
357 return;
358 }
359
360 parse_dep_file(map, st.st_size);
361
362 munmap(map, st.st_size);
363
364 close(fd);
365}
366
367void traps(void)
368{
369 static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
370
371 if (*(int *)test != INT_CONF) {
372 fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n",
373 *(int *)test);
374 exit(2);
375 }
376}
377
378int main(int argc, char *argv[])
379{
380 traps();
381
382 if (argc != 4)
383 usage();
384
385 depfile = argv[1];
386 target = argv[2];
387 cmdline = argv[3];
388
389 print_cmdline();
390 print_deps();
391
392 return 0;
393}
diff --git a/scripts/basic/split-include.c b/scripts/basic/split-include.c
new file mode 100644
index 000000000..459c45276
--- /dev/null
+++ b/scripts/basic/split-include.c
@@ -0,0 +1,226 @@
1/*
2 * split-include.c
3 *
4 * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
5 * This is a C version of syncdep.pl by Werner Almesberger.
6 *
7 * This program takes autoconf.h as input and outputs a directory full
8 * of one-line include files, merging onto the old values.
9 *
10 * Think of the configuration options as key-value pairs. Then there
11 * are five cases:
12 *
13 * key old value new value action
14 *
15 * KEY-1 VALUE-1 VALUE-1 leave file alone
16 * KEY-2 VALUE-2A VALUE-2B write VALUE-2B into file
17 * KEY-3 - VALUE-3 write VALUE-3 into file
18 * KEY-4 VALUE-4 - write an empty file
19 * KEY-5 (empty) - leave old empty file alone
20 */
21
22#include <sys/stat.h>
23#include <sys/types.h>
24
25#include <ctype.h>
26#include <errno.h>
27#include <fcntl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32
33#define ERROR_EXIT(strExit) \
34 { \
35 const int errnoSave = errno; \
36 fprintf(stderr, "%s: ", str_my_name); \
37 errno = errnoSave; \
38 perror((strExit)); \
39 exit(1); \
40 }
41
42
43
44int main(int argc, const char * argv [])
45{
46 const char * str_my_name;
47 const char * str_file_autoconf;
48 const char * str_dir_config;
49
50 FILE * fp_config;
51 FILE * fp_target;
52 FILE * fp_find;
53
54 int buffer_size;
55
56 char * line;
57 char * old_line;
58 char * list_target;
59 char * ptarget;
60
61 struct stat stat_buf;
62
63 /* Check arg count. */
64 if (argc != 3)
65 {
66 fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]);
67 exit(1);
68 }
69
70 str_my_name = argv[0];
71 str_file_autoconf = argv[1];
72 str_dir_config = argv[2];
73
74 /* Find a buffer size. */
75 if (stat(str_file_autoconf, &stat_buf) != 0)
76 ERROR_EXIT(str_file_autoconf);
77 buffer_size = 2 * stat_buf.st_size + 4096;
78
79 /* Allocate buffers. */
80 if ( (line = malloc(buffer_size)) == NULL
81 || (old_line = malloc(buffer_size)) == NULL
82 || (list_target = malloc(buffer_size)) == NULL )
83 ERROR_EXIT(str_file_autoconf);
84
85 /* Open autoconfig file. */
86 if ((fp_config = fopen(str_file_autoconf, "r")) == NULL)
87 ERROR_EXIT(str_file_autoconf);
88
89 /* Make output directory if needed. */
90 if (stat(str_dir_config, &stat_buf) != 0)
91 {
92 if (mkdir(str_dir_config, 0755) != 0)
93 ERROR_EXIT(str_dir_config);
94 }
95
96 /* Change to output directory. */
97 if (chdir(str_dir_config) != 0)
98 ERROR_EXIT(str_dir_config);
99
100 /* Put initial separator into target list. */
101 ptarget = list_target;
102 *ptarget++ = '\n';
103
104 /* Read config lines. */
105 while (fgets(line, buffer_size, fp_config))
106 {
107 const char * str_config;
108 int is_same;
109 int itarget;
110
111 if (line[0] != '#')
112 continue;
113 if ((str_config = strstr(line, "CONFIG_")) == NULL)
114 continue;
115
116 /* Make the output file name. */
117 str_config += sizeof("CONFIG_") - 1;
118 for (itarget = 0; !isspace(str_config[itarget]); itarget++)
119 {
120 int c = (unsigned char) str_config[itarget];
121 if (isupper(c)) c = tolower(c);
122 if (c == '_') c = '/';
123 ptarget[itarget] = c;
124 }
125 ptarget[itarget++] = '.';
126 ptarget[itarget++] = 'h';
127 ptarget[itarget++] = '\0';
128
129 /* Check for existing file. */
130 is_same = 0;
131 if ((fp_target = fopen(ptarget, "r")) != NULL)
132 {
133 fgets(old_line, buffer_size, fp_target);
134 if (fclose(fp_target) != 0)
135 ERROR_EXIT(ptarget);
136 if (!strcmp(line, old_line))
137 is_same = 1;
138 }
139
140 if (!is_same)
141 {
142 /* Auto-create directories. */
143 int islash;
144 for (islash = 0; islash < itarget; islash++)
145 {
146 if (ptarget[islash] == '/')
147 {
148 ptarget[islash] = '\0';
149 if (stat(ptarget, &stat_buf) != 0
150 && mkdir(ptarget, 0755) != 0)
151 ERROR_EXIT( ptarget );
152 ptarget[islash] = '/';
153 }
154 }
155
156 /* Write the file. */
157 if ((fp_target = fopen(ptarget, "w" )) == NULL)
158 ERROR_EXIT(ptarget);
159 fputs(line, fp_target);
160 if (ferror(fp_target) || fclose(fp_target) != 0)
161 ERROR_EXIT(ptarget);
162 }
163
164 /* Update target list */
165 ptarget += itarget;
166 *(ptarget-1) = '\n';
167 }
168
169 /*
170 * Close autoconfig file.
171 * Terminate the target list.
172 */
173 if (fclose(fp_config) != 0)
174 ERROR_EXIT(str_file_autoconf);
175 *ptarget = '\0';
176
177 /*
178 * Fix up existing files which have no new value.
179 * This is Case 4 and Case 5.
180 *
181 * I re-read the tree and filter it against list_target.
182 * This is crude. But it avoids data copies. Also, list_target
183 * is compact and contiguous, so it easily fits into cache.
184 *
185 * Notice that list_target contains strings separated by \n,
186 * with a \n before the first string and after the last.
187 * fgets gives the incoming names a terminating \n.
188 * So by having an initial \n, strstr will find exact matches.
189 */
190
191 fp_find = popen("find * -type f -name \"*.h\" -print", "r");
192 if (fp_find == 0)
193 ERROR_EXIT( "find" );
194
195 line[0] = '\n';
196 while (fgets(line+1, buffer_size, fp_find))
197 {
198 if (strstr(list_target, line) == NULL)
199 {
200 /*
201 * This is an old file with no CONFIG_* flag in autoconf.h.
202 */
203
204 /* First strip the \n. */
205 line[strlen(line)-1] = '\0';
206
207 /* Grab size. */
208 if (stat(line+1, &stat_buf) != 0)
209 ERROR_EXIT(line);
210
211 /* If file is not empty, make it empty and give it a fresh date. */
212 if (stat_buf.st_size != 0)
213 {
214 if ((fp_target = fopen(line+1, "w")) == NULL)
215 ERROR_EXIT(line);
216 if (fclose(fp_target) != 0)
217 ERROR_EXIT(line);
218 }
219 }
220 }
221
222 if (pclose(fp_find) != 0)
223 ERROR_EXIT("find");
224
225 return 0;
226}
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
new file mode 100644
index 000000000..a28414de8
--- /dev/null
+++ b/scripts/kconfig/Makefile
@@ -0,0 +1,254 @@
1# ===========================================================================
2# Kernel configuration targets
3# These targets are used from top-level makefile
4
5PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config
6
7xconfig: $(obj)/qconf
8 $< Config.in
9
10gconfig: $(obj)/gconf
11 $< Config.in
12
13menuconfig: $(obj)/mconf
14 $(Q)$(MAKE) $(build)=scripts/kconfig/lxdialog
15 $< Config.in
16
17config: $(obj)/conf
18 $< Config.in
19
20oldconfig: $(obj)/conf
21 $< -o Config.in
22
23silentoldconfig: $(obj)/conf
24 $< -s Config.in
25
26update-po-config: $(obj)/kxgettext
27 xgettext --default-domain=linux \
28 --add-comments --keyword=_ --keyword=N_ \
29 --files-from=scripts/kconfig/POTFILES.in \
30 --output scripts/kconfig/config.pot
31 $(Q)ln -fs Kconfig_i386 arch/um/Kconfig_arch
32 $(Q)for i in `ls arch/`; \
33 do \
34 scripts/kconfig/kxgettext arch/$$i/Kconfig \
35 | msguniq -o scripts/kconfig/linux_$${i}.pot; \
36 done
37 $(Q)msgcat scripts/kconfig/config.pot \
38 `find scripts/kconfig/ -type f -name linux_*.pot` \
39 --output scripts/kconfig/linux_raw.pot
40 $(Q)msguniq --sort-by-file scripts/kconfig/linux_raw.pot \
41 --output scripts/kconfig/linux.pot
42 $(Q)rm -f arch/um/Kconfig_arch
43 $(Q)rm -f scripts/kconfig/linux_*.pot scripts/kconfig/config.pot
44
45PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig
46
47randconfig: $(obj)/conf
48 $< -r Config.in
49
50allyesconfig: $(obj)/conf
51 $< -y Config.in
52
53allnoconfig: $(obj)/conf
54 $< -n Config.in
55
56allmodconfig: $(obj)/conf
57 $< -m Config.in
58
59defconfig: $(obj)/conf
60ifeq ($(KBUILD_DEFCONFIG),)
61 $< -d Config.in
62else
63 @echo *** Default configuration is based on '$(KBUILD_DEFCONFIG)'
64 $(Q)$< -D $(KBUILD_DEFCONFIG) Config.in
65endif
66
67%_defconfig: $(obj)/conf
68 $(Q)$< -D $@ Config.in
69
70# Help text used by make help
71help:
72 @echo ' config - Update current config utilising a line-oriented program'
73 @echo ' menuconfig - Update current config utilising a menu based program'
74 @echo ' xconfig - Update current config utilising a QT based front-end'
75 @echo ' gconfig - Update current config utilising a GTK based front-end'
76 @echo ' oldconfig - Update current config utilising a provided .config as base'
77 @echo ' randconfig - New config with random answer to all options'
78 @echo ' defconfig - New config with default answer to all options'
79 @echo ' allmodconfig - New config selecting modules when possible'
80 @echo ' allyesconfig - New config where all options are accepted with yes'
81 @echo ' allnoconfig - New config where all options are answered with no'
82
83# ===========================================================================
84# Shared Makefile for the various kconfig executables:
85# conf: Used for defconfig, oldconfig and related targets
86# mconf: Used for the mconfig target.
87# Utilizes the lxdialog package
88# qconf: Used for the xconfig target
89# Based on QT which needs to be installed to compile it
90# gconf: Used for the gconfig target
91# Based on GTK which needs to be installed to compile it
92# object files used by all kconfig flavours
93
94hostprogs-y := conf mconf qconf gconf kxgettext
95conf-objs := conf.o zconf.tab.o
96mconf-objs := mconf.o zconf.tab.o
97kxgettext-objs := kxgettext.o zconf.tab.o
98
99ifeq ($(MAKECMDGOALS),xconfig)
100 qconf-target := 1
101endif
102ifeq ($(MAKECMDGOALS),gconfig)
103 gconf-target := 1
104endif
105
106
107ifeq ($(qconf-target),1)
108qconf-cxxobjs := qconf.o
109qconf-objs := kconfig_load.o zconf.tab.o
110endif
111
112ifeq ($(gconf-target),1)
113gconf-objs := gconf.o kconfig_load.o zconf.tab.o
114endif
115
116clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \
117 .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c
118subdir- += lxdialog
119
120# Needed for systems without gettext
121KBUILD_HAVE_NLS := $(shell \
122 if echo "\#include <libintl.h>" | $(HOSTCC) $(HOSTCFLAGS) -E - > /dev/null 2>&1 ; \
123 then echo yes ; \
124 else echo no ; fi)
125ifeq ($(KBUILD_HAVE_NLS),no)
126HOSTCFLAGS += -DKBUILD_NO_NLS
127endif
128
129# generated files seem to need this to find local include files
130HOSTCFLAGS_lex.zconf.o := -I$(src)
131HOSTCFLAGS_zconf.tab.o := -I$(src)
132
133HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl
134HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
135
136HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
137HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
138 -D LKC_DIRECT_LINK
139
140$(obj)/qconf.o: $(obj)/.tmp_qtcheck
141
142ifeq ($(qconf-target),1)
143$(obj)/.tmp_qtcheck: $(src)/Makefile
144-include $(obj)/.tmp_qtcheck
145
146# QT needs some extra effort...
147$(obj)/.tmp_qtcheck:
148 @set -e; echo " CHECK qt"; dir=""; pkg=""; \
149 pkg-config --exists qt 2> /dev/null && pkg=qt; \
150 pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \
151 if [ -n "$$pkg" ]; then \
152 cflags="\$$(shell pkg-config $$pkg --cflags)"; \
153 libs="\$$(shell pkg-config $$pkg --libs)"; \
154 moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \
155 dir="$$(pkg-config $$pkg --variable=prefix)"; \
156 else \
157 for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \
158 if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
159 done; \
160 if [ -z "$$dir" ]; then \
161 echo "*"; \
162 echo "* Unable to find the QT installation. Please make sure that"; \
163 echo "* the QT development package is correctly installed and"; \
164 echo "* either install pkg-config or set the QTDIR environment"; \
165 echo "* variable to the correct location."; \
166 echo "*"; \
167 false; \
168 fi; \
169 libpath=$$dir/lib; lib=qt; osdir=""; \
170 $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \
171 osdir=x$$($(HOSTCXX) -print-multi-os-directory); \
172 test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \
173 test -f $$libpath/libqt-mt.so && lib=qt-mt; \
174 cflags="-I$$dir/include"; \
175 libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \
176 moc="$$dir/bin/moc"; \
177 fi; \
178 if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \
179 echo "*"; \
180 echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \
181 echo "*"; \
182 moc="/usr/bin/moc"; \
183 fi; \
184 echo "KC_QT_CFLAGS=$$cflags" > $@; \
185 echo "KC_QT_LIBS=$$libs" >> $@; \
186 echo "KC_QT_MOC=$$moc" >> $@
187endif
188
189$(obj)/gconf.o: $(obj)/.tmp_gtkcheck
190
191ifeq ($(gconf-target),1)
192-include $(obj)/.tmp_gtkcheck
193
194# GTK needs some extra effort, too...
195$(obj)/.tmp_gtkcheck:
196 @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \
197 if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \
198 touch $@; \
199 else \
200 echo "*"; \
201 echo "* GTK+ is present but version >= 2.0.0 is required."; \
202 echo "*"; \
203 false; \
204 fi \
205 else \
206 echo "*"; \
207 echo "* Unable to find the GTK+ installation. Please make sure that"; \
208 echo "* the GTK+ 2.0 development package is correctly installed..."; \
209 echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \
210 echo "*"; \
211 false; \
212 fi
213endif
214
215$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c
216
217$(obj)/kconfig_load.o: $(obj)/lkc_defs.h
218
219$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h
220
221$(obj)/gconf.o: $(obj)/lkc_defs.h
222
223$(obj)/%.moc: $(src)/%.h
224 $(KC_QT_MOC) -i $< -o $@
225
226$(obj)/lkc_defs.h: $(src)/lkc_proto.h
227 sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
228
229
230###
231# The following requires flex/bison/gperf
232# By default we use the _shipped versions, uncomment the following line if
233# you are modifying the flex/bison src.
234# LKC_GENPARSER := 1
235
236ifdef LKC_GENPARSER
237
238$(obj)/zconf.tab.c: $(src)/zconf.y
239$(obj)/lex.zconf.c: $(src)/zconf.l
240$(obj)/zconf.hash.c: $(src)/zconf.gperf
241
242%.tab.c: %.y
243 bison -l -b $* -p $(notdir $*) $<
244 cp $@ $@_shipped
245
246lex.%.c: %.l
247 flex -L -P$(notdir $*) -o$@ $<
248 cp $@ $@_shipped
249
250%.hash.c: %.gperf
251 gperf < $< > $@
252 cp $@ $@_shipped
253
254endif
diff --git a/scripts/kconfig/POTFILES.in b/scripts/kconfig/POTFILES.in
new file mode 100644
index 000000000..cc94e46a7
--- /dev/null
+++ b/scripts/kconfig/POTFILES.in
@@ -0,0 +1,5 @@
1scripts/kconfig/mconf.c
2scripts/kconfig/conf.c
3scripts/kconfig/confdata.c
4scripts/kconfig/gconf.c
5scripts/kconfig/qconf.cc
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
new file mode 100644
index 000000000..8012d1076
--- /dev/null
+++ b/scripts/kconfig/conf.c
@@ -0,0 +1,612 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <ctype.h>
7#include <stdlib.h>
8#include <stdio.h>
9#include <string.h>
10#include <unistd.h>
11#include <time.h>
12#include <sys/stat.h>
13
14#define LKC_DIRECT_LINK
15#include "lkc.h"
16
17static void conf(struct menu *menu);
18static void check_conf(struct menu *menu);
19
20enum {
21 ask_all,
22 ask_new,
23 ask_silent,
24 set_default,
25 set_yes,
26 set_mod,
27 set_no,
28 set_random
29} input_mode = ask_all;
30char *defconfig_file;
31
32static int indent = 1;
33static int valid_stdin = 1;
34static int conf_cnt;
35static char line[128];
36static struct menu *rootEntry;
37
38static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
39
40static void strip(char *str)
41{
42 char *p = str;
43 int l;
44
45 while ((isspace(*p)))
46 p++;
47 l = strlen(p);
48 if (p != str)
49 memmove(str, p, l + 1);
50 if (!l)
51 return;
52 p = str + l - 1;
53 while ((isspace(*p)))
54 *p-- = 0;
55}
56
57static void check_stdin(void)
58{
59 if (!valid_stdin && input_mode == ask_silent) {
60 printf(_("aborted!\n\n"));
61 printf(_("Console input/output is redirected. "));
62 printf(_("Run 'make oldconfig' to update configuration.\n\n"));
63 exit(1);
64 }
65}
66
67static void conf_askvalue(struct symbol *sym, const char *def)
68{
69 enum symbol_type type = sym_get_type(sym);
70 tristate val;
71
72 if (!sym_has_value(sym))
73 printf("(NEW) ");
74
75 line[0] = '\n';
76 line[1] = 0;
77
78 if (!sym_is_changable(sym)) {
79 printf("%s\n", def);
80 line[0] = '\n';
81 line[1] = 0;
82 return;
83 }
84
85 switch (input_mode) {
86 case set_no:
87 case set_mod:
88 case set_yes:
89 case set_random:
90 if (sym_has_value(sym)) {
91 printf("%s\n", def);
92 return;
93 }
94 break;
95 case ask_new:
96 case ask_silent:
97 if (sym_has_value(sym)) {
98 printf("%s\n", def);
99 return;
100 }
101 check_stdin();
102 case ask_all:
103 fflush(stdout);
104 fgets(line, 128, stdin);
105 return;
106 case set_default:
107 printf("%s\n", def);
108 return;
109 default:
110 break;
111 }
112
113 switch (type) {
114 case S_INT:
115 case S_HEX:
116 case S_STRING:
117 printf("%s\n", def);
118 return;
119 default:
120 ;
121 }
122 switch (input_mode) {
123 case set_yes:
124 if (sym_tristate_within_range(sym, yes)) {
125 line[0] = 'y';
126 line[1] = '\n';
127 line[2] = 0;
128 break;
129 }
130 case set_mod:
131 if (type == S_TRISTATE) {
132 if (sym_tristate_within_range(sym, mod)) {
133 line[0] = 'm';
134 line[1] = '\n';
135 line[2] = 0;
136 break;
137 }
138 } else {
139 if (sym_tristate_within_range(sym, yes)) {
140 line[0] = 'y';
141 line[1] = '\n';
142 line[2] = 0;
143 break;
144 }
145 }
146 case set_no:
147 if (sym_tristate_within_range(sym, no)) {
148 line[0] = 'n';
149 line[1] = '\n';
150 line[2] = 0;
151 break;
152 }
153 case set_random:
154 do {
155 val = (tristate)(random() % 3);
156 } while (!sym_tristate_within_range(sym, val));
157 switch (val) {
158 case no: line[0] = 'n'; break;
159 case mod: line[0] = 'm'; break;
160 case yes: line[0] = 'y'; break;
161 }
162 line[1] = '\n';
163 line[2] = 0;
164 break;
165 default:
166 break;
167 }
168 printf("%s", line);
169}
170
171int conf_string(struct menu *menu)
172{
173 struct symbol *sym = menu->sym;
174 const char *def, *help;
175
176 while (1) {
177 printf("%*s%s ", indent - 1, "", menu->prompt->text);
178 printf("(%s) ", sym->name);
179 def = sym_get_string_value(sym);
180 if (sym_get_string_value(sym))
181 printf("[%s] ", def);
182 conf_askvalue(sym, def);
183 switch (line[0]) {
184 case '\n':
185 break;
186 case '?':
187 /* print help */
188 if (line[1] == '\n') {
189 help = nohelp_text;
190 if (menu->sym->help)
191 help = menu->sym->help;
192 printf("\n%s\n", menu->sym->help);
193 def = NULL;
194 break;
195 }
196 default:
197 line[strlen(line)-1] = 0;
198 def = line;
199 }
200 if (def && sym_set_string_value(sym, def))
201 return 0;
202 }
203}
204
205static int conf_sym(struct menu *menu)
206{
207 struct symbol *sym = menu->sym;
208 int type;
209 tristate oldval, newval;
210 const char *help;
211
212 while (1) {
213 printf("%*s%s ", indent - 1, "", menu->prompt->text);
214 if (sym->name)
215 printf("(%s) ", sym->name);
216 type = sym_get_type(sym);
217 putchar('[');
218 oldval = sym_get_tristate_value(sym);
219 switch (oldval) {
220 case no:
221 putchar('N');
222 break;
223 case mod:
224 putchar('M');
225 break;
226 case yes:
227 putchar('Y');
228 break;
229 }
230 if (oldval != no && sym_tristate_within_range(sym, no))
231 printf("/n");
232 if (oldval != mod && sym_tristate_within_range(sym, mod))
233 printf("/m");
234 if (oldval != yes && sym_tristate_within_range(sym, yes))
235 printf("/y");
236 if (sym->help)
237 printf("/?");
238 printf("] ");
239 conf_askvalue(sym, sym_get_string_value(sym));
240 strip(line);
241
242 switch (line[0]) {
243 case 'n':
244 case 'N':
245 newval = no;
246 if (!line[1] || !strcmp(&line[1], "o"))
247 break;
248 continue;
249 case 'm':
250 case 'M':
251 newval = mod;
252 if (!line[1])
253 break;
254 continue;
255 case 'y':
256 case 'Y':
257 newval = yes;
258 if (!line[1] || !strcmp(&line[1], "es"))
259 break;
260 continue;
261 case 0:
262 newval = oldval;
263 break;
264 case '?':
265 goto help;
266 default:
267 continue;
268 }
269 if (sym_set_tristate_value(sym, newval))
270 return 0;
271help:
272 help = nohelp_text;
273 if (sym->help)
274 help = sym->help;
275 printf("\n%s\n", help);
276 }
277}
278
279static int conf_choice(struct menu *menu)
280{
281 struct symbol *sym, *def_sym;
282 struct menu *child;
283 int type;
284 bool is_new;
285
286 sym = menu->sym;
287 type = sym_get_type(sym);
288 is_new = !sym_has_value(sym);
289 if (sym_is_changable(sym)) {
290 conf_sym(menu);
291 sym_calc_value(sym);
292 switch (sym_get_tristate_value(sym)) {
293 case no:
294 return 1;
295 case mod:
296 return 0;
297 case yes:
298 break;
299 }
300 } else {
301 switch (sym_get_tristate_value(sym)) {
302 case no:
303 return 1;
304 case mod:
305 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
306 return 0;
307 case yes:
308 break;
309 }
310 }
311
312 while (1) {
313 int cnt, def;
314
315 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
316 def_sym = sym_get_choice_value(sym);
317 cnt = def = 0;
318 line[0] = 0;
319 for (child = menu->list; child; child = child->next) {
320 if (!menu_is_visible(child))
321 continue;
322 if (!child->sym) {
323 printf("%*c %s\n", indent, '*', menu_get_prompt(child));
324 continue;
325 }
326 cnt++;
327 if (child->sym == def_sym) {
328 def = cnt;
329 printf("%*c", indent, '>');
330 } else
331 printf("%*c", indent, ' ');
332 printf(" %d. %s", cnt, menu_get_prompt(child));
333 if (child->sym->name)
334 printf(" (%s)", child->sym->name);
335 if (!sym_has_value(child->sym))
336 printf(" (NEW)");
337 printf("\n");
338 }
339 printf("%*schoice", indent - 1, "");
340 if (cnt == 1) {
341 printf("[1]: 1\n");
342 goto conf_childs;
343 }
344 printf("[1-%d", cnt);
345 if (sym->help)
346 printf("?");
347 printf("]: ");
348 switch (input_mode) {
349 case ask_new:
350 case ask_silent:
351 if (!is_new) {
352 cnt = def;
353 printf("%d\n", cnt);
354 break;
355 }
356 check_stdin();
357 case ask_all:
358 fflush(stdout);
359 fgets(line, 128, stdin);
360 strip(line);
361 if (line[0] == '?') {
362 printf("\n%s\n", menu->sym->help ?
363 menu->sym->help : nohelp_text);
364 continue;
365 }
366 if (!line[0])
367 cnt = def;
368 else if (isdigit(line[0]))
369 cnt = atoi(line);
370 else
371 continue;
372 break;
373 case set_random:
374 def = (random() % cnt) + 1;
375 case set_default:
376 case set_yes:
377 case set_mod:
378 case set_no:
379 cnt = def;
380 printf("%d\n", cnt);
381 break;
382 }
383
384 conf_childs:
385 for (child = menu->list; child; child = child->next) {
386 if (!child->sym || !menu_is_visible(child))
387 continue;
388 if (!--cnt)
389 break;
390 }
391 if (!child)
392 continue;
393 if (line[strlen(line) - 1] == '?') {
394 printf("\n%s\n", child->sym->help ?
395 child->sym->help : nohelp_text);
396 continue;
397 }
398 sym_set_choice_value(sym, child->sym);
399 if (child->list) {
400 indent += 2;
401 conf(child->list);
402 indent -= 2;
403 }
404 return 1;
405 }
406}
407
408static void conf(struct menu *menu)
409{
410 struct symbol *sym;
411 struct property *prop;
412 struct menu *child;
413
414 if (!menu_is_visible(menu))
415 return;
416
417 sym = menu->sym;
418 prop = menu->prompt;
419 if (prop) {
420 const char *prompt;
421
422 switch (prop->type) {
423 case P_MENU:
424 if (input_mode == ask_silent && rootEntry != menu) {
425 check_conf(menu);
426 return;
427 }
428 case P_COMMENT:
429 prompt = menu_get_prompt(menu);
430 if (prompt)
431 printf("%*c\n%*c %s\n%*c\n",
432 indent, '*',
433 indent, '*', prompt,
434 indent, '*');
435 default:
436 ;
437 }
438 }
439
440 if (!sym)
441 goto conf_childs;
442
443 if (sym_is_choice(sym)) {
444 conf_choice(menu);
445 if (sym->curr.tri != mod)
446 return;
447 goto conf_childs;
448 }
449
450 switch (sym->type) {
451 case S_INT:
452 case S_HEX:
453 case S_STRING:
454 conf_string(menu);
455 break;
456 default:
457 conf_sym(menu);
458 break;
459 }
460
461conf_childs:
462 if (sym)
463 indent += 2;
464 for (child = menu->list; child; child = child->next)
465 conf(child);
466 if (sym)
467 indent -= 2;
468}
469
470static void check_conf(struct menu *menu)
471{
472 struct symbol *sym;
473 struct menu *child;
474
475 if (!menu_is_visible(menu))
476 return;
477
478 sym = menu->sym;
479 if (sym && !sym_has_value(sym)) {
480 if (sym_is_changable(sym) ||
481 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
482 if (!conf_cnt++)
483 printf(_("*\n* Restart config...\n*\n"));
484 rootEntry = menu_get_parent_menu(menu);
485 conf(rootEntry);
486 }
487 }
488
489 for (child = menu->list; child; child = child->next)
490 check_conf(child);
491}
492
493int main(int ac, char **av)
494{
495 int i = 1;
496 const char *name;
497 struct stat tmpstat;
498
499 if (ac > i && av[i][0] == '-') {
500 switch (av[i++][1]) {
501 case 'o':
502 input_mode = ask_new;
503 break;
504 case 's':
505 input_mode = ask_silent;
506 valid_stdin = isatty(0) && isatty(1) && isatty(2);
507 break;
508 case 'd':
509 input_mode = set_default;
510 break;
511 case 'D':
512 input_mode = set_default;
513 defconfig_file = av[i++];
514 if (!defconfig_file) {
515 printf(_("%s: No default config file specified\n"),
516 av[0]);
517 exit(1);
518 }
519 break;
520 case 'n':
521 input_mode = set_no;
522 break;
523 case 'm':
524 input_mode = set_mod;
525 break;
526 case 'y':
527 input_mode = set_yes;
528 break;
529 case 'r':
530 input_mode = set_random;
531 srandom(time(NULL));
532 break;
533 case 'h':
534 case '?':
535 fprintf(stderr, "See README for usage info\n");
536 exit(0);
537 }
538 }
539 name = av[i];
540 if (!name) {
541 printf(_("%s: Kconfig file missing\n"), av[0]);
542 }
543 conf_parse(name);
544 //zconfdump(stdout);
545 switch (input_mode) {
546 case set_default:
547 if (!defconfig_file)
548 defconfig_file = conf_get_default_confname();
549 if (conf_read(defconfig_file)) {
550 printf("***\n"
551 "*** Can't find default configuration \"%s\"!\n"
552 "***\n", defconfig_file);
553 exit(1);
554 }
555 break;
556 case ask_silent:
557 if (stat(".config", &tmpstat)) {
558 printf(_("***\n"
559 "*** You have not yet configured your kernel!\n"
560 "***\n"
561 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
562 "*** \"make menuconfig\" or \"make xconfig\").\n"
563 "***\n"));
564 exit(1);
565 }
566 case ask_all:
567 case ask_new:
568 conf_read(NULL);
569 break;
570 case set_no:
571 case set_mod:
572 case set_yes:
573 case set_random:
574 name = getenv("KCONFIG_ALLCONFIG");
575 if (name && !stat(name, &tmpstat)) {
576 conf_read_simple(name);
577 break;
578 }
579 switch (input_mode) {
580 case set_no: name = "allno.config"; break;
581 case set_mod: name = "allmod.config"; break;
582 case set_yes: name = "allyes.config"; break;
583 case set_random: name = "allrandom.config"; break;
584 default: break;
585 }
586 if (!stat(name, &tmpstat))
587 conf_read_simple(name);
588 else if (!stat("all.config", &tmpstat))
589 conf_read_simple("all.config");
590 break;
591 default:
592 break;
593 }
594
595 if (input_mode != ask_silent) {
596 rootEntry = &rootmenu;
597 conf(&rootmenu);
598 if (input_mode == ask_all) {
599 input_mode = ask_silent;
600 valid_stdin = 1;
601 }
602 }
603 do {
604 conf_cnt = 0;
605 check_conf(&rootmenu);
606 } while (conf_cnt);
607 if (conf_write(NULL)) {
608 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
609 return 1;
610 }
611 return 0;
612}
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
new file mode 100644
index 000000000..301774f0c
--- /dev/null
+++ b/scripts/kconfig/confdata.c
@@ -0,0 +1,560 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <sys/stat.h>
7#include <ctype.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <time.h>
12#include <unistd.h>
13
14#define LKC_DIRECT_LINK
15#include "lkc.h"
16
17static void conf_warning(const char *fmt, ...)
18 __attribute__ ((format (printf, 1, 2)));
19
20static const char *conf_filename;
21static int conf_lineno, conf_warnings, conf_unsaved;
22
23const char conf_def_filename[] = ".config";
24
25const char conf_defname[] = "arch/$ARCH/defconfig";
26
27const char *conf_confnames[] = {
28 ".config",
29 "/lib/modules/$UNAME_RELEASE/.config",
30 "/etc/kernel-config",
31 "/boot/config-$UNAME_RELEASE",
32 conf_defname,
33 NULL,
34};
35
36static void conf_warning(const char *fmt, ...)
37{
38 va_list ap;
39 va_start(ap, fmt);
40 fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
41 vfprintf(stderr, fmt, ap);
42 fprintf(stderr, "\n");
43 va_end(ap);
44 conf_warnings++;
45}
46
47static char *conf_expand_value(const char *in)
48{
49 struct symbol *sym;
50 const char *src;
51 static char res_value[SYMBOL_MAXLENGTH];
52 char *dst, name[SYMBOL_MAXLENGTH];
53
54 res_value[0] = 0;
55 dst = name;
56 while ((src = strchr(in, '$'))) {
57 strncat(res_value, in, src - in);
58 src++;
59 dst = name;
60 while (isalnum(*src) || *src == '_')
61 *dst++ = *src++;
62 *dst = 0;
63 sym = sym_lookup(name, 0);
64 sym_calc_value(sym);
65 strcat(res_value, sym_get_string_value(sym));
66 in = src;
67 }
68 strcat(res_value, in);
69
70 return res_value;
71}
72
73char *conf_get_default_confname(void)
74{
75 struct stat buf;
76 static char fullname[PATH_MAX+1];
77 char *env, *name;
78
79 name = conf_expand_value(conf_defname);
80 env = getenv(SRCTREE);
81 if (env) {
82 sprintf(fullname, "%s/%s", env, name);
83 if (!stat(fullname, &buf))
84 return fullname;
85 }
86 return name;
87}
88
89int conf_read_simple(const char *name)
90{
91 FILE *in = NULL;
92 char line[1024];
93 char *p, *p2;
94 struct symbol *sym;
95 int i;
96
97 if (name) {
98 in = zconf_fopen(name);
99 } else {
100 const char **names = conf_confnames;
101 while ((name = *names++)) {
102 name = conf_expand_value(name);
103 in = zconf_fopen(name);
104 if (in) {
105 printf(_("#\n"
106 "# using defaults found in %s\n"
107 "#\n"), name);
108 break;
109 }
110 }
111 }
112 if (!in)
113 return 1;
114
115 conf_filename = name;
116 conf_lineno = 0;
117 conf_warnings = 0;
118 conf_unsaved = 0;
119
120 for_all_symbols(i, sym) {
121 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
122 if (sym_is_choice(sym))
123 sym->flags &= ~SYMBOL_NEW;
124 sym->flags &= ~SYMBOL_VALID;
125 switch (sym->type) {
126 case S_INT:
127 case S_HEX:
128 case S_STRING:
129 if (sym->user.val)
130 free(sym->user.val);
131 default:
132 sym->user.val = NULL;
133 sym->user.tri = no;
134 }
135 }
136
137 while (fgets(line, sizeof(line), in)) {
138 conf_lineno++;
139 sym = NULL;
140 switch (line[0]) {
141 case '#':
142 if (memcmp(line + 2, "CONFIG_", 7))
143 continue;
144 p = strchr(line + 9, ' ');
145 if (!p)
146 continue;
147 *p++ = 0;
148 if (strncmp(p, "is not set", 10))
149 continue;
150 sym = sym_find(line + 9);
151 if (!sym) {
152 conf_warning("trying to assign nonexistent symbol %s", line + 9);
153 break;
154 } else if (!(sym->flags & SYMBOL_NEW)) {
155 conf_warning("trying to reassign symbol %s", sym->name);
156 break;
157 }
158 switch (sym->type) {
159 case S_BOOLEAN:
160 case S_TRISTATE:
161 sym->user.tri = no;
162 sym->flags &= ~SYMBOL_NEW;
163 break;
164 default:
165 ;
166 }
167 break;
168 case 'C':
169 if (memcmp(line, "CONFIG_", 7)) {
170 conf_warning("unexpected data");
171 continue;
172 }
173 p = strchr(line + 7, '=');
174 if (!p)
175 continue;
176 *p++ = 0;
177 p2 = strchr(p, '\n');
178 if (p2)
179 *p2 = 0;
180 sym = sym_find(line + 7);
181 if (!sym) {
182 conf_warning("trying to assign nonexistent symbol %s", line + 7);
183 break;
184 } else if (!(sym->flags & SYMBOL_NEW)) {
185 conf_warning("trying to reassign symbol %s", sym->name);
186 break;
187 }
188 switch (sym->type) {
189 case S_TRISTATE:
190 if (p[0] == 'm') {
191 sym->user.tri = mod;
192 sym->flags &= ~SYMBOL_NEW;
193 break;
194 }
195 case S_BOOLEAN:
196 if (p[0] == 'y') {
197 sym->user.tri = yes;
198 sym->flags &= ~SYMBOL_NEW;
199 break;
200 }
201 if (p[0] == 'n') {
202 sym->user.tri = no;
203 sym->flags &= ~SYMBOL_NEW;
204 break;
205 }
206 conf_warning("symbol value '%s' invalid for %s", p, sym->name);
207 break;
208 case S_STRING:
209 if (*p++ != '"')
210 break;
211 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
212 if (*p2 == '"') {
213 *p2 = 0;
214 break;
215 }
216 memmove(p2, p2 + 1, strlen(p2));
217 }
218 if (!p2) {
219 conf_warning("invalid string found");
220 continue;
221 }
222 case S_INT:
223 case S_HEX:
224 if (sym_string_valid(sym, p)) {
225 sym->user.val = strdup(p);
226 sym->flags &= ~SYMBOL_NEW;
227 } else {
228 conf_warning("symbol value '%s' invalid for %s", p, sym->name);
229 continue;
230 }
231 break;
232 default:
233 ;
234 }
235 break;
236 case '\n':
237 break;
238 default:
239 conf_warning("unexpected data");
240 continue;
241 }
242 if (sym && sym_is_choice_value(sym)) {
243 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
244 switch (sym->user.tri) {
245 case no:
246 break;
247 case mod:
248 if (cs->user.tri == yes) {
249 conf_warning("%s creates inconsistent choice state", sym->name);
250 cs->flags |= SYMBOL_NEW;
251 }
252 break;
253 case yes:
254 if (cs->user.tri != no) {
255 conf_warning("%s creates inconsistent choice state", sym->name);
256 cs->flags |= SYMBOL_NEW;
257 } else
258 cs->user.val = sym;
259 break;
260 }
261 cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
262 }
263 }
264 fclose(in);
265
266 if (modules_sym)
267 sym_calc_value(modules_sym);
268 return 0;
269}
270
271int conf_read(const char *name)
272{
273 struct symbol *sym;
274 struct property *prop;
275 struct expr *e;
276 int i;
277
278 if (conf_read_simple(name))
279 return 1;
280
281 for_all_symbols(i, sym) {
282 sym_calc_value(sym);
283 if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
284 goto sym_ok;
285 if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
286 /* check that calculated value agrees with saved value */
287 switch (sym->type) {
288 case S_BOOLEAN:
289 case S_TRISTATE:
290 if (sym->user.tri != sym_get_tristate_value(sym))
291 break;
292 if (!sym_is_choice(sym))
293 goto sym_ok;
294 default:
295 if (!strcmp(sym->curr.val, sym->user.val))
296 goto sym_ok;
297 break;
298 }
299 } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
300 /* no previous value and not saved */
301 goto sym_ok;
302 conf_unsaved++;
303 /* maybe print value in verbose mode... */
304 sym_ok:
305 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
306 if (sym->visible == no)
307 sym->flags |= SYMBOL_NEW;
308 switch (sym->type) {
309 case S_STRING:
310 case S_INT:
311 case S_HEX:
312 if (!sym_string_within_range(sym, sym->user.val)) {
313 sym->flags |= SYMBOL_NEW;
314 sym->flags &= ~SYMBOL_VALID;
315 }
316 default:
317 break;
318 }
319 }
320 if (!sym_is_choice(sym))
321 continue;
322 prop = sym_get_choice_prop(sym);
323 for (e = prop->expr; e; e = e->left.expr)
324 if (e->right.sym->visible != no)
325 sym->flags |= e->right.sym->flags & SYMBOL_NEW;
326 }
327
328 sym_change_count = conf_warnings || conf_unsaved;
329
330 return 0;
331}
332
333int conf_write(const char *name)
334{
335 FILE *out, *out_h;
336 struct symbol *sym;
337 struct menu *menu;
338 const char *basename;
339 char dirname[128], tmpname[128], newname[128];
340 int type, l;
341 const char *str;
342 time_t now;
343 int use_timestamp = 1;
344 char *env;
345
346 dirname[0] = 0;
347 if (name && name[0]) {
348 struct stat st;
349 char *slash;
350
351 if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
352 strcpy(dirname, name);
353 strcat(dirname, "/");
354 basename = conf_def_filename;
355 } else if ((slash = strrchr(name, '/'))) {
356 int size = slash - name + 1;
357 memcpy(dirname, name, size);
358 dirname[size] = 0;
359 if (slash[1])
360 basename = slash + 1;
361 else
362 basename = conf_def_filename;
363 } else
364 basename = name;
365 } else
366 basename = conf_def_filename;
367
368 sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
369 out = fopen(newname, "w");
370 if (!out)
371 return 1;
372 out_h = NULL;
373 if (!name) {
374 out_h = fopen(".tmpconfig.h", "w");
375 if (!out_h)
376 return 1;
377 file_write_dep(NULL);
378 }
379 sym = sym_lookup("KERNELVERSION", 0);
380 sym_calc_value(sym);
381 time(&now);
382 env = getenv("KCONFIG_NOTIMESTAMP");
383 if (env && *env)
384 use_timestamp = 0;
385
386 fprintf(out, _("#\n"
387 "# Automatically generated make config: don't edit\n"
388 "# Linux kernel version: %s\n"
389 "%s%s"
390 "#\n"),
391 sym_get_string_value(sym),
392 use_timestamp ? "# " : "",
393 use_timestamp ? ctime(&now) : "");
394 if (out_h) {
395 char buf[sizeof("#define AUTOCONF_TIMESTAMP "
396 "\"YYYY-MM-DD HH:MM:SS some_timezone\"\n")];
397 buf[0] = '\0';
398 if (use_timestamp)
399 strftime(buf, sizeof(buf), "#define AUTOCONF_TIMESTAMP "
400 "\"%Y-%m-%d %H:%M:%S %Z\"\n", localtime(&now));
401 fprintf(out_h, "/*\n"
402 " * Automatically generated C config: don't edit\n"
403 " * Linux kernel version: %s\n"
404 " */\n"
405 "%s"
406 "#define AUTOCONF_INCLUDED\n",
407 sym_get_string_value(sym),
408 buf);
409 }
410 if (!sym_change_count)
411 sym_clear_all_valid();
412
413 menu = rootmenu.list;
414 while (menu) {
415 sym = menu->sym;
416 if (!sym) {
417 if (!menu_is_visible(menu))
418 goto next;
419 str = menu_get_prompt(menu);
420 fprintf(out, "\n"
421 "#\n"
422 "# %s\n"
423 "#\n", str);
424 if (out_h)
425 fprintf(out_h, "\n"
426 "/*\n"
427 " * %s\n"
428 " */\n", str);
429 } else if (!(sym->flags & SYMBOL_CHOICE)) {
430 sym_calc_value(sym);
431 if (!(sym->flags & SYMBOL_WRITE))
432 goto next;
433 sym->flags &= ~SYMBOL_WRITE;
434 type = sym->type;
435 if (type == S_TRISTATE) {
436 sym_calc_value(modules_sym);
437 if (modules_sym->curr.tri == no)
438 type = S_BOOLEAN;
439 }
440 switch (type) {
441 case S_BOOLEAN:
442 case S_TRISTATE:
443 switch (sym_get_tristate_value(sym)) {
444 case no:
445 fprintf(out, "# CONFIG_%s is not set\n", sym->name);
446 if (out_h) {
447 fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
448 /* bbox */
449 fprintf(out_h, "#define ENABLE_%s 0\n", sym->name);
450 fprintf(out_h, "#define USE_%s(...)\n", sym->name);
451 fprintf(out_h, "#define SKIP_%s(...) __VA_ARGS__\n", sym->name);
452 }
453 break;
454 case mod:
455 fprintf(out, "CONFIG_%s=m\n", sym->name);
456 if (out_h)
457 fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
458 break;
459 case yes:
460 fprintf(out, "CONFIG_%s=y\n", sym->name);
461 if (out_h) {
462 fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
463 /* bbox */
464 fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
465 fprintf(out_h, "#define USE_%s(...) __VA_ARGS__\n", sym->name);
466 fprintf(out_h, "#define SKIP_%s(...)\n", sym->name);
467 }
468 break;
469 }
470 break;
471 case S_STRING:
472 // fix me
473 str = sym_get_string_value(sym);
474 fprintf(out, "CONFIG_%s=\"", sym->name);
475 if (out_h)
476 fprintf(out_h, "#define CONFIG_%s \"", sym->name);
477 do {
478 l = strcspn(str, "\"\\");
479 if (l) {
480 fwrite(str, l, 1, out);
481 if (out_h)
482 fwrite(str, l, 1, out_h);
483 }
484 str += l;
485 while (*str == '\\' || *str == '"') {
486 fprintf(out, "\\%c", *str);
487 if (out_h)
488 fprintf(out_h, "\\%c", *str);
489 str++;
490 }
491 } while (*str);
492 fputs("\"\n", out);
493 if (out_h) {
494 fputs("\"\n", out_h);
495 /* bbox */
496 fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
497 fprintf(out_h, "#define USE_%s(...) __VA_ARGS__\n", sym->name);
498 fprintf(out_h, "#define SKIP_%s(...)\n", sym->name);
499 }
500 break;
501 case S_HEX:
502 str = sym_get_string_value(sym);
503 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
504 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
505 if (out_h) {
506 fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
507 /* bbox */
508 fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
509 fprintf(out_h, "#define USE_%s(...) __VA_ARGS__\n", sym->name);
510 fprintf(out_h, "#define SKIP_%s(...)\n", sym->name);
511 }
512 break;
513 }
514 case S_INT:
515 str = sym_get_string_value(sym);
516 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
517 if (out_h) {
518 fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
519 /* bbox */
520 fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
521 fprintf(out_h, "#define USE_%s(...) __VA_ARGS__\n", sym->name);
522 fprintf(out_h, "#define SKIP_%s(...)\n", sym->name);
523 }
524 break;
525 }
526 }
527
528 next:
529 if (menu->list) {
530 menu = menu->list;
531 continue;
532 }
533 if (menu->next)
534 menu = menu->next;
535 else while ((menu = menu->parent)) {
536 if (menu->next) {
537 menu = menu->next;
538 break;
539 }
540 }
541 }
542 fclose(out);
543 if (out_h) {
544 fclose(out_h);
545 rename(".tmpconfig.h", "include/autoconf.h");
546 }
547 if (!name || basename != conf_def_filename) {
548 if (!name)
549 name = conf_def_filename;
550 sprintf(tmpname, "%s.old", name);
551 rename(name, tmpname);
552 }
553 sprintf(tmpname, "%s%s", dirname, basename);
554 if (rename(newname, tmpname))
555 return 1;
556
557 sym_change_count = 0;
558
559 return 0;
560}
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
new file mode 100644
index 000000000..30e4f9d69
--- /dev/null
+++ b/scripts/kconfig/expr.c
@@ -0,0 +1,1099 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
10#define LKC_DIRECT_LINK
11#include "lkc.h"
12
13#define DEBUG_EXPR 0
14
15struct expr *expr_alloc_symbol(struct symbol *sym)
16{
17 struct expr *e = malloc(sizeof(*e));
18 memset(e, 0, sizeof(*e));
19 e->type = E_SYMBOL;
20 e->left.sym = sym;
21 return e;
22}
23
24struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
25{
26 struct expr *e = malloc(sizeof(*e));
27 memset(e, 0, sizeof(*e));
28 e->type = type;
29 e->left.expr = ce;
30 return e;
31}
32
33struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
34{
35 struct expr *e = malloc(sizeof(*e));
36 memset(e, 0, sizeof(*e));
37 e->type = type;
38 e->left.expr = e1;
39 e->right.expr = e2;
40 return e;
41}
42
43struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
44{
45 struct expr *e = malloc(sizeof(*e));
46 memset(e, 0, sizeof(*e));
47 e->type = type;
48 e->left.sym = s1;
49 e->right.sym = s2;
50 return e;
51}
52
53struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
54{
55 if (!e1)
56 return e2;
57 return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
58}
59
60struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
61{
62 if (!e1)
63 return e2;
64 return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
65}
66
67struct expr *expr_copy(struct expr *org)
68{
69 struct expr *e;
70
71 if (!org)
72 return NULL;
73
74 e = malloc(sizeof(*org));
75 memcpy(e, org, sizeof(*org));
76 switch (org->type) {
77 case E_SYMBOL:
78 e->left = org->left;
79 break;
80 case E_NOT:
81 e->left.expr = expr_copy(org->left.expr);
82 break;
83 case E_EQUAL:
84 case E_UNEQUAL:
85 e->left.sym = org->left.sym;
86 e->right.sym = org->right.sym;
87 break;
88 case E_AND:
89 case E_OR:
90 case E_CHOICE:
91 e->left.expr = expr_copy(org->left.expr);
92 e->right.expr = expr_copy(org->right.expr);
93 break;
94 default:
95 printf("can't copy type %d\n", e->type);
96 free(e);
97 e = NULL;
98 break;
99 }
100
101 return e;
102}
103
104void expr_free(struct expr *e)
105{
106 if (!e)
107 return;
108
109 switch (e->type) {
110 case E_SYMBOL:
111 break;
112 case E_NOT:
113 expr_free(e->left.expr);
114 return;
115 case E_EQUAL:
116 case E_UNEQUAL:
117 break;
118 case E_OR:
119 case E_AND:
120 expr_free(e->left.expr);
121 expr_free(e->right.expr);
122 break;
123 default:
124 printf("how to free type %d?\n", e->type);
125 break;
126 }
127 free(e);
128}
129
130static int trans_count;
131
132#define e1 (*ep1)
133#define e2 (*ep2)
134
135static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
136{
137 if (e1->type == type) {
138 __expr_eliminate_eq(type, &e1->left.expr, &e2);
139 __expr_eliminate_eq(type, &e1->right.expr, &e2);
140 return;
141 }
142 if (e2->type == type) {
143 __expr_eliminate_eq(type, &e1, &e2->left.expr);
144 __expr_eliminate_eq(type, &e1, &e2->right.expr);
145 return;
146 }
147 if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
148 e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO)))
149 return;
150 if (!expr_eq(e1, e2))
151 return;
152 trans_count++;
153 expr_free(e1); expr_free(e2);
154 switch (type) {
155 case E_OR:
156 e1 = expr_alloc_symbol(&symbol_no);
157 e2 = expr_alloc_symbol(&symbol_no);
158 break;
159 case E_AND:
160 e1 = expr_alloc_symbol(&symbol_yes);
161 e2 = expr_alloc_symbol(&symbol_yes);
162 break;
163 default:
164 ;
165 }
166}
167
168void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
169{
170 if (!e1 || !e2)
171 return;
172 switch (e1->type) {
173 case E_OR:
174 case E_AND:
175 __expr_eliminate_eq(e1->type, ep1, ep2);
176 default:
177 ;
178 }
179 if (e1->type != e2->type) switch (e2->type) {
180 case E_OR:
181 case E_AND:
182 __expr_eliminate_eq(e2->type, ep1, ep2);
183 default:
184 ;
185 }
186 e1 = expr_eliminate_yn(e1);
187 e2 = expr_eliminate_yn(e2);
188}
189
190#undef e1
191#undef e2
192
193int expr_eq(struct expr *e1, struct expr *e2)
194{
195 int res, old_count;
196
197 if (e1->type != e2->type)
198 return 0;
199 switch (e1->type) {
200 case E_EQUAL:
201 case E_UNEQUAL:
202 return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
203 case E_SYMBOL:
204 return e1->left.sym == e2->left.sym;
205 case E_NOT:
206 return expr_eq(e1->left.expr, e2->left.expr);
207 case E_AND:
208 case E_OR:
209 e1 = expr_copy(e1);
210 e2 = expr_copy(e2);
211 old_count = trans_count;
212 expr_eliminate_eq(&e1, &e2);
213 res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
214 e1->left.sym == e2->left.sym);
215 expr_free(e1);
216 expr_free(e2);
217 trans_count = old_count;
218 return res;
219 case E_CHOICE:
220 case E_RANGE:
221 case E_NONE:
222 /* panic */;
223 }
224
225 if (DEBUG_EXPR) {
226 expr_fprint(e1, stdout);
227 printf(" = ");
228 expr_fprint(e2, stdout);
229 printf(" ?\n");
230 }
231
232 return 0;
233}
234
235struct expr *expr_eliminate_yn(struct expr *e)
236{
237 struct expr *tmp;
238
239 if (e) switch (e->type) {
240 case E_AND:
241 e->left.expr = expr_eliminate_yn(e->left.expr);
242 e->right.expr = expr_eliminate_yn(e->right.expr);
243 if (e->left.expr->type == E_SYMBOL) {
244 if (e->left.expr->left.sym == &symbol_no) {
245 expr_free(e->left.expr);
246 expr_free(e->right.expr);
247 e->type = E_SYMBOL;
248 e->left.sym = &symbol_no;
249 e->right.expr = NULL;
250 return e;
251 } else if (e->left.expr->left.sym == &symbol_yes) {
252 free(e->left.expr);
253 tmp = e->right.expr;
254 *e = *(e->right.expr);
255 free(tmp);
256 return e;
257 }
258 }
259 if (e->right.expr->type == E_SYMBOL) {
260 if (e->right.expr->left.sym == &symbol_no) {
261 expr_free(e->left.expr);
262 expr_free(e->right.expr);
263 e->type = E_SYMBOL;
264 e->left.sym = &symbol_no;
265 e->right.expr = NULL;
266 return e;
267 } else if (e->right.expr->left.sym == &symbol_yes) {
268 free(e->right.expr);
269 tmp = e->left.expr;
270 *e = *(e->left.expr);
271 free(tmp);
272 return e;
273 }
274 }
275 break;
276 case E_OR:
277 e->left.expr = expr_eliminate_yn(e->left.expr);
278 e->right.expr = expr_eliminate_yn(e->right.expr);
279 if (e->left.expr->type == E_SYMBOL) {
280 if (e->left.expr->left.sym == &symbol_no) {
281 free(e->left.expr);
282 tmp = e->right.expr;
283 *e = *(e->right.expr);
284 free(tmp);
285 return e;
286 } else if (e->left.expr->left.sym == &symbol_yes) {
287 expr_free(e->left.expr);
288 expr_free(e->right.expr);
289 e->type = E_SYMBOL;
290 e->left.sym = &symbol_yes;
291 e->right.expr = NULL;
292 return e;
293 }
294 }
295 if (e->right.expr->type == E_SYMBOL) {
296 if (e->right.expr->left.sym == &symbol_no) {
297 free(e->right.expr);
298 tmp = e->left.expr;
299 *e = *(e->left.expr);
300 free(tmp);
301 return e;
302 } else if (e->right.expr->left.sym == &symbol_yes) {
303 expr_free(e->left.expr);
304 expr_free(e->right.expr);
305 e->type = E_SYMBOL;
306 e->left.sym = &symbol_yes;
307 e->right.expr = NULL;
308 return e;
309 }
310 }
311 break;
312 default:
313 ;
314 }
315 return e;
316}
317
318/*
319 * bool FOO!=n => FOO
320 */
321struct expr *expr_trans_bool(struct expr *e)
322{
323 if (!e)
324 return NULL;
325 switch (e->type) {
326 case E_AND:
327 case E_OR:
328 case E_NOT:
329 e->left.expr = expr_trans_bool(e->left.expr);
330 e->right.expr = expr_trans_bool(e->right.expr);
331 break;
332 case E_UNEQUAL:
333 // FOO!=n -> FOO
334 if (e->left.sym->type == S_TRISTATE) {
335 if (e->right.sym == &symbol_no) {
336 e->type = E_SYMBOL;
337 e->right.sym = NULL;
338 }
339 }
340 break;
341 default:
342 ;
343 }
344 return e;
345}
346
347/*
348 * e1 || e2 -> ?
349 */
350struct expr *expr_join_or(struct expr *e1, struct expr *e2)
351{
352 struct expr *tmp;
353 struct symbol *sym1, *sym2;
354
355 if (expr_eq(e1, e2))
356 return expr_copy(e1);
357 if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
358 return NULL;
359 if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
360 return NULL;
361 if (e1->type == E_NOT) {
362 tmp = e1->left.expr;
363 if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
364 return NULL;
365 sym1 = tmp->left.sym;
366 } else
367 sym1 = e1->left.sym;
368 if (e2->type == E_NOT) {
369 if (e2->left.expr->type != E_SYMBOL)
370 return NULL;
371 sym2 = e2->left.expr->left.sym;
372 } else
373 sym2 = e2->left.sym;
374 if (sym1 != sym2)
375 return NULL;
376 if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
377 return NULL;
378 if (sym1->type == S_TRISTATE) {
379 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
380 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
381 (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
382 // (a='y') || (a='m') -> (a!='n')
383 return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
384 }
385 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
386 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
387 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
388 // (a='y') || (a='n') -> (a!='m')
389 return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
390 }
391 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
392 ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
393 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
394 // (a='m') || (a='n') -> (a!='y')
395 return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
396 }
397 }
398 if (sym1->type == S_BOOLEAN && sym1 == sym2) {
399 if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
400 (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
401 return expr_alloc_symbol(&symbol_yes);
402 }
403
404 if (DEBUG_EXPR) {
405 printf("optimize (");
406 expr_fprint(e1, stdout);
407 printf(") || (");
408 expr_fprint(e2, stdout);
409 printf(")?\n");
410 }
411 return NULL;
412}
413
414struct expr *expr_join_and(struct expr *e1, struct expr *e2)
415{
416 struct expr *tmp;
417 struct symbol *sym1, *sym2;
418
419 if (expr_eq(e1, e2))
420 return expr_copy(e1);
421 if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
422 return NULL;
423 if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
424 return NULL;
425 if (e1->type == E_NOT) {
426 tmp = e1->left.expr;
427 if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
428 return NULL;
429 sym1 = tmp->left.sym;
430 } else
431 sym1 = e1->left.sym;
432 if (e2->type == E_NOT) {
433 if (e2->left.expr->type != E_SYMBOL)
434 return NULL;
435 sym2 = e2->left.expr->left.sym;
436 } else
437 sym2 = e2->left.sym;
438 if (sym1 != sym2)
439 return NULL;
440 if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
441 return NULL;
442
443 if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
444 (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
445 // (a) && (a='y') -> (a='y')
446 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
447
448 if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
449 (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
450 // (a) && (a!='n') -> (a)
451 return expr_alloc_symbol(sym1);
452
453 if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
454 (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
455 // (a) && (a!='m') -> (a='y')
456 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
457
458 if (sym1->type == S_TRISTATE) {
459 if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
460 // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
461 sym2 = e1->right.sym;
462 if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
463 return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
464 : expr_alloc_symbol(&symbol_no);
465 }
466 if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
467 // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
468 sym2 = e2->right.sym;
469 if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
470 return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
471 : expr_alloc_symbol(&symbol_no);
472 }
473 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
474 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
475 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
476 // (a!='y') && (a!='n') -> (a='m')
477 return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
478
479 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
480 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
481 (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
482 // (a!='y') && (a!='m') -> (a='n')
483 return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
484
485 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
486 ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
487 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
488 // (a!='m') && (a!='n') -> (a='m')
489 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
490
491 if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
492 (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
493 (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
494 (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
495 return NULL;
496 }
497
498 if (DEBUG_EXPR) {
499 printf("optimize (");
500 expr_fprint(e1, stdout);
501 printf(") && (");
502 expr_fprint(e2, stdout);
503 printf(")?\n");
504 }
505 return NULL;
506}
507
508static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
509{
510#define e1 (*ep1)
511#define e2 (*ep2)
512 struct expr *tmp;
513
514 if (e1->type == type) {
515 expr_eliminate_dups1(type, &e1->left.expr, &e2);
516 expr_eliminate_dups1(type, &e1->right.expr, &e2);
517 return;
518 }
519 if (e2->type == type) {
520 expr_eliminate_dups1(type, &e1, &e2->left.expr);
521 expr_eliminate_dups1(type, &e1, &e2->right.expr);
522 return;
523 }
524 if (e1 == e2)
525 return;
526
527 switch (e1->type) {
528 case E_OR: case E_AND:
529 expr_eliminate_dups1(e1->type, &e1, &e1);
530 default:
531 ;
532 }
533
534 switch (type) {
535 case E_OR:
536 tmp = expr_join_or(e1, e2);
537 if (tmp) {
538 expr_free(e1); expr_free(e2);
539 e1 = expr_alloc_symbol(&symbol_no);
540 e2 = tmp;
541 trans_count++;
542 }
543 break;
544 case E_AND:
545 tmp = expr_join_and(e1, e2);
546 if (tmp) {
547 expr_free(e1); expr_free(e2);
548 e1 = expr_alloc_symbol(&symbol_yes);
549 e2 = tmp;
550 trans_count++;
551 }
552 break;
553 default:
554 ;
555 }
556#undef e1
557#undef e2
558}
559
560static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
561{
562#define e1 (*ep1)
563#define e2 (*ep2)
564 struct expr *tmp, *tmp1, *tmp2;
565
566 if (e1->type == type) {
567 expr_eliminate_dups2(type, &e1->left.expr, &e2);
568 expr_eliminate_dups2(type, &e1->right.expr, &e2);
569 return;
570 }
571 if (e2->type == type) {
572 expr_eliminate_dups2(type, &e1, &e2->left.expr);
573 expr_eliminate_dups2(type, &e1, &e2->right.expr);
574 }
575 if (e1 == e2)
576 return;
577
578 switch (e1->type) {
579 case E_OR:
580 expr_eliminate_dups2(e1->type, &e1, &e1);
581 // (FOO || BAR) && (!FOO && !BAR) -> n
582 tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
583 tmp2 = expr_copy(e2);
584 tmp = expr_extract_eq_and(&tmp1, &tmp2);
585 if (expr_is_yes(tmp1)) {
586 expr_free(e1);
587 e1 = expr_alloc_symbol(&symbol_no);
588 trans_count++;
589 }
590 expr_free(tmp2);
591 expr_free(tmp1);
592 expr_free(tmp);
593 break;
594 case E_AND:
595 expr_eliminate_dups2(e1->type, &e1, &e1);
596 // (FOO && BAR) || (!FOO || !BAR) -> y
597 tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
598 tmp2 = expr_copy(e2);
599 tmp = expr_extract_eq_or(&tmp1, &tmp2);
600 if (expr_is_no(tmp1)) {
601 expr_free(e1);
602 e1 = expr_alloc_symbol(&symbol_yes);
603 trans_count++;
604 }
605 expr_free(tmp2);
606 expr_free(tmp1);
607 expr_free(tmp);
608 break;
609 default:
610 ;
611 }
612#undef e1
613#undef e2
614}
615
616struct expr *expr_eliminate_dups(struct expr *e)
617{
618 int oldcount;
619 if (!e)
620 return e;
621
622 oldcount = trans_count;
623 while (1) {
624 trans_count = 0;
625 switch (e->type) {
626 case E_OR: case E_AND:
627 expr_eliminate_dups1(e->type, &e, &e);
628 expr_eliminate_dups2(e->type, &e, &e);
629 default:
630 ;
631 }
632 if (!trans_count)
633 break;
634 e = expr_eliminate_yn(e);
635 }
636 trans_count = oldcount;
637 return e;
638}
639
640struct expr *expr_transform(struct expr *e)
641{
642 struct expr *tmp;
643
644 if (!e)
645 return NULL;
646 switch (e->type) {
647 case E_EQUAL:
648 case E_UNEQUAL:
649 case E_SYMBOL:
650 case E_CHOICE:
651 break;
652 default:
653 e->left.expr = expr_transform(e->left.expr);
654 e->right.expr = expr_transform(e->right.expr);
655 }
656
657 switch (e->type) {
658 case E_EQUAL:
659 if (e->left.sym->type != S_BOOLEAN)
660 break;
661 if (e->right.sym == &symbol_no) {
662 e->type = E_NOT;
663 e->left.expr = expr_alloc_symbol(e->left.sym);
664 e->right.sym = NULL;
665 break;
666 }
667 if (e->right.sym == &symbol_mod) {
668 printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
669 e->type = E_SYMBOL;
670 e->left.sym = &symbol_no;
671 e->right.sym = NULL;
672 break;
673 }
674 if (e->right.sym == &symbol_yes) {
675 e->type = E_SYMBOL;
676 e->right.sym = NULL;
677 break;
678 }
679 break;
680 case E_UNEQUAL:
681 if (e->left.sym->type != S_BOOLEAN)
682 break;
683 if (e->right.sym == &symbol_no) {
684 e->type = E_SYMBOL;
685 e->right.sym = NULL;
686 break;
687 }
688 if (e->right.sym == &symbol_mod) {
689 printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
690 e->type = E_SYMBOL;
691 e->left.sym = &symbol_yes;
692 e->right.sym = NULL;
693 break;
694 }
695 if (e->right.sym == &symbol_yes) {
696 e->type = E_NOT;
697 e->left.expr = expr_alloc_symbol(e->left.sym);
698 e->right.sym = NULL;
699 break;
700 }
701 break;
702 case E_NOT:
703 switch (e->left.expr->type) {
704 case E_NOT:
705 // !!a -> a
706 tmp = e->left.expr->left.expr;
707 free(e->left.expr);
708 free(e);
709 e = tmp;
710 e = expr_transform(e);
711 break;
712 case E_EQUAL:
713 case E_UNEQUAL:
714 // !a='x' -> a!='x'
715 tmp = e->left.expr;
716 free(e);
717 e = tmp;
718 e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
719 break;
720 case E_OR:
721 // !(a || b) -> !a && !b
722 tmp = e->left.expr;
723 e->type = E_AND;
724 e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
725 tmp->type = E_NOT;
726 tmp->right.expr = NULL;
727 e = expr_transform(e);
728 break;
729 case E_AND:
730 // !(a && b) -> !a || !b
731 tmp = e->left.expr;
732 e->type = E_OR;
733 e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
734 tmp->type = E_NOT;
735 tmp->right.expr = NULL;
736 e = expr_transform(e);
737 break;
738 case E_SYMBOL:
739 if (e->left.expr->left.sym == &symbol_yes) {
740 // !'y' -> 'n'
741 tmp = e->left.expr;
742 free(e);
743 e = tmp;
744 e->type = E_SYMBOL;
745 e->left.sym = &symbol_no;
746 break;
747 }
748 if (e->left.expr->left.sym == &symbol_mod) {
749 // !'m' -> 'm'
750 tmp = e->left.expr;
751 free(e);
752 e = tmp;
753 e->type = E_SYMBOL;
754 e->left.sym = &symbol_mod;
755 break;
756 }
757 if (e->left.expr->left.sym == &symbol_no) {
758 // !'n' -> 'y'
759 tmp = e->left.expr;
760 free(e);
761 e = tmp;
762 e->type = E_SYMBOL;
763 e->left.sym = &symbol_yes;
764 break;
765 }
766 break;
767 default:
768 ;
769 }
770 break;
771 default:
772 ;
773 }
774 return e;
775}
776
777int expr_contains_symbol(struct expr *dep, struct symbol *sym)
778{
779 if (!dep)
780 return 0;
781
782 switch (dep->type) {
783 case E_AND:
784 case E_OR:
785 return expr_contains_symbol(dep->left.expr, sym) ||
786 expr_contains_symbol(dep->right.expr, sym);
787 case E_SYMBOL:
788 return dep->left.sym == sym;
789 case E_EQUAL:
790 case E_UNEQUAL:
791 return dep->left.sym == sym ||
792 dep->right.sym == sym;
793 case E_NOT:
794 return expr_contains_symbol(dep->left.expr, sym);
795 default:
796 ;
797 }
798 return 0;
799}
800
801bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
802{
803 if (!dep)
804 return false;
805
806 switch (dep->type) {
807 case E_AND:
808 return expr_depends_symbol(dep->left.expr, sym) ||
809 expr_depends_symbol(dep->right.expr, sym);
810 case E_SYMBOL:
811 return dep->left.sym == sym;
812 case E_EQUAL:
813 if (dep->left.sym == sym) {
814 if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
815 return true;
816 }
817 break;
818 case E_UNEQUAL:
819 if (dep->left.sym == sym) {
820 if (dep->right.sym == &symbol_no)
821 return true;
822 }
823 break;
824 default:
825 ;
826 }
827 return false;
828}
829
830struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
831{
832 struct expr *tmp = NULL;
833 expr_extract_eq(E_AND, &tmp, ep1, ep2);
834 if (tmp) {
835 *ep1 = expr_eliminate_yn(*ep1);
836 *ep2 = expr_eliminate_yn(*ep2);
837 }
838 return tmp;
839}
840
841struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
842{
843 struct expr *tmp = NULL;
844 expr_extract_eq(E_OR, &tmp, ep1, ep2);
845 if (tmp) {
846 *ep1 = expr_eliminate_yn(*ep1);
847 *ep2 = expr_eliminate_yn(*ep2);
848 }
849 return tmp;
850}
851
852void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
853{
854#define e1 (*ep1)
855#define e2 (*ep2)
856 if (e1->type == type) {
857 expr_extract_eq(type, ep, &e1->left.expr, &e2);
858 expr_extract_eq(type, ep, &e1->right.expr, &e2);
859 return;
860 }
861 if (e2->type == type) {
862 expr_extract_eq(type, ep, ep1, &e2->left.expr);
863 expr_extract_eq(type, ep, ep1, &e2->right.expr);
864 return;
865 }
866 if (expr_eq(e1, e2)) {
867 *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
868 expr_free(e2);
869 if (type == E_AND) {
870 e1 = expr_alloc_symbol(&symbol_yes);
871 e2 = expr_alloc_symbol(&symbol_yes);
872 } else if (type == E_OR) {
873 e1 = expr_alloc_symbol(&symbol_no);
874 e2 = expr_alloc_symbol(&symbol_no);
875 }
876 }
877#undef e1
878#undef e2
879}
880
881struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
882{
883 struct expr *e1, *e2;
884
885 if (!e) {
886 e = expr_alloc_symbol(sym);
887 if (type == E_UNEQUAL)
888 e = expr_alloc_one(E_NOT, e);
889 return e;
890 }
891 switch (e->type) {
892 case E_AND:
893 e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
894 e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
895 if (sym == &symbol_yes)
896 e = expr_alloc_two(E_AND, e1, e2);
897 if (sym == &symbol_no)
898 e = expr_alloc_two(E_OR, e1, e2);
899 if (type == E_UNEQUAL)
900 e = expr_alloc_one(E_NOT, e);
901 return e;
902 case E_OR:
903 e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
904 e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
905 if (sym == &symbol_yes)
906 e = expr_alloc_two(E_OR, e1, e2);
907 if (sym == &symbol_no)
908 e = expr_alloc_two(E_AND, e1, e2);
909 if (type == E_UNEQUAL)
910 e = expr_alloc_one(E_NOT, e);
911 return e;
912 case E_NOT:
913 return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
914 case E_UNEQUAL:
915 case E_EQUAL:
916 if (type == E_EQUAL) {
917 if (sym == &symbol_yes)
918 return expr_copy(e);
919 if (sym == &symbol_mod)
920 return expr_alloc_symbol(&symbol_no);
921 if (sym == &symbol_no)
922 return expr_alloc_one(E_NOT, expr_copy(e));
923 } else {
924 if (sym == &symbol_yes)
925 return expr_alloc_one(E_NOT, expr_copy(e));
926 if (sym == &symbol_mod)
927 return expr_alloc_symbol(&symbol_yes);
928 if (sym == &symbol_no)
929 return expr_copy(e);
930 }
931 break;
932 case E_SYMBOL:
933 return expr_alloc_comp(type, e->left.sym, sym);
934 case E_CHOICE:
935 case E_RANGE:
936 case E_NONE:
937 /* panic */;
938 }
939 return NULL;
940}
941
942tristate expr_calc_value(struct expr *e)
943{
944 tristate val1, val2;
945 const char *str1, *str2;
946
947 if (!e)
948 return yes;
949
950 switch (e->type) {
951 case E_SYMBOL:
952 sym_calc_value(e->left.sym);
953 return e->left.sym->curr.tri;
954 case E_AND:
955 val1 = expr_calc_value(e->left.expr);
956 val2 = expr_calc_value(e->right.expr);
957 return E_AND(val1, val2);
958 case E_OR:
959 val1 = expr_calc_value(e->left.expr);
960 val2 = expr_calc_value(e->right.expr);
961 return E_OR(val1, val2);
962 case E_NOT:
963 val1 = expr_calc_value(e->left.expr);
964 return E_NOT(val1);
965 case E_EQUAL:
966 sym_calc_value(e->left.sym);
967 sym_calc_value(e->right.sym);
968 str1 = sym_get_string_value(e->left.sym);
969 str2 = sym_get_string_value(e->right.sym);
970 return !strcmp(str1, str2) ? yes : no;
971 case E_UNEQUAL:
972 sym_calc_value(e->left.sym);
973 sym_calc_value(e->right.sym);
974 str1 = sym_get_string_value(e->left.sym);
975 str2 = sym_get_string_value(e->right.sym);
976 return !strcmp(str1, str2) ? no : yes;
977 default:
978 printf("expr_calc_value: %d?\n", e->type);
979 return no;
980 }
981}
982
983int expr_compare_type(enum expr_type t1, enum expr_type t2)
984{
985#if 0
986 return 1;
987#else
988 if (t1 == t2)
989 return 0;
990 switch (t1) {
991 case E_EQUAL:
992 case E_UNEQUAL:
993 if (t2 == E_NOT)
994 return 1;
995 case E_NOT:
996 if (t2 == E_AND)
997 return 1;
998 case E_AND:
999 if (t2 == E_OR)
1000 return 1;
1001 case E_OR:
1002 if (t2 == E_CHOICE)
1003 return 1;
1004 case E_CHOICE:
1005 if (t2 == 0)
1006 return 1;
1007 default:
1008 return -1;
1009 }
1010 printf("[%dgt%d?]", t1, t2);
1011 return 0;
1012#endif
1013}
1014
1015void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken)
1016{
1017 if (!e) {
1018 fn(data, "y");
1019 return;
1020 }
1021
1022 if (expr_compare_type(prevtoken, e->type) > 0)
1023 fn(data, "(");
1024 switch (e->type) {
1025 case E_SYMBOL:
1026 if (e->left.sym->name)
1027 fn(data, e->left.sym->name);
1028 else
1029 fn(data, "<choice>");
1030 break;
1031 case E_NOT:
1032 fn(data, "!");
1033 expr_print(e->left.expr, fn, data, E_NOT);
1034 break;
1035 case E_EQUAL:
1036 fn(data, e->left.sym->name);
1037 fn(data, "=");
1038 fn(data, e->right.sym->name);
1039 break;
1040 case E_UNEQUAL:
1041 fn(data, e->left.sym->name);
1042 fn(data, "!=");
1043 fn(data, e->right.sym->name);
1044 break;
1045 case E_OR:
1046 expr_print(e->left.expr, fn, data, E_OR);
1047 fn(data, " || ");
1048 expr_print(e->right.expr, fn, data, E_OR);
1049 break;
1050 case E_AND:
1051 expr_print(e->left.expr, fn, data, E_AND);
1052 fn(data, " && ");
1053 expr_print(e->right.expr, fn, data, E_AND);
1054 break;
1055 case E_CHOICE:
1056 fn(data, e->right.sym->name);
1057 if (e->left.expr) {
1058 fn(data, " ^ ");
1059 expr_print(e->left.expr, fn, data, E_CHOICE);
1060 }
1061 break;
1062 case E_RANGE:
1063 fn(data, "[");
1064 fn(data, e->left.sym->name);
1065 fn(data, " ");
1066 fn(data, e->right.sym->name);
1067 fn(data, "]");
1068 break;
1069 default:
1070 {
1071 char buf[32];
1072 sprintf(buf, "<unknown type %d>", e->type);
1073 fn(data, buf);
1074 break;
1075 }
1076 }
1077 if (expr_compare_type(prevtoken, e->type) > 0)
1078 fn(data, ")");
1079}
1080
1081static void expr_print_file_helper(void *data, const char *str)
1082{
1083 fwrite(str, strlen(str), 1, data);
1084}
1085
1086void expr_fprint(struct expr *e, FILE *out)
1087{
1088 expr_print(e, expr_print_file_helper, out, E_NONE);
1089}
1090
1091static void expr_print_gstr_helper(void *data, const char *str)
1092{
1093 str_append((struct gstr*)data, str);
1094}
1095
1096void expr_gstr_print(struct expr *e, struct gstr *gs)
1097{
1098 expr_print(e, expr_print_gstr_helper, gs, E_NONE);
1099}
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
new file mode 100644
index 000000000..1b36ef18c
--- /dev/null
+++ b/scripts/kconfig/expr.h
@@ -0,0 +1,194 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#ifndef EXPR_H
7#define EXPR_H
8
9#ifdef __cplusplus
10extern "C" {
11#endif
12
13#include <stdio.h>
14#ifndef __cplusplus
15#include <stdbool.h>
16#endif
17
18struct file {
19 struct file *next;
20 struct file *parent;
21 char *name;
22 int lineno;
23 int flags;
24};
25
26#define FILE_BUSY 0x0001
27#define FILE_SCANNED 0x0002
28#define FILE_PRINTED 0x0004
29
30typedef enum tristate {
31 no, mod, yes
32} tristate;
33
34enum expr_type {
35 E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE
36};
37
38union expr_data {
39 struct expr *expr;
40 struct symbol *sym;
41};
42
43struct expr {
44 enum expr_type type;
45 union expr_data left, right;
46};
47
48#define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
49#define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
50#define E_NOT(dep) (2-(dep))
51
52struct expr_value {
53 struct expr *expr;
54 tristate tri;
55};
56
57struct symbol_value {
58 void *val;
59 tristate tri;
60};
61
62enum symbol_type {
63 S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
64};
65
66struct symbol {
67 struct symbol *next;
68 char *name;
69 char *help;
70 enum symbol_type type;
71 struct symbol_value curr, user;
72 tristate visible;
73 int flags;
74 struct property *prop;
75 struct expr *dep, *dep2;
76 struct expr_value rev_dep;
77};
78
79#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)
80
81#define SYMBOL_YES 0x0001
82#define SYMBOL_MOD 0x0002
83#define SYMBOL_NO 0x0004
84#define SYMBOL_CONST 0x0007
85#define SYMBOL_CHECK 0x0008
86#define SYMBOL_CHOICE 0x0010
87#define SYMBOL_CHOICEVAL 0x0020
88#define SYMBOL_PRINTED 0x0040
89#define SYMBOL_VALID 0x0080
90#define SYMBOL_OPTIONAL 0x0100
91#define SYMBOL_WRITE 0x0200
92#define SYMBOL_CHANGED 0x0400
93#define SYMBOL_NEW 0x0800
94#define SYMBOL_AUTO 0x1000
95#define SYMBOL_CHECKED 0x2000
96#define SYMBOL_WARNED 0x8000
97
98#define SYMBOL_MAXLENGTH 256
99#define SYMBOL_HASHSIZE 257
100#define SYMBOL_HASHMASK 0xff
101
102enum prop_type {
103 P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT, P_RANGE
104};
105
106struct property {
107 struct property *next;
108 struct symbol *sym;
109 enum prop_type type;
110 const char *text;
111 struct expr_value visible;
112 struct expr *expr;
113 struct menu *menu;
114 struct file *file;
115 int lineno;
116};
117
118#define for_all_properties(sym, st, tok) \
119 for (st = sym->prop; st; st = st->next) \
120 if (st->type == (tok))
121#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
122#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
123#define for_all_prompts(sym, st) \
124 for (st = sym->prop; st; st = st->next) \
125 if (st->text)
126
127struct menu {
128 struct menu *next;
129 struct menu *parent;
130 struct menu *list;
131 struct symbol *sym;
132 struct property *prompt;
133 struct expr *dep;
134 unsigned int flags;
135 //char *help;
136 struct file *file;
137 int lineno;
138 void *data;
139};
140
141#define MENU_CHANGED 0x0001
142#define MENU_ROOT 0x0002
143
144#ifndef SWIG
145
146extern struct file *file_list;
147extern struct file *current_file;
148struct file *lookup_file(const char *name);
149
150extern struct symbol symbol_yes, symbol_no, symbol_mod;
151extern struct symbol *modules_sym;
152extern int cdebug;
153struct expr *expr_alloc_symbol(struct symbol *sym);
154struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
155struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
156struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
157struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
158struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
159struct expr *expr_copy(struct expr *org);
160void expr_free(struct expr *e);
161int expr_eq(struct expr *e1, struct expr *e2);
162void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
163tristate expr_calc_value(struct expr *e);
164struct expr *expr_eliminate_yn(struct expr *e);
165struct expr *expr_trans_bool(struct expr *e);
166struct expr *expr_eliminate_dups(struct expr *e);
167struct expr *expr_transform(struct expr *e);
168int expr_contains_symbol(struct expr *dep, struct symbol *sym);
169bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
170struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
171struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
172void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
173struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
174
175void expr_fprint(struct expr *e, FILE *out);
176struct gstr; /* forward */
177void expr_gstr_print(struct expr *e, struct gstr *gs);
178
179static inline int expr_is_yes(struct expr *e)
180{
181 return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
182}
183
184static inline int expr_is_no(struct expr *e)
185{
186 return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
187}
188#endif
189
190#ifdef __cplusplus
191}
192#endif
193
194#endif /* EXPR_H */
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
new file mode 100644
index 000000000..665bd5300
--- /dev/null
+++ b/scripts/kconfig/gconf.c
@@ -0,0 +1,1645 @@
1/* Hey EMACS -*- linux-c -*- */
2/*
3 *
4 * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
5 * Released under the terms of the GNU GPL v2.0.
6 *
7 */
8
9#ifdef HAVE_CONFIG_H
10# include <config.h>
11#endif
12
13#include "lkc.h"
14#include "images.c"
15
16#include <glade/glade.h>
17#include <gtk/gtk.h>
18#include <glib.h>
19#include <gdk/gdkkeysyms.h>
20
21#include <stdio.h>
22#include <string.h>
23#include <unistd.h>
24#include <time.h>
25#include <stdlib.h>
26
27//#define DEBUG
28
29enum {
30 SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
31};
32
33static gint view_mode = FULL_VIEW;
34static gboolean show_name = TRUE;
35static gboolean show_range = TRUE;
36static gboolean show_value = TRUE;
37static gboolean show_all = FALSE;
38static gboolean show_debug = FALSE;
39static gboolean resizeable = FALSE;
40
41static gboolean config_changed = FALSE;
42
43static char nohelp_text[] =
44 N_("Sorry, no help available for this option yet.\n");
45
46GtkWidget *main_wnd = NULL;
47GtkWidget *tree1_w = NULL; // left frame
48GtkWidget *tree2_w = NULL; // right frame
49GtkWidget *text_w = NULL;
50GtkWidget *hpaned = NULL;
51GtkWidget *vpaned = NULL;
52GtkWidget *back_btn = NULL;
53
54GtkTextTag *tag1, *tag2;
55GdkColor color;
56
57GtkTreeStore *tree1, *tree2, *tree;
58GtkTreeModel *model1, *model2;
59static GtkTreeIter *parents[256];
60static gint indent;
61
62static struct menu *current; // current node for SINGLE view
63static struct menu *browsed; // browsed node for SPLIT view
64
65enum {
66 COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
67 COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
68 COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
69 COL_NUMBER
70};
71
72static void display_list(void);
73static void display_tree(struct menu *menu);
74static void display_tree_part(void);
75static void update_tree(struct menu *src, GtkTreeIter * dst);
76static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
77static gchar **fill_row(struct menu *menu);
78
79
80/* Helping/Debugging Functions */
81
82
83const char *dbg_print_stype(int val)
84{
85 static char buf[256];
86
87 bzero(buf, 256);
88
89 if (val == S_UNKNOWN)
90 strcpy(buf, "unknown");
91 if (val == S_BOOLEAN)
92 strcpy(buf, "boolean");
93 if (val == S_TRISTATE)
94 strcpy(buf, "tristate");
95 if (val == S_INT)
96 strcpy(buf, "int");
97 if (val == S_HEX)
98 strcpy(buf, "hex");
99 if (val == S_STRING)
100 strcpy(buf, "string");
101 if (val == S_OTHER)
102 strcpy(buf, "other");
103
104#ifdef DEBUG
105 printf("%s", buf);
106#endif
107
108 return buf;
109}
110
111const char *dbg_print_flags(int val)
112{
113 static char buf[256];
114
115 bzero(buf, 256);
116
117 if (val & SYMBOL_YES)
118 strcat(buf, "yes/");
119 if (val & SYMBOL_MOD)
120 strcat(buf, "mod/");
121 if (val & SYMBOL_NO)
122 strcat(buf, "no/");
123 if (val & SYMBOL_CONST)
124 strcat(buf, "const/");
125 if (val & SYMBOL_CHECK)
126 strcat(buf, "check/");
127 if (val & SYMBOL_CHOICE)
128 strcat(buf, "choice/");
129 if (val & SYMBOL_CHOICEVAL)
130 strcat(buf, "choiceval/");
131 if (val & SYMBOL_PRINTED)
132 strcat(buf, "printed/");
133 if (val & SYMBOL_VALID)
134 strcat(buf, "valid/");
135 if (val & SYMBOL_OPTIONAL)
136 strcat(buf, "optional/");
137 if (val & SYMBOL_WRITE)
138 strcat(buf, "write/");
139 if (val & SYMBOL_CHANGED)
140 strcat(buf, "changed/");
141 if (val & SYMBOL_NEW)
142 strcat(buf, "new/");
143 if (val & SYMBOL_AUTO)
144 strcat(buf, "auto/");
145
146 buf[strlen(buf) - 1] = '\0';
147#ifdef DEBUG
148 printf("%s", buf);
149#endif
150
151 return buf;
152}
153
154const char *dbg_print_ptype(int val)
155{
156 static char buf[256];
157
158 bzero(buf, 256);
159
160 if (val == P_UNKNOWN)
161 strcpy(buf, "unknown");
162 if (val == P_PROMPT)
163 strcpy(buf, "prompt");
164 if (val == P_COMMENT)
165 strcpy(buf, "comment");
166 if (val == P_MENU)
167 strcpy(buf, "menu");
168 if (val == P_DEFAULT)
169 strcpy(buf, "default");
170 if (val == P_CHOICE)
171 strcpy(buf, "choice");
172
173#ifdef DEBUG
174 printf("%s", buf);
175#endif
176
177 return buf;
178}
179
180
181void replace_button_icon(GladeXML * xml, GdkDrawable * window,
182 GtkStyle * style, gchar * btn_name, gchar ** xpm)
183{
184 GdkPixmap *pixmap;
185 GdkBitmap *mask;
186 GtkToolButton *button;
187 GtkWidget *image;
188
189 pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
190 &style->bg[GTK_STATE_NORMAL],
191 xpm);
192
193 button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
194 image = gtk_image_new_from_pixmap(pixmap, mask);
195 gtk_widget_show(image);
196 gtk_tool_button_set_icon_widget(button, image);
197}
198
199/* Main Window Initialization */
200void init_main_window(const gchar * glade_file)
201{
202 GladeXML *xml;
203 GtkWidget *widget;
204 GtkTextBuffer *txtbuf;
205 char title[256];
206 GtkStyle *style;
207
208 xml = glade_xml_new(glade_file, "window1", NULL);
209 if (!xml)
210 g_error(_("GUI loading failed !\n"));
211 glade_xml_signal_autoconnect(xml);
212
213 main_wnd = glade_xml_get_widget(xml, "window1");
214 hpaned = glade_xml_get_widget(xml, "hpaned1");
215 vpaned = glade_xml_get_widget(xml, "vpaned1");
216 tree1_w = glade_xml_get_widget(xml, "treeview1");
217 tree2_w = glade_xml_get_widget(xml, "treeview2");
218 text_w = glade_xml_get_widget(xml, "textview3");
219
220 back_btn = glade_xml_get_widget(xml, "button1");
221 gtk_widget_set_sensitive(back_btn, FALSE);
222
223 widget = glade_xml_get_widget(xml, "show_name1");
224 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
225 show_name);
226
227 widget = glade_xml_get_widget(xml, "show_range1");
228 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
229 show_range);
230
231 widget = glade_xml_get_widget(xml, "show_data1");
232 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
233 show_value);
234
235 style = gtk_widget_get_style(main_wnd);
236 widget = glade_xml_get_widget(xml, "toolbar1");
237
238#if 0 /* Use stock Gtk icons instead */
239 replace_button_icon(xml, main_wnd->window, style,
240 "button1", (gchar **) xpm_back);
241 replace_button_icon(xml, main_wnd->window, style,
242 "button2", (gchar **) xpm_load);
243 replace_button_icon(xml, main_wnd->window, style,
244 "button3", (gchar **) xpm_save);
245#endif
246 replace_button_icon(xml, main_wnd->window, style,
247 "button4", (gchar **) xpm_single_view);
248 replace_button_icon(xml, main_wnd->window, style,
249 "button5", (gchar **) xpm_split_view);
250 replace_button_icon(xml, main_wnd->window, style,
251 "button6", (gchar **) xpm_tree_view);
252
253#if 0
254 switch (view_mode) {
255 case SINGLE_VIEW:
256 widget = glade_xml_get_widget(xml, "button4");
257 g_signal_emit_by_name(widget, "clicked");
258 break;
259 case SPLIT_VIEW:
260 widget = glade_xml_get_widget(xml, "button5");
261 g_signal_emit_by_name(widget, "clicked");
262 break;
263 case FULL_VIEW:
264 widget = glade_xml_get_widget(xml, "button6");
265 g_signal_emit_by_name(widget, "clicked");
266 break;
267 }
268#endif
269 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
270 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
271 "foreground", "red",
272 "weight", PANGO_WEIGHT_BOLD,
273 NULL);
274 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
275 /*"style", PANGO_STYLE_OBLIQUE, */
276 NULL);
277
278 sprintf(title, _("Linux Kernel v%s Configuration"),
279 getenv("KERNELVERSION"));
280 gtk_window_set_title(GTK_WINDOW(main_wnd), title);
281
282 gtk_widget_show(main_wnd);
283}
284
285void init_tree_model(void)
286{
287 gint i;
288
289 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
290 G_TYPE_STRING, G_TYPE_STRING,
291 G_TYPE_STRING, G_TYPE_STRING,
292 G_TYPE_STRING, G_TYPE_STRING,
293 G_TYPE_POINTER, GDK_TYPE_COLOR,
294 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
295 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
296 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
297 G_TYPE_BOOLEAN);
298 model2 = GTK_TREE_MODEL(tree2);
299
300 for (parents[0] = NULL, i = 1; i < 256; i++)
301 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
302
303 tree1 = gtk_tree_store_new(COL_NUMBER,
304 G_TYPE_STRING, G_TYPE_STRING,
305 G_TYPE_STRING, G_TYPE_STRING,
306 G_TYPE_STRING, G_TYPE_STRING,
307 G_TYPE_POINTER, GDK_TYPE_COLOR,
308 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
309 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
310 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
311 G_TYPE_BOOLEAN);
312 model1 = GTK_TREE_MODEL(tree1);
313}
314
315void init_left_tree(void)
316{
317 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
318 GtkCellRenderer *renderer;
319 GtkTreeSelection *sel;
320 GtkTreeViewColumn *column;
321
322 gtk_tree_view_set_model(view, model1);
323 gtk_tree_view_set_headers_visible(view, TRUE);
324 gtk_tree_view_set_rules_hint(view, FALSE);
325
326 column = gtk_tree_view_column_new();
327 gtk_tree_view_append_column(view, column);
328 gtk_tree_view_column_set_title(column, _("Options"));
329
330 renderer = gtk_cell_renderer_toggle_new();
331 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
332 renderer, FALSE);
333 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
334 renderer,
335 "active", COL_BTNACT,
336 "inconsistent", COL_BTNINC,
337 "visible", COL_BTNVIS,
338 "radio", COL_BTNRAD, NULL);
339 renderer = gtk_cell_renderer_text_new();
340 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
341 renderer, FALSE);
342 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
343 renderer,
344 "text", COL_OPTION,
345 "foreground-gdk",
346 COL_COLOR, NULL);
347
348 sel = gtk_tree_view_get_selection(view);
349 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
350 gtk_widget_realize(tree1_w);
351}
352
353static void renderer_edited(GtkCellRendererText * cell,
354 const gchar * path_string,
355 const gchar * new_text, gpointer user_data);
356static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
357 gchar * arg1, gpointer user_data);
358
359void init_right_tree(void)
360{
361 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
362 GtkCellRenderer *renderer;
363 GtkTreeSelection *sel;
364 GtkTreeViewColumn *column;
365 gint i;
366
367 gtk_tree_view_set_model(view, model2);
368 gtk_tree_view_set_headers_visible(view, TRUE);
369 gtk_tree_view_set_rules_hint(view, FALSE);
370
371 column = gtk_tree_view_column_new();
372 gtk_tree_view_append_column(view, column);
373 gtk_tree_view_column_set_title(column, _("Options"));
374
375 renderer = gtk_cell_renderer_pixbuf_new();
376 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
377 renderer, FALSE);
378 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
379 renderer,
380 "pixbuf", COL_PIXBUF,
381 "visible", COL_PIXVIS, NULL);
382 renderer = gtk_cell_renderer_toggle_new();
383 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
384 renderer, FALSE);
385 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
386 renderer,
387 "active", COL_BTNACT,
388 "inconsistent", COL_BTNINC,
389 "visible", COL_BTNVIS,
390 "radio", COL_BTNRAD, NULL);
391 /*g_signal_connect(G_OBJECT(renderer), "toggled",
392 G_CALLBACK(renderer_toggled), NULL); */
393 renderer = gtk_cell_renderer_text_new();
394 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
395 renderer, FALSE);
396 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
397 renderer,
398 "text", COL_OPTION,
399 "foreground-gdk",
400 COL_COLOR, NULL);
401
402 renderer = gtk_cell_renderer_text_new();
403 gtk_tree_view_insert_column_with_attributes(view, -1,
404 _("Name"), renderer,
405 "text", COL_NAME,
406 "foreground-gdk",
407 COL_COLOR, NULL);
408 renderer = gtk_cell_renderer_text_new();
409 gtk_tree_view_insert_column_with_attributes(view, -1,
410 "N", renderer,
411 "text", COL_NO,
412 "foreground-gdk",
413 COL_COLOR, NULL);
414 renderer = gtk_cell_renderer_text_new();
415 gtk_tree_view_insert_column_with_attributes(view, -1,
416 "M", renderer,
417 "text", COL_MOD,
418 "foreground-gdk",
419 COL_COLOR, NULL);
420 renderer = gtk_cell_renderer_text_new();
421 gtk_tree_view_insert_column_with_attributes(view, -1,
422 "Y", renderer,
423 "text", COL_YES,
424 "foreground-gdk",
425 COL_COLOR, NULL);
426 renderer = gtk_cell_renderer_text_new();
427 gtk_tree_view_insert_column_with_attributes(view, -1,
428 _("Value"), renderer,
429 "text", COL_VALUE,
430 "editable",
431 COL_EDIT,
432 "foreground-gdk",
433 COL_COLOR, NULL);
434 g_signal_connect(G_OBJECT(renderer), "edited",
435 G_CALLBACK(renderer_edited), NULL);
436
437 column = gtk_tree_view_get_column(view, COL_NAME);
438 gtk_tree_view_column_set_visible(column, show_name);
439 column = gtk_tree_view_get_column(view, COL_NO);
440 gtk_tree_view_column_set_visible(column, show_range);
441 column = gtk_tree_view_get_column(view, COL_MOD);
442 gtk_tree_view_column_set_visible(column, show_range);
443 column = gtk_tree_view_get_column(view, COL_YES);
444 gtk_tree_view_column_set_visible(column, show_range);
445 column = gtk_tree_view_get_column(view, COL_VALUE);
446 gtk_tree_view_column_set_visible(column, show_value);
447
448 if (resizeable) {
449 for (i = 0; i < COL_VALUE; i++) {
450 column = gtk_tree_view_get_column(view, i);
451 gtk_tree_view_column_set_resizable(column, TRUE);
452 }
453 }
454
455 sel = gtk_tree_view_get_selection(view);
456 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
457}
458
459
460/* Utility Functions */
461
462
463static void text_insert_help(struct menu *menu)
464{
465 GtkTextBuffer *buffer;
466 GtkTextIter start, end;
467 const char *prompt = menu_get_prompt(menu);
468 gchar *name;
469 const char *help = _(nohelp_text);
470
471 if (!menu->sym)
472 help = "";
473 else if (menu->sym->help)
474 help = _(menu->sym->help);
475
476 if (menu->sym && menu->sym->name)
477 name = g_strdup_printf(_(menu->sym->name));
478 else
479 name = g_strdup("");
480
481 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
482 gtk_text_buffer_get_bounds(buffer, &start, &end);
483 gtk_text_buffer_delete(buffer, &start, &end);
484 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
485
486 gtk_text_buffer_get_end_iter(buffer, &end);
487 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
488 NULL);
489 gtk_text_buffer_insert_at_cursor(buffer, " ", 1);
490 gtk_text_buffer_get_end_iter(buffer, &end);
491 gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1,
492 NULL);
493 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
494 gtk_text_buffer_get_end_iter(buffer, &end);
495 gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2,
496 NULL);
497}
498
499
500static void text_insert_msg(const char *title, const char *message)
501{
502 GtkTextBuffer *buffer;
503 GtkTextIter start, end;
504 const char *msg = message;
505
506 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
507 gtk_text_buffer_get_bounds(buffer, &start, &end);
508 gtk_text_buffer_delete(buffer, &start, &end);
509 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
510
511 gtk_text_buffer_get_end_iter(buffer, &end);
512 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
513 NULL);
514 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
515 gtk_text_buffer_get_end_iter(buffer, &end);
516 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
517 NULL);
518}
519
520
521/* Main Windows Callbacks */
522
523void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data);
524gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
525 gpointer user_data)
526{
527 GtkWidget *dialog, *label;
528 gint result;
529
530 if (config_changed == FALSE)
531 return FALSE;
532
533 dialog = gtk_dialog_new_with_buttons(_("Warning !"),
534 GTK_WINDOW(main_wnd),
535 (GtkDialogFlags)
536 (GTK_DIALOG_MODAL |
537 GTK_DIALOG_DESTROY_WITH_PARENT),
538 GTK_STOCK_OK,
539 GTK_RESPONSE_YES,
540 GTK_STOCK_NO,
541 GTK_RESPONSE_NO,
542 GTK_STOCK_CANCEL,
543 GTK_RESPONSE_CANCEL, NULL);
544 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
545 GTK_RESPONSE_CANCEL);
546
547 label = gtk_label_new(_("\nSave configuration ?\n"));
548 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
549 gtk_widget_show(label);
550
551 result = gtk_dialog_run(GTK_DIALOG(dialog));
552 switch (result) {
553 case GTK_RESPONSE_YES:
554 on_save1_activate(NULL, NULL);
555 return FALSE;
556 case GTK_RESPONSE_NO:
557 return FALSE;
558 case GTK_RESPONSE_CANCEL:
559 case GTK_RESPONSE_DELETE_EVENT:
560 default:
561 gtk_widget_destroy(dialog);
562 return TRUE;
563 }
564
565 return FALSE;
566}
567
568
569void on_window1_destroy(GtkObject * object, gpointer user_data)
570{
571 gtk_main_quit();
572}
573
574
575void
576on_window1_size_request(GtkWidget * widget,
577 GtkRequisition * requisition, gpointer user_data)
578{
579 static gint old_h;
580 gint w, h;
581
582 if (widget->window == NULL)
583 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
584 else
585 gdk_window_get_size(widget->window, &w, &h);
586
587 if (h == old_h)
588 return;
589 old_h = h;
590
591 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
592}
593
594
595/* Menu & Toolbar Callbacks */
596
597
598static void
599load_filename(GtkFileSelection * file_selector, gpointer user_data)
600{
601 const gchar *fn;
602
603 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
604 (user_data));
605
606 if (conf_read(fn))
607 text_insert_msg(_("Error"), _("Unable to load configuration !"));
608 else
609 display_tree(&rootmenu);
610}
611
612void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
613{
614 GtkWidget *fs;
615
616 fs = gtk_file_selection_new(_("Load file..."));
617 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
618 "clicked",
619 G_CALLBACK(load_filename), (gpointer) fs);
620 g_signal_connect_swapped(GTK_OBJECT
621 (GTK_FILE_SELECTION(fs)->ok_button),
622 "clicked", G_CALLBACK(gtk_widget_destroy),
623 (gpointer) fs);
624 g_signal_connect_swapped(GTK_OBJECT
625 (GTK_FILE_SELECTION(fs)->cancel_button),
626 "clicked", G_CALLBACK(gtk_widget_destroy),
627 (gpointer) fs);
628 gtk_widget_show(fs);
629}
630
631
632void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data)
633{
634 if (conf_write(NULL))
635 text_insert_msg(_("Error"), _("Unable to save configuration !"));
636
637 config_changed = FALSE;
638}
639
640
641static void
642store_filename(GtkFileSelection * file_selector, gpointer user_data)
643{
644 const gchar *fn;
645
646 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
647 (user_data));
648
649 if (conf_write(fn))
650 text_insert_msg(_("Error"), _("Unable to save configuration !"));
651
652 gtk_widget_destroy(GTK_WIDGET(user_data));
653}
654
655void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
656{
657 GtkWidget *fs;
658
659 fs = gtk_file_selection_new(_("Save file as..."));
660 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
661 "clicked",
662 G_CALLBACK(store_filename), (gpointer) fs);
663 g_signal_connect_swapped(GTK_OBJECT
664 (GTK_FILE_SELECTION(fs)->ok_button),
665 "clicked", G_CALLBACK(gtk_widget_destroy),
666 (gpointer) fs);
667 g_signal_connect_swapped(GTK_OBJECT
668 (GTK_FILE_SELECTION(fs)->cancel_button),
669 "clicked", G_CALLBACK(gtk_widget_destroy),
670 (gpointer) fs);
671 gtk_widget_show(fs);
672}
673
674
675void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
676{
677 if (!on_window1_delete_event(NULL, NULL, NULL))
678 gtk_widget_destroy(GTK_WIDGET(main_wnd));
679}
680
681
682void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
683{
684 GtkTreeViewColumn *col;
685
686 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
687 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
688 if (col)
689 gtk_tree_view_column_set_visible(col, show_name);
690}
691
692
693void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
694{
695 GtkTreeViewColumn *col;
696
697 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
698 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
699 if (col)
700 gtk_tree_view_column_set_visible(col, show_range);
701 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
702 if (col)
703 gtk_tree_view_column_set_visible(col, show_range);
704 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
705 if (col)
706 gtk_tree_view_column_set_visible(col, show_range);
707
708}
709
710
711void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
712{
713 GtkTreeViewColumn *col;
714
715 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
716 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
717 if (col)
718 gtk_tree_view_column_set_visible(col, show_value);
719}
720
721
722void
723on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
724{
725 show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
726
727 gtk_tree_store_clear(tree2);
728 display_tree(&rootmenu); // instead of update_tree to speed-up
729}
730
731
732void
733on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
734{
735 show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
736 update_tree(&rootmenu, NULL);
737}
738
739
740void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
741{
742 GtkWidget *dialog;
743 const gchar *intro_text = _(
744 "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
745 "for Linux.\n"
746 "For each option, a blank box indicates the feature is disabled, a\n"
747 "check indicates it is enabled, and a dot indicates that it is to\n"
748 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
749 "\n"
750 "If you do not see an option (e.g., a device driver) that you\n"
751 "believe should be present, try turning on Show All Options\n"
752 "under the Options menu.\n"
753 "Although there is no cross reference yet to help you figure out\n"
754 "what other options must be enabled to support the option you\n"
755 "are interested in, you can still view the help of a grayed-out\n"
756 "option.\n"
757 "\n"
758 "Toggling Show Debug Info under the Options menu will show \n"
759 "the dependencies, which you can then match by examining other options.");
760
761 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
762 GTK_DIALOG_DESTROY_WITH_PARENT,
763 GTK_MESSAGE_INFO,
764 GTK_BUTTONS_CLOSE, intro_text);
765 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
766 G_CALLBACK(gtk_widget_destroy),
767 GTK_OBJECT(dialog));
768 gtk_widget_show_all(dialog);
769}
770
771
772void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
773{
774 GtkWidget *dialog;
775 const gchar *about_text =
776 _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
777 "Based on the source code from Roman Zippel.\n");
778
779 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
780 GTK_DIALOG_DESTROY_WITH_PARENT,
781 GTK_MESSAGE_INFO,
782 GTK_BUTTONS_CLOSE, about_text);
783 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
784 G_CALLBACK(gtk_widget_destroy),
785 GTK_OBJECT(dialog));
786 gtk_widget_show_all(dialog);
787}
788
789
790void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
791{
792 GtkWidget *dialog;
793 const gchar *license_text =
794 _("gkc is released under the terms of the GNU GPL v2.\n"
795 "For more information, please see the source code or\n"
796 "visit http://www.fsf.org/licenses/licenses.html\n");
797
798 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
799 GTK_DIALOG_DESTROY_WITH_PARENT,
800 GTK_MESSAGE_INFO,
801 GTK_BUTTONS_CLOSE, license_text);
802 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
803 G_CALLBACK(gtk_widget_destroy),
804 GTK_OBJECT(dialog));
805 gtk_widget_show_all(dialog);
806}
807
808
809void on_back_clicked(GtkButton * button, gpointer user_data)
810{
811 enum prop_type ptype;
812
813 current = current->parent;
814 ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
815 if (ptype != P_MENU)
816 current = current->parent;
817 display_tree_part();
818
819 if (current == &rootmenu)
820 gtk_widget_set_sensitive(back_btn, FALSE);
821}
822
823
824void on_load_clicked(GtkButton * button, gpointer user_data)
825{
826 on_load1_activate(NULL, user_data);
827}
828
829
830void on_save_clicked(GtkButton * button, gpointer user_data)
831{
832 on_save1_activate(NULL, user_data);
833}
834
835
836void on_single_clicked(GtkButton * button, gpointer user_data)
837{
838 view_mode = SINGLE_VIEW;
839 gtk_paned_set_position(GTK_PANED(hpaned), 0);
840 gtk_widget_hide(tree1_w);
841 current = &rootmenu;
842 display_tree_part();
843}
844
845
846void on_split_clicked(GtkButton * button, gpointer user_data)
847{
848 gint w, h;
849 view_mode = SPLIT_VIEW;
850 gtk_widget_show(tree1_w);
851 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
852 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
853 if (tree2)
854 gtk_tree_store_clear(tree2);
855 display_list();
856
857 /* Disable back btn, like in full mode. */
858 gtk_widget_set_sensitive(back_btn, FALSE);
859}
860
861
862void on_full_clicked(GtkButton * button, gpointer user_data)
863{
864 view_mode = FULL_VIEW;
865 gtk_paned_set_position(GTK_PANED(hpaned), 0);
866 gtk_widget_hide(tree1_w);
867 if (tree2)
868 gtk_tree_store_clear(tree2);
869 display_tree(&rootmenu);
870 gtk_widget_set_sensitive(back_btn, FALSE);
871}
872
873
874void on_collapse_clicked(GtkButton * button, gpointer user_data)
875{
876 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
877}
878
879
880void on_expand_clicked(GtkButton * button, gpointer user_data)
881{
882 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
883}
884
885
886/* CTree Callbacks */
887
888/* Change hex/int/string value in the cell */
889static void renderer_edited(GtkCellRendererText * cell,
890 const gchar * path_string,
891 const gchar * new_text, gpointer user_data)
892{
893 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
894 GtkTreeIter iter;
895 const char *old_def, *new_def;
896 struct menu *menu;
897 struct symbol *sym;
898
899 if (!gtk_tree_model_get_iter(model2, &iter, path))
900 return;
901
902 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
903 sym = menu->sym;
904
905 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
906 new_def = new_text;
907
908 sym_set_string_value(sym, new_def);
909
910 config_changed = TRUE;
911 update_tree(&rootmenu, NULL);
912
913 gtk_tree_path_free(path);
914}
915
916/* Change the value of a symbol and update the tree */
917static void change_sym_value(struct menu *menu, gint col)
918{
919 struct symbol *sym = menu->sym;
920 tristate oldval, newval;
921
922 if (!sym)
923 return;
924
925 if (col == COL_NO)
926 newval = no;
927 else if (col == COL_MOD)
928 newval = mod;
929 else if (col == COL_YES)
930 newval = yes;
931 else
932 return;
933
934 switch (sym_get_type(sym)) {
935 case S_BOOLEAN:
936 case S_TRISTATE:
937 oldval = sym_get_tristate_value(sym);
938 if (!sym_tristate_within_range(sym, newval))
939 newval = yes;
940 sym_set_tristate_value(sym, newval);
941 config_changed = TRUE;
942 if (view_mode == FULL_VIEW)
943 update_tree(&rootmenu, NULL);
944 else if (view_mode == SPLIT_VIEW) {
945 update_tree(browsed, NULL);
946 display_list();
947 }
948 else if (view_mode == SINGLE_VIEW)
949 display_tree_part(); //fixme: keep exp/coll
950 break;
951 case S_INT:
952 case S_HEX:
953 case S_STRING:
954 default:
955 break;
956 }
957}
958
959static void toggle_sym_value(struct menu *menu)
960{
961 if (!menu->sym)
962 return;
963
964 sym_toggle_tristate_value(menu->sym);
965 if (view_mode == FULL_VIEW)
966 update_tree(&rootmenu, NULL);
967 else if (view_mode == SPLIT_VIEW) {
968 update_tree(browsed, NULL);
969 display_list();
970 }
971 else if (view_mode == SINGLE_VIEW)
972 display_tree_part(); //fixme: keep exp/coll
973}
974
975static void renderer_toggled(GtkCellRendererToggle * cell,
976 gchar * path_string, gpointer user_data)
977{
978 GtkTreePath *path, *sel_path = NULL;
979 GtkTreeIter iter, sel_iter;
980 GtkTreeSelection *sel;
981 struct menu *menu;
982
983 path = gtk_tree_path_new_from_string(path_string);
984 if (!gtk_tree_model_get_iter(model2, &iter, path))
985 return;
986
987 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
988 if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
989 sel_path = gtk_tree_model_get_path(model2, &sel_iter);
990 if (!sel_path)
991 goto out1;
992 if (gtk_tree_path_compare(path, sel_path))
993 goto out2;
994
995 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
996 toggle_sym_value(menu);
997
998 out2:
999 gtk_tree_path_free(sel_path);
1000 out1:
1001 gtk_tree_path_free(path);
1002}
1003
1004static gint column2index(GtkTreeViewColumn * column)
1005{
1006 gint i;
1007
1008 for (i = 0; i < COL_NUMBER; i++) {
1009 GtkTreeViewColumn *col;
1010
1011 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
1012 if (col == column)
1013 return i;
1014 }
1015
1016 return -1;
1017}
1018
1019
1020/* User click: update choice (full) or goes down (single) */
1021gboolean
1022on_treeview2_button_press_event(GtkWidget * widget,
1023 GdkEventButton * event, gpointer user_data)
1024{
1025 GtkTreeView *view = GTK_TREE_VIEW(widget);
1026 GtkTreePath *path;
1027 GtkTreeViewColumn *column;
1028 GtkTreeIter iter;
1029 struct menu *menu;
1030 gint col;
1031
1032#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
1033 gint tx = (gint) event->x;
1034 gint ty = (gint) event->y;
1035 gint cx, cy;
1036
1037 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1038 &cy);
1039#else
1040 gtk_tree_view_get_cursor(view, &path, &column);
1041#endif
1042 if (path == NULL)
1043 return FALSE;
1044
1045 if (!gtk_tree_model_get_iter(model2, &iter, path))
1046 return FALSE;
1047 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1048
1049 col = column2index(column);
1050 if (event->type == GDK_2BUTTON_PRESS) {
1051 enum prop_type ptype;
1052 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1053
1054 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
1055 // goes down into menu
1056 current = menu;
1057 display_tree_part();
1058 gtk_widget_set_sensitive(back_btn, TRUE);
1059 } else if ((col == COL_OPTION)) {
1060 toggle_sym_value(menu);
1061 gtk_tree_view_expand_row(view, path, TRUE);
1062 }
1063 } else {
1064 if (col == COL_VALUE) {
1065 toggle_sym_value(menu);
1066 gtk_tree_view_expand_row(view, path, TRUE);
1067 } else if (col == COL_NO || col == COL_MOD
1068 || col == COL_YES) {
1069 change_sym_value(menu, col);
1070 gtk_tree_view_expand_row(view, path, TRUE);
1071 }
1072 }
1073
1074 return FALSE;
1075}
1076
1077/* Key pressed: update choice */
1078gboolean
1079on_treeview2_key_press_event(GtkWidget * widget,
1080 GdkEventKey * event, gpointer user_data)
1081{
1082 GtkTreeView *view = GTK_TREE_VIEW(widget);
1083 GtkTreePath *path;
1084 GtkTreeViewColumn *column;
1085 GtkTreeIter iter;
1086 struct menu *menu;
1087 gint col;
1088
1089 gtk_tree_view_get_cursor(view, &path, &column);
1090 if (path == NULL)
1091 return FALSE;
1092
1093 if (event->keyval == GDK_space) {
1094 if (gtk_tree_view_row_expanded(view, path))
1095 gtk_tree_view_collapse_row(view, path);
1096 else
1097 gtk_tree_view_expand_row(view, path, FALSE);
1098 return TRUE;
1099 }
1100 if (event->keyval == GDK_KP_Enter) {
1101 }
1102 if (widget == tree1_w)
1103 return FALSE;
1104
1105 gtk_tree_model_get_iter(model2, &iter, path);
1106 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1107
1108 if (!strcasecmp(event->string, "n"))
1109 col = COL_NO;
1110 else if (!strcasecmp(event->string, "m"))
1111 col = COL_MOD;
1112 else if (!strcasecmp(event->string, "y"))
1113 col = COL_YES;
1114 else
1115 col = -1;
1116 change_sym_value(menu, col);
1117
1118 return FALSE;
1119}
1120
1121
1122/* Row selection changed: update help */
1123void
1124on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
1125{
1126 GtkTreeSelection *selection;
1127 GtkTreeIter iter;
1128 struct menu *menu;
1129
1130 selection = gtk_tree_view_get_selection(treeview);
1131 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
1132 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1133 text_insert_help(menu);
1134 }
1135}
1136
1137
1138/* User click: display sub-tree in the right frame. */
1139gboolean
1140on_treeview1_button_press_event(GtkWidget * widget,
1141 GdkEventButton * event, gpointer user_data)
1142{
1143 GtkTreeView *view = GTK_TREE_VIEW(widget);
1144 GtkTreePath *path;
1145 GtkTreeViewColumn *column;
1146 GtkTreeIter iter;
1147 struct menu *menu;
1148
1149 gint tx = (gint) event->x;
1150 gint ty = (gint) event->y;
1151 gint cx, cy;
1152
1153 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1154 &cy);
1155 if (path == NULL)
1156 return FALSE;
1157
1158 gtk_tree_model_get_iter(model1, &iter, path);
1159 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1160
1161 if (event->type == GDK_2BUTTON_PRESS) {
1162 toggle_sym_value(menu);
1163 current = menu;
1164 display_tree_part();
1165 } else {
1166 browsed = menu;
1167 display_tree_part();
1168 }
1169
1170 gtk_widget_realize(tree2_w);
1171 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1172 gtk_widget_grab_focus(tree2_w);
1173
1174 return FALSE;
1175}
1176
1177
1178/* Fill a row of strings */
1179static gchar **fill_row(struct menu *menu)
1180{
1181 static gchar *row[COL_NUMBER];
1182 struct symbol *sym = menu->sym;
1183 const char *def;
1184 int stype;
1185 tristate val;
1186 enum prop_type ptype;
1187 int i;
1188
1189 for (i = COL_OPTION; i <= COL_COLOR; i++)
1190 g_free(row[i]);
1191 bzero(row, sizeof(row));
1192
1193 row[COL_OPTION] =
1194 g_strdup_printf("%s %s", menu_get_prompt(menu),
1195 sym ? (sym->
1196 flags & SYMBOL_NEW ? "(NEW)" : "") :
1197 "");
1198
1199 if (show_all && !menu_is_visible(menu))
1200 row[COL_COLOR] = g_strdup("DarkGray");
1201 else
1202 row[COL_COLOR] = g_strdup("Black");
1203
1204 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1205 switch (ptype) {
1206 case P_MENU:
1207 row[COL_PIXBUF] = (gchar *) xpm_menu;
1208 if (view_mode == SINGLE_VIEW)
1209 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1210 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1211 break;
1212 case P_COMMENT:
1213 row[COL_PIXBUF] = (gchar *) xpm_void;
1214 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1215 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1216 break;
1217 default:
1218 row[COL_PIXBUF] = (gchar *) xpm_void;
1219 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1220 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1221 break;
1222 }
1223
1224 if (!sym)
1225 return row;
1226 row[COL_NAME] = g_strdup(sym->name);
1227
1228 sym_calc_value(sym);
1229 sym->flags &= ~SYMBOL_CHANGED;
1230
1231 if (sym_is_choice(sym)) { // parse childs for getting final value
1232 struct menu *child;
1233 struct symbol *def_sym = sym_get_choice_value(sym);
1234 struct menu *def_menu = NULL;
1235
1236 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1237
1238 for (child = menu->list; child; child = child->next) {
1239 if (menu_is_visible(child)
1240 && child->sym == def_sym)
1241 def_menu = child;
1242 }
1243
1244 if (def_menu)
1245 row[COL_VALUE] =
1246 g_strdup(menu_get_prompt(def_menu));
1247 }
1248 if (sym->flags & SYMBOL_CHOICEVAL)
1249 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1250
1251 stype = sym_get_type(sym);
1252 switch (stype) {
1253 case S_BOOLEAN:
1254 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
1255 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1256 if (sym_is_choice(sym))
1257 break;
1258 case S_TRISTATE:
1259 val = sym_get_tristate_value(sym);
1260 switch (val) {
1261 case no:
1262 row[COL_NO] = g_strdup("N");
1263 row[COL_VALUE] = g_strdup("N");
1264 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1265 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1266 break;
1267 case mod:
1268 row[COL_MOD] = g_strdup("M");
1269 row[COL_VALUE] = g_strdup("M");
1270 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1271 break;
1272 case yes:
1273 row[COL_YES] = g_strdup("Y");
1274 row[COL_VALUE] = g_strdup("Y");
1275 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1276 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1277 break;
1278 }
1279
1280 if (val != no && sym_tristate_within_range(sym, no))
1281 row[COL_NO] = g_strdup("_");
1282 if (val != mod && sym_tristate_within_range(sym, mod))
1283 row[COL_MOD] = g_strdup("_");
1284 if (val != yes && sym_tristate_within_range(sym, yes))
1285 row[COL_YES] = g_strdup("_");
1286 break;
1287 case S_INT:
1288 case S_HEX:
1289 case S_STRING:
1290 def = sym_get_string_value(sym);
1291 row[COL_VALUE] = g_strdup(def);
1292 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1293 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1294 break;
1295 }
1296
1297 return row;
1298}
1299
1300
1301/* Set the node content with a row of strings */
1302static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1303{
1304 GdkColor color;
1305 gboolean success;
1306 GdkPixbuf *pix;
1307
1308 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1309 row[COL_PIXBUF]);
1310
1311 gdk_color_parse(row[COL_COLOR], &color);
1312 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1313 FALSE, FALSE, &success);
1314
1315 gtk_tree_store_set(tree, node,
1316 COL_OPTION, row[COL_OPTION],
1317 COL_NAME, row[COL_NAME],
1318 COL_NO, row[COL_NO],
1319 COL_MOD, row[COL_MOD],
1320 COL_YES, row[COL_YES],
1321 COL_VALUE, row[COL_VALUE],
1322 COL_MENU, (gpointer) menu,
1323 COL_COLOR, &color,
1324 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1325 COL_PIXBUF, pix,
1326 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1327 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1328 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1329 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1330 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1331 -1);
1332
1333 g_object_unref(pix);
1334}
1335
1336
1337/* Add a node to the tree */
1338static void place_node(struct menu *menu, char **row)
1339{
1340 GtkTreeIter *parent = parents[indent - 1];
1341 GtkTreeIter *node = parents[indent];
1342
1343 gtk_tree_store_append(tree, node, parent);
1344 set_node(node, menu, row);
1345}
1346
1347
1348/* Find a node in the GTK+ tree */
1349static GtkTreeIter found;
1350
1351/*
1352 * Find a menu in the GtkTree starting at parent.
1353 */
1354GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
1355 struct menu *tofind)
1356{
1357 GtkTreeIter iter;
1358 GtkTreeIter *child = &iter;
1359 gboolean valid;
1360 GtkTreeIter *ret;
1361
1362 valid = gtk_tree_model_iter_children(model2, child, parent);
1363 while (valid) {
1364 struct menu *menu;
1365
1366 gtk_tree_model_get(model2, child, 6, &menu, -1);
1367
1368 if (menu == tofind) {
1369 memcpy(&found, child, sizeof(GtkTreeIter));
1370 return &found;
1371 }
1372
1373 ret = gtktree_iter_find_node(child, tofind);
1374 if (ret)
1375 return ret;
1376
1377 valid = gtk_tree_model_iter_next(model2, child);
1378 }
1379
1380 return NULL;
1381}
1382
1383
1384/*
1385 * Update the tree by adding/removing entries
1386 * Does not change other nodes
1387 */
1388static void update_tree(struct menu *src, GtkTreeIter * dst)
1389{
1390 struct menu *child1;
1391 GtkTreeIter iter, tmp;
1392 GtkTreeIter *child2 = &iter;
1393 gboolean valid;
1394 GtkTreeIter *sibling;
1395 struct symbol *sym;
1396 struct property *prop;
1397 struct menu *menu1, *menu2;
1398
1399 if (src == &rootmenu)
1400 indent = 1;
1401
1402 valid = gtk_tree_model_iter_children(model2, child2, dst);
1403 for (child1 = src->list; child1; child1 = child1->next) {
1404
1405 prop = child1->prompt;
1406 sym = child1->sym;
1407
1408 reparse:
1409 menu1 = child1;
1410 if (valid)
1411 gtk_tree_model_get(model2, child2, COL_MENU,
1412 &menu2, -1);
1413 else
1414 menu2 = NULL; // force adding of a first child
1415
1416#ifdef DEBUG
1417 printf("%*c%s | %s\n", indent, ' ',
1418 menu1 ? menu_get_prompt(menu1) : "nil",
1419 menu2 ? menu_get_prompt(menu2) : "nil");
1420#endif
1421
1422 if (!menu_is_visible(child1) && !show_all) { // remove node
1423 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1424 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1425 valid = gtk_tree_model_iter_next(model2,
1426 child2);
1427 gtk_tree_store_remove(tree2, &tmp);
1428 if (!valid)
1429 return; // next parent
1430 else
1431 goto reparse; // next child
1432 } else
1433 continue;
1434 }
1435
1436 if (menu1 != menu2) {
1437 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1438 if (!valid && !menu2)
1439 sibling = NULL;
1440 else
1441 sibling = child2;
1442 gtk_tree_store_insert_before(tree2,
1443 child2,
1444 dst, sibling);
1445 set_node(child2, menu1, fill_row(menu1));
1446 if (menu2 == NULL)
1447 valid = TRUE;
1448 } else { // remove node
1449 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1450 valid = gtk_tree_model_iter_next(model2,
1451 child2);
1452 gtk_tree_store_remove(tree2, &tmp);
1453 if (!valid)
1454 return; // next parent
1455 else
1456 goto reparse; // next child
1457 }
1458 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1459 set_node(child2, menu1, fill_row(menu1));
1460 }
1461
1462 indent++;
1463 update_tree(child1, child2);
1464 indent--;
1465
1466 valid = gtk_tree_model_iter_next(model2, child2);
1467 }
1468}
1469
1470
1471/* Display the whole tree (single/split/full view) */
1472static void display_tree(struct menu *menu)
1473{
1474 struct symbol *sym;
1475 struct property *prop;
1476 struct menu *child;
1477 enum prop_type ptype;
1478
1479 if (menu == &rootmenu) {
1480 indent = 1;
1481 current = &rootmenu;
1482 }
1483
1484 for (child = menu->list; child; child = child->next) {
1485 prop = child->prompt;
1486 sym = child->sym;
1487 ptype = prop ? prop->type : P_UNKNOWN;
1488
1489 if (sym)
1490 sym->flags &= ~SYMBOL_CHANGED;
1491
1492 if ((view_mode == SPLIT_VIEW)
1493 && !(child->flags & MENU_ROOT) && (tree == tree1))
1494 continue;
1495
1496 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1497 && (tree == tree2))
1498 continue;
1499
1500 if (menu_is_visible(child) || show_all)
1501 place_node(child, fill_row(child));
1502#ifdef DEBUG
1503 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1504 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
1505 dbg_print_ptype(ptype);
1506 printf(" | ");
1507 if (sym) {
1508 dbg_print_stype(sym->type);
1509 printf(" | ");
1510 dbg_print_flags(sym->flags);
1511 printf("\n");
1512 } else
1513 printf("\n");
1514#endif
1515 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1516 && (tree == tree2))
1517 continue;
1518/*
1519 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
1520 || (view_mode == FULL_VIEW)
1521 || (view_mode == SPLIT_VIEW))*/
1522 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
1523 || (view_mode == FULL_VIEW)
1524 || (view_mode == SPLIT_VIEW)) {
1525 indent++;
1526 display_tree(child);
1527 indent--;
1528 }
1529 }
1530}
1531
1532/* Display a part of the tree starting at current node (single/split view) */
1533static void display_tree_part(void)
1534{
1535 if (tree2)
1536 gtk_tree_store_clear(tree2);
1537 if (view_mode == SINGLE_VIEW)
1538 display_tree(current);
1539 else if (view_mode == SPLIT_VIEW)
1540 display_tree(browsed);
1541 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1542}
1543
1544/* Display the list in the left frame (split view) */
1545static void display_list(void)
1546{
1547 if (tree1)
1548 gtk_tree_store_clear(tree1);
1549
1550 tree = tree1;
1551 display_tree(&rootmenu);
1552 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1553 tree = tree2;
1554}
1555
1556void fixup_rootmenu(struct menu *menu)
1557{
1558 struct menu *child;
1559 static int menu_cnt = 0;
1560
1561 menu->flags |= MENU_ROOT;
1562 for (child = menu->list; child; child = child->next) {
1563 if (child->prompt && child->prompt->type == P_MENU) {
1564 menu_cnt++;
1565 fixup_rootmenu(child);
1566 menu_cnt--;
1567 } else if (!menu_cnt)
1568 fixup_rootmenu(child);
1569 }
1570}
1571
1572
1573/* Main */
1574int main(int ac, char *av[])
1575{
1576 const char *name;
1577 char *env;
1578 gchar *glade_file;
1579
1580#ifndef LKC_DIRECT_LINK
1581 kconfig_load();
1582#endif
1583
1584 bindtextdomain(PACKAGE, LOCALEDIR);
1585 bind_textdomain_codeset(PACKAGE, "UTF-8");
1586 textdomain(PACKAGE);
1587
1588 /* GTK stuffs */
1589 gtk_set_locale();
1590 gtk_init(&ac, &av);
1591 glade_init();
1592
1593 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1594 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1595
1596 /* Determine GUI path */
1597 env = getenv(SRCTREE);
1598 if (env)
1599 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1600 else if (av[0][0] == '/')
1601 glade_file = g_strconcat(av[0], ".glade", NULL);
1602 else
1603 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1604
1605 /* Load the interface and connect signals */
1606 init_main_window(glade_file);
1607 init_tree_model();
1608 init_left_tree();
1609 init_right_tree();
1610
1611 /* Conf stuffs */
1612 if (ac > 1 && av[1][0] == '-') {
1613 switch (av[1][1]) {
1614 case 'a':
1615 //showAll = 1;
1616 break;
1617 case 'h':
1618 case '?':
1619 printf("%s <config>\n", av[0]);
1620 exit(0);
1621 }
1622 name = av[2];
1623 } else
1624 name = av[1];
1625
1626 conf_parse(name);
1627 fixup_rootmenu(&rootmenu);
1628 conf_read(NULL);
1629
1630 switch (view_mode) {
1631 case SINGLE_VIEW:
1632 display_tree_part();
1633 break;
1634 case SPLIT_VIEW:
1635 display_list();
1636 break;
1637 case FULL_VIEW:
1638 display_tree(&rootmenu);
1639 break;
1640 }
1641
1642 gtk_main();
1643
1644 return 0;
1645}
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
new file mode 100644
index 000000000..f8744ed64
--- /dev/null
+++ b/scripts/kconfig/gconf.glade
@@ -0,0 +1,648 @@
1<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
2<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
3
4<glade-interface>
5
6<widget class="GtkWindow" id="window1">
7 <property name="visible">True</property>
8 <property name="title" translatable="yes">Gtk Kernel Configurator</property>
9 <property name="type">GTK_WINDOW_TOPLEVEL</property>
10 <property name="window_position">GTK_WIN_POS_NONE</property>
11 <property name="modal">False</property>
12 <property name="default_width">640</property>
13 <property name="default_height">480</property>
14 <property name="resizable">True</property>
15 <property name="destroy_with_parent">False</property>
16 <property name="decorated">True</property>
17 <property name="skip_taskbar_hint">False</property>
18 <property name="skip_pager_hint">False</property>
19 <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
20 <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
21 <signal name="destroy" handler="on_window1_destroy" object="window1"/>
22 <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/>
23 <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/>
24
25 <child>
26 <widget class="GtkVBox" id="vbox1">
27 <property name="visible">True</property>
28 <property name="homogeneous">False</property>
29 <property name="spacing">0</property>
30
31 <child>
32 <widget class="GtkMenuBar" id="menubar1">
33 <property name="visible">True</property>
34
35 <child>
36 <widget class="GtkMenuItem" id="file1">
37 <property name="visible">True</property>
38 <property name="label" translatable="yes">_File</property>
39 <property name="use_underline">True</property>
40
41 <child>
42 <widget class="GtkMenu" id="file1_menu">
43
44 <child>
45 <widget class="GtkImageMenuItem" id="load1">
46 <property name="visible">True</property>
47 <property name="tooltip" translatable="yes">Load a config file</property>
48 <property name="label" translatable="yes">_Load</property>
49 <property name="use_underline">True</property>
50 <signal name="activate" handler="on_load1_activate"/>
51 <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
52
53 <child internal-child="image">
54 <widget class="GtkImage" id="image39">
55 <property name="visible">True</property>
56 <property name="stock">gtk-open</property>
57 <property name="icon_size">1</property>
58 <property name="xalign">0.5</property>
59 <property name="yalign">0.5</property>
60 <property name="xpad">0</property>
61 <property name="ypad">0</property>
62 </widget>
63 </child>
64 </widget>
65 </child>
66
67 <child>
68 <widget class="GtkImageMenuItem" id="save1">
69 <property name="visible">True</property>
70 <property name="tooltip" translatable="yes">Save the config in .config</property>
71 <property name="label" translatable="yes">_Save</property>
72 <property name="use_underline">True</property>
73 <signal name="activate" handler="on_save1_activate"/>
74 <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
75
76 <child internal-child="image">
77 <widget class="GtkImage" id="image40">
78 <property name="visible">True</property>
79 <property name="stock">gtk-save</property>
80 <property name="icon_size">1</property>
81 <property name="xalign">0.5</property>
82 <property name="yalign">0.5</property>
83 <property name="xpad">0</property>
84 <property name="ypad">0</property>
85 </widget>
86 </child>
87 </widget>
88 </child>
89
90 <child>
91 <widget class="GtkImageMenuItem" id="save_as1">
92 <property name="visible">True</property>
93 <property name="tooltip" translatable="yes">Save the config in a file</property>
94 <property name="label" translatable="yes">Save _as</property>
95 <property name="use_underline">True</property>
96 <signal name="activate" handler="on_save_as1_activate"/>
97
98 <child internal-child="image">
99 <widget class="GtkImage" id="image41">
100 <property name="visible">True</property>
101 <property name="stock">gtk-save-as</property>
102 <property name="icon_size">1</property>
103 <property name="xalign">0.5</property>
104 <property name="yalign">0.5</property>
105 <property name="xpad">0</property>
106 <property name="ypad">0</property>
107 </widget>
108 </child>
109 </widget>
110 </child>
111
112 <child>
113 <widget class="GtkSeparatorMenuItem" id="separator1">
114 <property name="visible">True</property>
115 </widget>
116 </child>
117
118 <child>
119 <widget class="GtkImageMenuItem" id="quit1">
120 <property name="visible">True</property>
121 <property name="label" translatable="yes">_Quit</property>
122 <property name="use_underline">True</property>
123 <signal name="activate" handler="on_quit1_activate"/>
124 <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
125
126 <child internal-child="image">
127 <widget class="GtkImage" id="image42">
128 <property name="visible">True</property>
129 <property name="stock">gtk-quit</property>
130 <property name="icon_size">1</property>
131 <property name="xalign">0.5</property>
132 <property name="yalign">0.5</property>
133 <property name="xpad">0</property>
134 <property name="ypad">0</property>
135 </widget>
136 </child>
137 </widget>
138 </child>
139 </widget>
140 </child>
141 </widget>
142 </child>
143
144 <child>
145 <widget class="GtkMenuItem" id="options1">
146 <property name="visible">True</property>
147 <property name="label" translatable="yes">_Options</property>
148 <property name="use_underline">True</property>
149
150 <child>
151 <widget class="GtkMenu" id="options1_menu">
152
153 <child>
154 <widget class="GtkCheckMenuItem" id="show_name1">
155 <property name="visible">True</property>
156 <property name="tooltip" translatable="yes">Show name</property>
157 <property name="label" translatable="yes">Show _name</property>
158 <property name="use_underline">True</property>
159 <property name="active">False</property>
160 <signal name="activate" handler="on_show_name1_activate"/>
161 </widget>
162 </child>
163
164 <child>
165 <widget class="GtkCheckMenuItem" id="show_range1">
166 <property name="visible">True</property>
167 <property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
168 <property name="label" translatable="yes">Show _range</property>
169 <property name="use_underline">True</property>
170 <property name="active">False</property>
171 <signal name="activate" handler="on_show_range1_activate"/>
172 </widget>
173 </child>
174
175 <child>
176 <widget class="GtkCheckMenuItem" id="show_data1">
177 <property name="visible">True</property>
178 <property name="tooltip" translatable="yes">Show value of the option</property>
179 <property name="label" translatable="yes">Show _data</property>
180 <property name="use_underline">True</property>
181 <property name="active">False</property>
182 <signal name="activate" handler="on_show_data1_activate"/>
183 </widget>
184 </child>
185
186 <child>
187 <widget class="GtkSeparatorMenuItem" id="separator2">
188 <property name="visible">True</property>
189 </widget>
190 </child>
191
192 <child>
193 <widget class="GtkCheckMenuItem" id="show_all_options1">
194 <property name="visible">True</property>
195 <property name="tooltip" translatable="yes">Show all options</property>
196 <property name="label" translatable="yes">Show all _options</property>
197 <property name="use_underline">True</property>
198 <property name="active">False</property>
199 <signal name="activate" handler="on_show_all_options1_activate"/>
200 </widget>
201 </child>
202
203 <child>
204 <widget class="GtkCheckMenuItem" id="show_debug_info1">
205 <property name="visible">True</property>
206 <property name="tooltip" translatable="yes">Show masked options</property>
207 <property name="label" translatable="yes">Show _debug info</property>
208 <property name="use_underline">True</property>
209 <property name="active">False</property>
210 <signal name="activate" handler="on_show_debug_info1_activate"/>
211 </widget>
212 </child>
213 </widget>
214 </child>
215 </widget>
216 </child>
217
218 <child>
219 <widget class="GtkMenuItem" id="help1">
220 <property name="visible">True</property>
221 <property name="label" translatable="yes">_Help</property>
222 <property name="use_underline">True</property>
223
224 <child>
225 <widget class="GtkMenu" id="help1_menu">
226
227 <child>
228 <widget class="GtkImageMenuItem" id="introduction1">
229 <property name="visible">True</property>
230 <property name="label" translatable="yes">_Introduction</property>
231 <property name="use_underline">True</property>
232 <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
233 <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/>
234
235 <child internal-child="image">
236 <widget class="GtkImage" id="image43">
237 <property name="visible">True</property>
238 <property name="stock">gtk-dialog-question</property>
239 <property name="icon_size">1</property>
240 <property name="xalign">0.5</property>
241 <property name="yalign">0.5</property>
242 <property name="xpad">0</property>
243 <property name="ypad">0</property>
244 </widget>
245 </child>
246 </widget>
247 </child>
248
249 <child>
250 <widget class="GtkImageMenuItem" id="about1">
251 <property name="visible">True</property>
252 <property name="label" translatable="yes">_About</property>
253 <property name="use_underline">True</property>
254 <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
255 <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
256
257 <child internal-child="image">
258 <widget class="GtkImage" id="image44">
259 <property name="visible">True</property>
260 <property name="stock">gtk-properties</property>
261 <property name="icon_size">1</property>
262 <property name="xalign">0.5</property>
263 <property name="yalign">0.5</property>
264 <property name="xpad">0</property>
265 <property name="ypad">0</property>
266 </widget>
267 </child>
268 </widget>
269 </child>
270
271 <child>
272 <widget class="GtkImageMenuItem" id="license1">
273 <property name="visible">True</property>
274 <property name="label" translatable="yes">_License</property>
275 <property name="use_underline">True</property>
276 <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
277
278 <child internal-child="image">
279 <widget class="GtkImage" id="image45">
280 <property name="visible">True</property>
281 <property name="stock">gtk-justify-fill</property>
282 <property name="icon_size">1</property>
283 <property name="xalign">0.5</property>
284 <property name="yalign">0.5</property>
285 <property name="xpad">0</property>
286 <property name="ypad">0</property>
287 </widget>
288 </child>
289 </widget>
290 </child>
291 </widget>
292 </child>
293 </widget>
294 </child>
295 </widget>
296 <packing>
297 <property name="padding">0</property>
298 <property name="expand">False</property>
299 <property name="fill">False</property>
300 </packing>
301 </child>
302
303 <child>
304 <widget class="GtkHandleBox" id="handlebox1">
305 <property name="visible">True</property>
306 <property name="shadow_type">GTK_SHADOW_OUT</property>
307 <property name="handle_position">GTK_POS_LEFT</property>
308 <property name="snap_edge">GTK_POS_TOP</property>
309
310 <child>
311 <widget class="GtkToolbar" id="toolbar1">
312 <property name="visible">True</property>
313 <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
314 <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
315 <property name="tooltips">True</property>
316 <property name="show_arrow">True</property>
317
318 <child>
319 <widget class="GtkToolButton" id="button1">
320 <property name="visible">True</property>
321 <property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
322 <property name="label" translatable="yes">Back</property>
323 <property name="use_underline">True</property>
324 <property name="stock_id">gtk-undo</property>
325 <property name="visible_horizontal">True</property>
326 <property name="visible_vertical">True</property>
327 <property name="is_important">False</property>
328 <signal name="clicked" handler="on_back_clicked"/>
329 </widget>
330 <packing>
331 <property name="expand">False</property>
332 <property name="homogeneous">True</property>
333 </packing>
334 </child>
335
336 <child>
337 <widget class="GtkToolItem" id="toolitem1">
338 <property name="visible">True</property>
339 <property name="visible_horizontal">True</property>
340 <property name="visible_vertical">True</property>
341 <property name="is_important">False</property>
342
343 <child>
344 <widget class="GtkVSeparator" id="vseparator1">
345 <property name="visible">True</property>
346 </widget>
347 </child>
348 </widget>
349 <packing>
350 <property name="expand">False</property>
351 <property name="homogeneous">False</property>
352 </packing>
353 </child>
354
355 <child>
356 <widget class="GtkToolButton" id="button2">
357 <property name="visible">True</property>
358 <property name="tooltip" translatable="yes">Load a config file</property>
359 <property name="label" translatable="yes">Load</property>
360 <property name="use_underline">True</property>
361 <property name="stock_id">gtk-open</property>
362 <property name="visible_horizontal">True</property>
363 <property name="visible_vertical">True</property>
364 <property name="is_important">False</property>
365 <signal name="clicked" handler="on_load_clicked"/>
366 </widget>
367 <packing>
368 <property name="expand">False</property>
369 <property name="homogeneous">True</property>
370 </packing>
371 </child>
372
373 <child>
374 <widget class="GtkToolButton" id="button3">
375 <property name="visible">True</property>
376 <property name="tooltip" translatable="yes">Save a config file</property>
377 <property name="label" translatable="yes">Save</property>
378 <property name="use_underline">True</property>
379 <property name="stock_id">gtk-save</property>
380 <property name="visible_horizontal">True</property>
381 <property name="visible_vertical">True</property>
382 <property name="is_important">False</property>
383 <signal name="clicked" handler="on_save_clicked"/>
384 </widget>
385 <packing>
386 <property name="expand">False</property>
387 <property name="homogeneous">True</property>
388 </packing>
389 </child>
390
391 <child>
392 <widget class="GtkToolItem" id="toolitem2">
393 <property name="visible">True</property>
394 <property name="visible_horizontal">True</property>
395 <property name="visible_vertical">True</property>
396 <property name="is_important">False</property>
397
398 <child>
399 <widget class="GtkVSeparator" id="vseparator2">
400 <property name="visible">True</property>
401 </widget>
402 </child>
403 </widget>
404 <packing>
405 <property name="expand">False</property>
406 <property name="homogeneous">False</property>
407 </packing>
408 </child>
409
410 <child>
411 <widget class="GtkToolButton" id="button4">
412 <property name="visible">True</property>
413 <property name="tooltip" translatable="yes">Single view</property>
414 <property name="label" translatable="yes">Single</property>
415 <property name="use_underline">True</property>
416 <property name="stock_id">gtk-missing-image</property>
417 <property name="visible_horizontal">True</property>
418 <property name="visible_vertical">True</property>
419 <property name="is_important">False</property>
420 <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
421 </widget>
422 <packing>
423 <property name="expand">False</property>
424 <property name="homogeneous">True</property>
425 </packing>
426 </child>
427
428 <child>
429 <widget class="GtkToolButton" id="button5">
430 <property name="visible">True</property>
431 <property name="tooltip" translatable="yes">Split view</property>
432 <property name="label" translatable="yes">Split</property>
433 <property name="use_underline">True</property>
434 <property name="stock_id">gtk-missing-image</property>
435 <property name="visible_horizontal">True</property>
436 <property name="visible_vertical">True</property>
437 <property name="is_important">False</property>
438 <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
439 </widget>
440 <packing>
441 <property name="expand">False</property>
442 <property name="homogeneous">True</property>
443 </packing>
444 </child>
445
446 <child>
447 <widget class="GtkToolButton" id="button6">
448 <property name="visible">True</property>
449 <property name="tooltip" translatable="yes">Full view</property>
450 <property name="label" translatable="yes">Full</property>
451 <property name="use_underline">True</property>
452 <property name="stock_id">gtk-missing-image</property>
453 <property name="visible_horizontal">True</property>
454 <property name="visible_vertical">True</property>
455 <property name="is_important">False</property>
456 <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
457 </widget>
458 <packing>
459 <property name="expand">False</property>
460 <property name="homogeneous">True</property>
461 </packing>
462 </child>
463
464 <child>
465 <widget class="GtkToolItem" id="toolitem3">
466 <property name="visible">True</property>
467 <property name="visible_horizontal">True</property>
468 <property name="visible_vertical">True</property>
469 <property name="is_important">False</property>
470
471 <child>
472 <widget class="GtkVSeparator" id="vseparator3">
473 <property name="visible">True</property>
474 </widget>
475 </child>
476 </widget>
477 <packing>
478 <property name="expand">False</property>
479 <property name="homogeneous">False</property>
480 </packing>
481 </child>
482
483 <child>
484 <widget class="GtkToolButton" id="button7">
485 <property name="visible">True</property>
486 <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
487 <property name="label" translatable="yes">Collapse</property>
488 <property name="use_underline">True</property>
489 <property name="stock_id">gtk-remove</property>
490 <property name="visible_horizontal">True</property>
491 <property name="visible_vertical">True</property>
492 <property name="is_important">False</property>
493 <signal name="clicked" handler="on_collapse_clicked"/>
494 </widget>
495 <packing>
496 <property name="expand">False</property>
497 <property name="homogeneous">True</property>
498 </packing>
499 </child>
500
501 <child>
502 <widget class="GtkToolButton" id="button8">
503 <property name="visible">True</property>
504 <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
505 <property name="label" translatable="yes">Expand</property>
506 <property name="use_underline">True</property>
507 <property name="stock_id">gtk-add</property>
508 <property name="visible_horizontal">True</property>
509 <property name="visible_vertical">True</property>
510 <property name="is_important">False</property>
511 <signal name="clicked" handler="on_expand_clicked"/>
512 </widget>
513 <packing>
514 <property name="expand">False</property>
515 <property name="homogeneous">True</property>
516 </packing>
517 </child>
518 </widget>
519 </child>
520 </widget>
521 <packing>
522 <property name="padding">0</property>
523 <property name="expand">False</property>
524 <property name="fill">False</property>
525 </packing>
526 </child>
527
528 <child>
529 <widget class="GtkHPaned" id="hpaned1">
530 <property name="width_request">1</property>
531 <property name="visible">True</property>
532 <property name="can_focus">True</property>
533 <property name="position">0</property>
534
535 <child>
536 <widget class="GtkScrolledWindow" id="scrolledwindow1">
537 <property name="visible">True</property>
538 <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
539 <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
540 <property name="shadow_type">GTK_SHADOW_IN</property>
541 <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
542
543 <child>
544 <widget class="GtkTreeView" id="treeview1">
545 <property name="visible">True</property>
546 <property name="can_focus">True</property>
547 <property name="headers_visible">True</property>
548 <property name="rules_hint">False</property>
549 <property name="reorderable">False</property>
550 <property name="enable_search">True</property>
551 <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/>
552 <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/>
553 <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/>
554 </widget>
555 </child>
556 </widget>
557 <packing>
558 <property name="shrink">True</property>
559 <property name="resize">False</property>
560 </packing>
561 </child>
562
563 <child>
564 <widget class="GtkVPaned" id="vpaned1">
565 <property name="visible">True</property>
566 <property name="can_focus">True</property>
567 <property name="position">0</property>
568
569 <child>
570 <widget class="GtkScrolledWindow" id="scrolledwindow2">
571 <property name="visible">True</property>
572 <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
573 <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
574 <property name="shadow_type">GTK_SHADOW_IN</property>
575 <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
576
577 <child>
578 <widget class="GtkTreeView" id="treeview2">
579 <property name="visible">True</property>
580 <property name="can_focus">True</property>
581 <property name="has_focus">True</property>
582 <property name="headers_visible">True</property>
583 <property name="rules_hint">False</property>
584 <property name="reorderable">False</property>
585 <property name="enable_search">True</property>
586 <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/>
587 <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/>
588 <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/>
589 </widget>
590 </child>
591 </widget>
592 <packing>
593 <property name="shrink">True</property>
594 <property name="resize">False</property>
595 </packing>
596 </child>
597
598 <child>
599 <widget class="GtkScrolledWindow" id="scrolledwindow3">
600 <property name="visible">True</property>
601 <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
602 <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
603 <property name="shadow_type">GTK_SHADOW_IN</property>
604 <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
605
606 <child>
607 <widget class="GtkTextView" id="textview3">
608 <property name="visible">True</property>
609 <property name="can_focus">True</property>
610 <property name="editable">False</property>
611 <property name="overwrite">False</property>
612 <property name="accepts_tab">True</property>
613 <property name="justification">GTK_JUSTIFY_LEFT</property>
614 <property name="wrap_mode">GTK_WRAP_WORD</property>
615 <property name="cursor_visible">True</property>
616 <property name="pixels_above_lines">0</property>
617 <property name="pixels_below_lines">0</property>
618 <property name="pixels_inside_wrap">0</property>
619 <property name="left_margin">0</property>
620 <property name="right_margin">0</property>
621 <property name="indent">0</property>
622 <property name="text" translatable="yes">Sorry, no help available for this option yet.</property>
623 </widget>
624 </child>
625 </widget>
626 <packing>
627 <property name="shrink">True</property>
628 <property name="resize">True</property>
629 </packing>
630 </child>
631 </widget>
632 <packing>
633 <property name="shrink">True</property>
634 <property name="resize">True</property>
635 </packing>
636 </child>
637 </widget>
638 <packing>
639 <property name="padding">0</property>
640 <property name="expand">True</property>
641 <property name="fill">True</property>
642 </packing>
643 </child>
644 </widget>
645 </child>
646</widget>
647
648</glade-interface>
diff --git a/scripts/kconfig/images.c b/scripts/kconfig/images.c
new file mode 100644
index 000000000..d4f84bd4a
--- /dev/null
+++ b/scripts/kconfig/images.c
@@ -0,0 +1,326 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6static const char *xpm_load[] = {
7"22 22 5 1",
8". c None",
9"# c #000000",
10"c c #838100",
11"a c #ffff00",
12"b c #ffffff",
13"......................",
14"......................",
15"......................",
16"............####....#.",
17"...........#....##.##.",
18"..................###.",
19".................####.",
20".####...........#####.",
21"#abab##########.......",
22"#babababababab#.......",
23"#ababababababa#.......",
24"#babababababab#.......",
25"#ababab###############",
26"#babab##cccccccccccc##",
27"#abab##cccccccccccc##.",
28"#bab##cccccccccccc##..",
29"#ab##cccccccccccc##...",
30"#b##cccccccccccc##....",
31"###cccccccccccc##.....",
32"##cccccccccccc##......",
33"###############.......",
34"......................"};
35
36static const char *xpm_save[] = {
37"22 22 5 1",
38". c None",
39"# c #000000",
40"a c #838100",
41"b c #c5c2c5",
42"c c #cdb6d5",
43"......................",
44".####################.",
45".#aa#bbbbbbbbbbbb#bb#.",
46".#aa#bbbbbbbbbbbb#bb#.",
47".#aa#bbbbbbbbbcbb####.",
48".#aa#bbbccbbbbbbb#aa#.",
49".#aa#bbbccbbbbbbb#aa#.",
50".#aa#bbbbbbbbbbbb#aa#.",
51".#aa#bbbbbbbbbbbb#aa#.",
52".#aa#bbbbbbbbbbbb#aa#.",
53".#aa#bbbbbbbbbbbb#aa#.",
54".#aaa############aaa#.",
55".#aaaaaaaaaaaaaaaaaa#.",
56".#aaaaaaaaaaaaaaaaaa#.",
57".#aaa#############aa#.",
58".#aaa#########bbb#aa#.",
59".#aaa#########bbb#aa#.",
60".#aaa#########bbb#aa#.",
61".#aaa#########bbb#aa#.",
62".#aaa#########bbb#aa#.",
63"..##################..",
64"......................"};
65
66static const char *xpm_back[] = {
67"22 22 3 1",
68". c None",
69"# c #000083",
70"a c #838183",
71"......................",
72"......................",
73"......................",
74"......................",
75"......................",
76"...........######a....",
77"..#......##########...",
78"..##...####......##a..",
79"..###.###.........##..",
80"..######..........##..",
81"..#####...........##..",
82"..######..........##..",
83"..#######.........##..",
84"..########.......##a..",
85"...............a###...",
86"...............###....",
87"......................",
88"......................",
89"......................",
90"......................",
91"......................",
92"......................"};
93
94static const char *xpm_tree_view[] = {
95"22 22 2 1",
96". c None",
97"# c #000000",
98"......................",
99"......................",
100"......#...............",
101"......#...............",
102"......#...............",
103"......#...............",
104"......#...............",
105"......########........",
106"......#...............",
107"......#...............",
108"......#...............",
109"......#...............",
110"......#...............",
111"......########........",
112"......#...............",
113"......#...............",
114"......#...............",
115"......#...............",
116"......#...............",
117"......########........",
118"......................",
119"......................"};
120
121static const char *xpm_single_view[] = {
122"22 22 2 1",
123". c None",
124"# c #000000",
125"......................",
126"......................",
127"..........#...........",
128"..........#...........",
129"..........#...........",
130"..........#...........",
131"..........#...........",
132"..........#...........",
133"..........#...........",
134"..........#...........",
135"..........#...........",
136"..........#...........",
137"..........#...........",
138"..........#...........",
139"..........#...........",
140"..........#...........",
141"..........#...........",
142"..........#...........",
143"..........#...........",
144"..........#...........",
145"......................",
146"......................"};
147
148static const char *xpm_split_view[] = {
149"22 22 2 1",
150". c None",
151"# c #000000",
152"......................",
153"......................",
154"......#......#........",
155"......#......#........",
156"......#......#........",
157"......#......#........",
158"......#......#........",
159"......#......#........",
160"......#......#........",
161"......#......#........",
162"......#......#........",
163"......#......#........",
164"......#......#........",
165"......#......#........",
166"......#......#........",
167"......#......#........",
168"......#......#........",
169"......#......#........",
170"......#......#........",
171"......#......#........",
172"......................",
173"......................"};
174
175static const char *xpm_symbol_no[] = {
176"12 12 2 1",
177" c white",
178". c black",
179" ",
180" .......... ",
181" . . ",
182" . . ",
183" . . ",
184" . . ",
185" . . ",
186" . . ",
187" . . ",
188" . . ",
189" .......... ",
190" "};
191
192static const char *xpm_symbol_mod[] = {
193"12 12 2 1",
194" c white",
195". c black",
196" ",
197" .......... ",
198" . . ",
199" . . ",
200" . .. . ",
201" . .... . ",
202" . .... . ",
203" . .. . ",
204" . . ",
205" . . ",
206" .......... ",
207" "};
208
209static const char *xpm_symbol_yes[] = {
210"12 12 2 1",
211" c white",
212". c black",
213" ",
214" .......... ",
215" . . ",
216" . . ",
217" . . . ",
218" . .. . ",
219" . . .. . ",
220" . .... . ",
221" . .. . ",
222" . . ",
223" .......... ",
224" "};
225
226static const char *xpm_choice_no[] = {
227"12 12 2 1",
228" c white",
229". c black",
230" ",
231" .... ",
232" .. .. ",
233" . . ",
234" . . ",
235" . . ",
236" . . ",
237" . . ",
238" . . ",
239" .. .. ",
240" .... ",
241" "};
242
243static const char *xpm_choice_yes[] = {
244"12 12 2 1",
245" c white",
246". c black",
247" ",
248" .... ",
249" .. .. ",
250" . . ",
251" . .. . ",
252" . .... . ",
253" . .... . ",
254" . .. . ",
255" . . ",
256" .. .. ",
257" .... ",
258" "};
259
260static const char *xpm_menu[] = {
261"12 12 2 1",
262" c white",
263". c black",
264" ",
265" .......... ",
266" . . ",
267" . .. . ",
268" . .... . ",
269" . ...... . ",
270" . ...... . ",
271" . .... . ",
272" . .. . ",
273" . . ",
274" .......... ",
275" "};
276
277static const char *xpm_menu_inv[] = {
278"12 12 2 1",
279" c white",
280". c black",
281" ",
282" .......... ",
283" .......... ",
284" .. ...... ",
285" .. .... ",
286" .. .. ",
287" .. .. ",
288" .. .... ",
289" .. ...... ",
290" .......... ",
291" .......... ",
292" "};
293
294static const char *xpm_menuback[] = {
295"12 12 2 1",
296" c white",
297". c black",
298" ",
299" .......... ",
300" . . ",
301" . .. . ",
302" . .... . ",
303" . ...... . ",
304" . ...... . ",
305" . .... . ",
306" . .. . ",
307" . . ",
308" .......... ",
309" "};
310
311static const char *xpm_void[] = {
312"12 12 2 1",
313" c white",
314". c black",
315" ",
316" ",
317" ",
318" ",
319" ",
320" ",
321" ",
322" ",
323" ",
324" ",
325" ",
326" "};
diff --git a/scripts/kconfig/kconfig_load.c b/scripts/kconfig/kconfig_load.c
new file mode 100644
index 000000000..dbdcaad82
--- /dev/null
+++ b/scripts/kconfig/kconfig_load.c
@@ -0,0 +1,35 @@
1#include <dlfcn.h>
2#include <stdio.h>
3#include <stdlib.h>
4
5#include "lkc.h"
6
7#define P(name,type,arg) type (*name ## _p) arg
8#include "lkc_proto.h"
9#undef P
10
11void kconfig_load(void)
12{
13 void *handle;
14 char *error;
15
16 handle = dlopen("./libkconfig.so", RTLD_LAZY);
17 if (!handle) {
18 handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY);
19 if (!handle) {
20 fprintf(stderr, "%s\n", dlerror());
21 exit(1);
22 }
23 }
24
25#define P(name,type,arg) \
26{ \
27 name ## _p = dlsym(handle, #name); \
28 if ((error = dlerror())) { \
29 fprintf(stderr, "%s\n", error); \
30 exit(1); \
31 } \
32}
33#include "lkc_proto.h"
34#undef P
35}
diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c
new file mode 100644
index 000000000..abee55ca6
--- /dev/null
+++ b/scripts/kconfig/kxgettext.c
@@ -0,0 +1,227 @@
1/*
2 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
3 *
4 * Released under the terms of the GNU GPL v2.0
5 */
6
7#include <stdlib.h>
8#include <string.h>
9
10#define LKC_DIRECT_LINK
11#include "lkc.h"
12
13static char *escape(const char* text, char *bf, int len)
14{
15 char *bfp = bf;
16 int multiline = strchr(text, '\n') != NULL;
17 int eol = 0;
18 int textlen = strlen(text);
19
20 if ((textlen > 0) && (text[textlen-1] == '\n'))
21 eol = 1;
22
23 *bfp++ = '"';
24 --len;
25
26 if (multiline) {
27 *bfp++ = '"';
28 *bfp++ = '\n';
29 *bfp++ = '"';
30 len -= 3;
31 }
32
33 while (*text != '\0' && len > 1) {
34 if (*text == '"')
35 *bfp++ = '\\';
36 else if (*text == '\n') {
37 *bfp++ = '\\';
38 *bfp++ = 'n';
39 *bfp++ = '"';
40 *bfp++ = '\n';
41 *bfp++ = '"';
42 len -= 5;
43 ++text;
44 goto next;
45 }
46 *bfp++ = *text++;
47next:
48 --len;
49 }
50
51 if (multiline && eol)
52 bfp -= 3;
53
54 *bfp++ = '"';
55 *bfp = '\0';
56
57 return bf;
58}
59
60struct file_line {
61 struct file_line *next;
62 char* file;
63 int lineno;
64};
65
66static struct file_line *file_line__new(char *file, int lineno)
67{
68 struct file_line *self = malloc(sizeof(*self));
69
70 if (self == NULL)
71 goto out;
72
73 self->file = file;
74 self->lineno = lineno;
75 self->next = NULL;
76out:
77 return self;
78}
79
80struct message {
81 const char *msg;
82 const char *option;
83 struct message *next;
84 struct file_line *files;
85};
86
87static struct message *message__list;
88
89static struct message *message__new(const char *msg, char *option, char *file, int lineno)
90{
91 struct message *self = malloc(sizeof(*self));
92
93 if (self == NULL)
94 goto out;
95
96 self->files = file_line__new(file, lineno);
97 if (self->files == NULL)
98 goto out_fail;
99
100 self->msg = strdup(msg);
101 if (self->msg == NULL)
102 goto out_fail_msg;
103
104 self->option = option;
105 self->next = NULL;
106out:
107 return self;
108out_fail_msg:
109 free(self->files);
110out_fail:
111 free(self);
112 self = NULL;
113 goto out;
114}
115
116static struct message *mesage__find(const char *msg)
117{
118 struct message *m = message__list;
119
120 while (m != NULL) {
121 if (strcmp(m->msg, msg) == 0)
122 break;
123 m = m->next;
124 }
125
126 return m;
127}
128
129static int message__add_file_line(struct message *self, char *file, int lineno)
130{
131 int rc = -1;
132 struct file_line *fl = file_line__new(file, lineno);
133
134 if (fl == NULL)
135 goto out;
136
137 fl->next = self->files;
138 self->files = fl;
139 rc = 0;
140out:
141 return rc;
142}
143
144static int message__add(const char *msg, char *option, char *file, int lineno)
145{
146 int rc = 0;
147 char bf[16384];
148 char *escaped = escape(msg, bf, sizeof(bf));
149 struct message *m = mesage__find(escaped);
150
151 if (m != NULL)
152 rc = message__add_file_line(m, file, lineno);
153 else {
154 m = message__new(escaped, option, file, lineno);
155
156 if (m != NULL) {
157 m->next = message__list;
158 message__list = m;
159 } else
160 rc = -1;
161 }
162 return rc;
163}
164
165void menu_build_message_list(struct menu *menu)
166{
167 struct menu *child;
168
169 message__add(menu_get_prompt(menu), NULL,
170 menu->file == NULL ? "Root Menu" : menu->file->name,
171 menu->lineno);
172
173 if (menu->sym != NULL && menu->sym->help != NULL)
174 message__add(menu->sym->help, menu->sym->name,
175 menu->file == NULL ? "Root Menu" : menu->file->name,
176 menu->lineno);
177
178 for (child = menu->list; child != NULL; child = child->next)
179 if (child->prompt != NULL)
180 menu_build_message_list(child);
181}
182
183static void message__print_file_lineno(struct message *self)
184{
185 struct file_line *fl = self->files;
186
187 putchar('\n');
188 if (self->option != NULL)
189 printf("# %s:00000\n", self->option);
190
191 printf("#: %s:%d", fl->file, fl->lineno);
192 fl = fl->next;
193
194 while (fl != NULL) {
195 printf(", %s:%d", fl->file, fl->lineno);
196 fl = fl->next;
197 }
198
199 putchar('\n');
200}
201
202static void message__print_gettext_msgid_msgstr(struct message *self)
203{
204 message__print_file_lineno(self);
205
206 printf("msgid %s\n"
207 "msgstr \"\"\n", self->msg);
208}
209
210void menu__xgettext(void)
211{
212 struct message *m = message__list;
213
214 while (m != NULL) {
215 message__print_gettext_msgid_msgstr(m);
216 m = m->next;
217 }
218}
219
220int main(int ac, char **av)
221{
222 conf_parse(av[1]);
223
224 menu_build_message_list(menu_get_root_menu(NULL));
225 menu__xgettext();
226 return 0;
227}
diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped
new file mode 100644
index 000000000..24e3c8cbb
--- /dev/null
+++ b/scripts/kconfig/lex.zconf.c_shipped
@@ -0,0 +1,2317 @@
1
2#line 3 "scripts/kconfig/lex.zconf.c"
3
4#define YY_INT_ALIGNED short int
5
6/* A lexical scanner generated by flex */
7
8#define FLEX_SCANNER
9#define YY_FLEX_MAJOR_VERSION 2
10#define YY_FLEX_MINOR_VERSION 5
11#define YY_FLEX_SUBMINOR_VERSION 31
12#if YY_FLEX_SUBMINOR_VERSION > 0
13#define FLEX_BETA
14#endif
15
16/* First, we deal with platform-specific or compiler-specific issues. */
17
18/* begin standard C headers. */
19#include <stdio.h>
20#include <string.h>
21#include <errno.h>
22#include <stdlib.h>
23
24/* end standard C headers. */
25
26/* flex integer type definitions */
27
28#ifndef FLEXINT_H
29#define FLEXINT_H
30
31/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
32
33#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
34#include <inttypes.h>
35typedef int8_t flex_int8_t;
36typedef uint8_t flex_uint8_t;
37typedef int16_t flex_int16_t;
38typedef uint16_t flex_uint16_t;
39typedef int32_t flex_int32_t;
40typedef uint32_t flex_uint32_t;
41#else
42typedef signed char flex_int8_t;
43typedef short int flex_int16_t;
44typedef int flex_int32_t;
45typedef unsigned char flex_uint8_t;
46typedef unsigned short int flex_uint16_t;
47typedef unsigned int flex_uint32_t;
48#endif /* ! C99 */
49
50/* Limits of integral types. */
51#ifndef INT8_MIN
52#define INT8_MIN (-128)
53#endif
54#ifndef INT16_MIN
55#define INT16_MIN (-32767-1)
56#endif
57#ifndef INT32_MIN
58#define INT32_MIN (-2147483647-1)
59#endif
60#ifndef INT8_MAX
61#define INT8_MAX (127)
62#endif
63#ifndef INT16_MAX
64#define INT16_MAX (32767)
65#endif
66#ifndef INT32_MAX
67#define INT32_MAX (2147483647)
68#endif
69#ifndef UINT8_MAX
70#define UINT8_MAX (255U)
71#endif
72#ifndef UINT16_MAX
73#define UINT16_MAX (65535U)
74#endif
75#ifndef UINT32_MAX
76#define UINT32_MAX (4294967295U)
77#endif
78
79#endif /* ! FLEXINT_H */
80
81#ifdef __cplusplus
82
83/* The "const" storage-class-modifier is valid. */
84#define YY_USE_CONST
85
86#else /* ! __cplusplus */
87
88#if __STDC__
89
90#define YY_USE_CONST
91
92#endif /* __STDC__ */
93#endif /* ! __cplusplus */
94
95#ifdef YY_USE_CONST
96#define yyconst const
97#else
98#define yyconst
99#endif
100
101/* Returned upon end-of-file. */
102#define YY_NULL 0
103
104/* Promotes a possibly negative, possibly signed char to an unsigned
105 * integer for use as an array index. If the signed char is negative,
106 * we want to instead treat it as an 8-bit unsigned char, hence the
107 * double cast.
108 */
109#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
110
111/* Enter a start condition. This macro really ought to take a parameter,
112 * but we do it the disgusting crufty way forced on us by the ()-less
113 * definition of BEGIN.
114 */
115#define BEGIN (yy_start) = 1 + 2 *
116
117/* Translate the current start state into a value that can be later handed
118 * to BEGIN to return to the state. The YYSTATE alias is for lex
119 * compatibility.
120 */
121#define YY_START (((yy_start) - 1) / 2)
122#define YYSTATE YY_START
123
124/* Action number for EOF rule of a given start state. */
125#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
126
127/* Special action meaning "start processing a new file". */
128#define YY_NEW_FILE zconfrestart(zconfin )
129
130#define YY_END_OF_BUFFER_CHAR 0
131
132/* Size of default input buffer. */
133#ifndef YY_BUF_SIZE
134#define YY_BUF_SIZE 16384
135#endif
136
137#ifndef YY_TYPEDEF_YY_BUFFER_STATE
138#define YY_TYPEDEF_YY_BUFFER_STATE
139typedef struct yy_buffer_state *YY_BUFFER_STATE;
140#endif
141
142extern int zconfleng;
143
144extern FILE *zconfin, *zconfout;
145
146#define EOB_ACT_CONTINUE_SCAN 0
147#define EOB_ACT_END_OF_FILE 1
148#define EOB_ACT_LAST_MATCH 2
149
150 #define YY_LESS_LINENO(n)
151
152/* Return all but the first "n" matched characters back to the input stream. */
153#define yyless(n) \
154 do \
155 { \
156 /* Undo effects of setting up zconftext. */ \
157 int yyless_macro_arg = (n); \
158 YY_LESS_LINENO(yyless_macro_arg);\
159 *yy_cp = (yy_hold_char); \
160 YY_RESTORE_YY_MORE_OFFSET \
161 (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
162 YY_DO_BEFORE_ACTION; /* set up zconftext again */ \
163 } \
164 while ( 0 )
165
166#define unput(c) yyunput( c, (yytext_ptr) )
167
168/* The following is because we cannot portably get our hands on size_t
169 * (without autoconf's help, which isn't available because we want
170 * flex-generated scanners to compile on their own).
171 */
172
173#ifndef YY_TYPEDEF_YY_SIZE_T
174#define YY_TYPEDEF_YY_SIZE_T
175typedef unsigned int yy_size_t;
176#endif
177
178#ifndef YY_STRUCT_YY_BUFFER_STATE
179#define YY_STRUCT_YY_BUFFER_STATE
180struct yy_buffer_state
181 {
182 FILE *yy_input_file;
183
184 char *yy_ch_buf; /* input buffer */
185 char *yy_buf_pos; /* current position in input buffer */
186
187 /* Size of input buffer in bytes, not including room for EOB
188 * characters.
189 */
190 yy_size_t yy_buf_size;
191
192 /* Number of characters read into yy_ch_buf, not including EOB
193 * characters.
194 */
195 int yy_n_chars;
196
197 /* Whether we "own" the buffer - i.e., we know we created it,
198 * and can realloc() it to grow it, and should free() it to
199 * delete it.
200 */
201 int yy_is_our_buffer;
202
203 /* Whether this is an "interactive" input source; if so, and
204 * if we're using stdio for input, then we want to use getc()
205 * instead of fread(), to make sure we stop fetching input after
206 * each newline.
207 */
208 int yy_is_interactive;
209
210 /* Whether we're considered to be at the beginning of a line.
211 * If so, '^' rules will be active on the next match, otherwise
212 * not.
213 */
214 int yy_at_bol;
215
216 int yy_bs_lineno; /**< The line count. */
217 int yy_bs_column; /**< The column count. */
218
219 /* Whether to try to fill the input buffer when we reach the
220 * end of it.
221 */
222 int yy_fill_buffer;
223
224 int yy_buffer_status;
225
226#define YY_BUFFER_NEW 0
227#define YY_BUFFER_NORMAL 1
228 /* When an EOF's been seen but there's still some text to process
229 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
230 * shouldn't try reading from the input source any more. We might
231 * still have a bunch of tokens to match, though, because of
232 * possible backing-up.
233 *
234 * When we actually see the EOF, we change the status to "new"
235 * (via zconfrestart()), so that the user can continue scanning by
236 * just pointing zconfin at a new input file.
237 */
238#define YY_BUFFER_EOF_PENDING 2
239
240 };
241#endif /* !YY_STRUCT_YY_BUFFER_STATE */
242
243/* Stack of input buffers. */
244static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
245static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
246static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
247
248/* We provide macros for accessing buffer states in case in the
249 * future we want to put the buffer states in a more general
250 * "scanner state".
251 *
252 * Returns the top of the stack, or NULL.
253 */
254#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
255 ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
256 : NULL)
257
258/* Same as previous macro, but useful when we know that the buffer stack is not
259 * NULL or when we need an lvalue. For internal use only.
260 */
261#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
262
263/* yy_hold_char holds the character lost when zconftext is formed. */
264static char yy_hold_char;
265static int yy_n_chars; /* number of characters read into yy_ch_buf */
266int zconfleng;
267
268/* Points to current character in buffer. */
269static char *yy_c_buf_p = (char *) 0;
270static int yy_init = 1; /* whether we need to initialize */
271static int yy_start = 0; /* start state number */
272
273/* Flag which is used to allow zconfwrap()'s to do buffer switches
274 * instead of setting up a fresh zconfin. A bit of a hack ...
275 */
276static int yy_did_buffer_switch_on_eof;
277
278void zconfrestart (FILE *input_file );
279void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer );
280YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size );
281void zconf_delete_buffer (YY_BUFFER_STATE b );
282void zconf_flush_buffer (YY_BUFFER_STATE b );
283void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer );
284void zconfpop_buffer_state (void );
285
286static void zconfensure_buffer_stack (void );
287static void zconf_load_buffer_state (void );
288static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file );
289
290#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER )
291
292YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size );
293YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str );
294YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len );
295
296void *zconfalloc (yy_size_t );
297void *zconfrealloc (void *,yy_size_t );
298void zconffree (void * );
299
300#define yy_new_buffer zconf_create_buffer
301
302#define yy_set_interactive(is_interactive) \
303 { \
304 if ( ! YY_CURRENT_BUFFER ){ \
305 zconfensure_buffer_stack (); \
306 YY_CURRENT_BUFFER_LVALUE = \
307 zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
308 } \
309 YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
310 }
311
312#define yy_set_bol(at_bol) \
313 { \
314 if ( ! YY_CURRENT_BUFFER ){\
315 zconfensure_buffer_stack (); \
316 YY_CURRENT_BUFFER_LVALUE = \
317 zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
318 } \
319 YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
320 }
321
322#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
323
324/* Begin user sect3 */
325
326#define zconfwrap() 1
327#define YY_SKIP_YYWRAP
328
329typedef unsigned char YY_CHAR;
330
331FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0;
332
333typedef int yy_state_type;
334
335extern int zconflineno;
336
337int zconflineno = 1;
338
339extern char *zconftext;
340#define yytext_ptr zconftext
341static yyconst flex_int16_t yy_nxt[][17] =
342 {
343 {
344 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
345 0, 0, 0, 0, 0, 0, 0
346 },
347
348 {
349 11, 12, 13, 14, 12, 12, 15, 12, 12, 12,
350 12, 12, 12, 12, 12, 12, 12
351 },
352
353 {
354 11, 12, 13, 14, 12, 12, 15, 12, 12, 12,
355 12, 12, 12, 12, 12, 12, 12
356 },
357
358 {
359 11, 16, 16, 17, 16, 16, 16, 16, 16, 16,
360 16, 16, 16, 18, 16, 16, 16
361 },
362
363 {
364 11, 16, 16, 17, 16, 16, 16, 16, 16, 16,
365 16, 16, 16, 18, 16, 16, 16
366
367 },
368
369 {
370 11, 19, 20, 21, 19, 19, 19, 19, 19, 19,
371 19, 19, 19, 19, 19, 19, 19
372 },
373
374 {
375 11, 19, 20, 21, 19, 19, 19, 19, 19, 19,
376 19, 19, 19, 19, 19, 19, 19
377 },
378
379 {
380 11, 22, 22, 23, 22, 24, 22, 22, 24, 22,
381 22, 22, 22, 22, 22, 25, 22
382 },
383
384 {
385 11, 22, 22, 23, 22, 24, 22, 22, 24, 22,
386 22, 22, 22, 22, 22, 25, 22
387 },
388
389 {
390 11, 26, 26, 27, 28, 29, 30, 31, 29, 32,
391 33, 34, 35, 35, 36, 37, 38
392
393 },
394
395 {
396 11, 26, 26, 27, 28, 29, 30, 31, 29, 32,
397 33, 34, 35, 35, 36, 37, 38
398 },
399
400 {
401 -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
402 -11, -11, -11, -11, -11, -11, -11
403 },
404
405 {
406 11, -12, -12, -12, -12, -12, -12, -12, -12, -12,
407 -12, -12, -12, -12, -12, -12, -12
408 },
409
410 {
411 11, -13, 39, 40, -13, -13, 41, -13, -13, -13,
412 -13, -13, -13, -13, -13, -13, -13
413 },
414
415 {
416 11, -14, -14, -14, -14, -14, -14, -14, -14, -14,
417 -14, -14, -14, -14, -14, -14, -14
418
419 },
420
421 {
422 11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
423 42, 42, 42, 42, 42, 42, 42
424 },
425
426 {
427 11, -16, -16, -16, -16, -16, -16, -16, -16, -16,
428 -16, -16, -16, -16, -16, -16, -16
429 },
430
431 {
432 11, -17, -17, -17, -17, -17, -17, -17, -17, -17,
433 -17, -17, -17, -17, -17, -17, -17
434 },
435
436 {
437 11, -18, -18, -18, -18, -18, -18, -18, -18, -18,
438 -18, -18, -18, 44, -18, -18, -18
439 },
440
441 {
442 11, 45, 45, -19, 45, 45, 45, 45, 45, 45,
443 45, 45, 45, 45, 45, 45, 45
444
445 },
446
447 {
448 11, -20, 46, 47, -20, -20, -20, -20, -20, -20,
449 -20, -20, -20, -20, -20, -20, -20
450 },
451
452 {
453 11, 48, -21, -21, 48, 48, 48, 48, 48, 48,
454 48, 48, 48, 48, 48, 48, 48
455 },
456
457 {
458 11, 49, 49, 50, 49, -22, 49, 49, -22, 49,
459 49, 49, 49, 49, 49, -22, 49
460 },
461
462 {
463 11, -23, -23, -23, -23, -23, -23, -23, -23, -23,
464 -23, -23, -23, -23, -23, -23, -23
465 },
466
467 {
468 11, -24, -24, -24, -24, -24, -24, -24, -24, -24,
469 -24, -24, -24, -24, -24, -24, -24
470
471 },
472
473 {
474 11, 51, 51, 52, 51, 51, 51, 51, 51, 51,
475 51, 51, 51, 51, 51, 51, 51
476 },
477
478 {
479 11, -26, -26, -26, -26, -26, -26, -26, -26, -26,
480 -26, -26, -26, -26, -26, -26, -26
481 },
482
483 {
484 11, -27, -27, -27, -27, -27, -27, -27, -27, -27,
485 -27, -27, -27, -27, -27, -27, -27
486 },
487
488 {
489 11, -28, -28, -28, -28, -28, -28, -28, -28, -28,
490 -28, -28, -28, -28, 53, -28, -28
491 },
492
493 {
494 11, -29, -29, -29, -29, -29, -29, -29, -29, -29,
495 -29, -29, -29, -29, -29, -29, -29
496
497 },
498
499 {
500 11, 54, 54, -30, 54, 54, 54, 54, 54, 54,
501 54, 54, 54, 54, 54, 54, 54
502 },
503
504 {
505 11, -31, -31, -31, -31, -31, -31, 55, -31, -31,
506 -31, -31, -31, -31, -31, -31, -31
507 },
508
509 {
510 11, -32, -32, -32, -32, -32, -32, -32, -32, -32,
511 -32, -32, -32, -32, -32, -32, -32
512 },
513
514 {
515 11, -33, -33, -33, -33, -33, -33, -33, -33, -33,
516 -33, -33, -33, -33, -33, -33, -33
517 },
518
519 {
520 11, -34, -34, -34, -34, -34, -34, -34, -34, -34,
521 -34, 56, 57, 57, -34, -34, -34
522
523 },
524
525 {
526 11, -35, -35, -35, -35, -35, -35, -35, -35, -35,
527 -35, 57, 57, 57, -35, -35, -35
528 },
529
530 {
531 11, -36, -36, -36, -36, -36, -36, -36, -36, -36,
532 -36, -36, -36, -36, -36, -36, -36
533 },
534
535 {
536 11, -37, -37, 58, -37, -37, -37, -37, -37, -37,
537 -37, -37, -37, -37, -37, -37, -37
538 },
539
540 {
541 11, -38, -38, -38, -38, -38, -38, -38, -38, -38,
542 -38, -38, -38, -38, -38, -38, 59
543 },
544
545 {
546 11, -39, 39, 40, -39, -39, 41, -39, -39, -39,
547 -39, -39, -39, -39, -39, -39, -39
548
549 },
550
551 {
552 11, -40, -40, -40, -40, -40, -40, -40, -40, -40,
553 -40, -40, -40, -40, -40, -40, -40
554 },
555
556 {
557 11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
558 42, 42, 42, 42, 42, 42, 42
559 },
560
561 {
562 11, 42, 42, 43, 42, 42, 42, 42, 42, 42,
563 42, 42, 42, 42, 42, 42, 42
564 },
565
566 {
567 11, -43, -43, -43, -43, -43, -43, -43, -43, -43,
568 -43, -43, -43, -43, -43, -43, -43
569 },
570
571 {
572 11, -44, -44, -44, -44, -44, -44, -44, -44, -44,
573 -44, -44, -44, 44, -44, -44, -44
574
575 },
576
577 {
578 11, 45, 45, -45, 45, 45, 45, 45, 45, 45,
579 45, 45, 45, 45, 45, 45, 45
580 },
581
582 {
583 11, -46, 46, 47, -46, -46, -46, -46, -46, -46,
584 -46, -46, -46, -46, -46, -46, -46
585 },
586
587 {
588 11, 48, -47, -47, 48, 48, 48, 48, 48, 48,
589 48, 48, 48, 48, 48, 48, 48
590 },
591
592 {
593 11, -48, -48, -48, -48, -48, -48, -48, -48, -48,
594 -48, -48, -48, -48, -48, -48, -48
595 },
596
597 {
598 11, 49, 49, 50, 49, -49, 49, 49, -49, 49,
599 49, 49, 49, 49, 49, -49, 49
600
601 },
602
603 {
604 11, -50, -50, -50, -50, -50, -50, -50, -50, -50,
605 -50, -50, -50, -50, -50, -50, -50
606 },
607
608 {
609 11, -51, -51, 52, -51, -51, -51, -51, -51, -51,
610 -51, -51, -51, -51, -51, -51, -51
611 },
612
613 {
614 11, -52, -52, -52, -52, -52, -52, -52, -52, -52,
615 -52, -52, -52, -52, -52, -52, -52
616 },
617
618 {
619 11, -53, -53, -53, -53, -53, -53, -53, -53, -53,
620 -53, -53, -53, -53, -53, -53, -53
621 },
622
623 {
624 11, 54, 54, -54, 54, 54, 54, 54, 54, 54,
625 54, 54, 54, 54, 54, 54, 54
626
627 },
628
629 {
630 11, -55, -55, -55, -55, -55, -55, -55, -55, -55,
631 -55, -55, -55, -55, -55, -55, -55
632 },
633
634 {
635 11, -56, -56, -56, -56, -56, -56, -56, -56, -56,
636 -56, 60, 57, 57, -56, -56, -56
637 },
638
639 {
640 11, -57, -57, -57, -57, -57, -57, -57, -57, -57,
641 -57, 57, 57, 57, -57, -57, -57
642 },
643
644 {
645 11, -58, -58, -58, -58, -58, -58, -58, -58, -58,
646 -58, -58, -58, -58, -58, -58, -58
647 },
648
649 {
650 11, -59, -59, -59, -59, -59, -59, -59, -59, -59,
651 -59, -59, -59, -59, -59, -59, -59
652
653 },
654
655 {
656 11, -60, -60, -60, -60, -60, -60, -60, -60, -60,
657 -60, 57, 57, 57, -60, -60, -60
658 },
659
660 } ;
661
662static yy_state_type yy_get_previous_state (void );
663static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
664static int yy_get_next_buffer (void );
665static void yy_fatal_error (yyconst char msg[] );
666
667/* Done after the current pattern has been matched and before the
668 * corresponding action - sets up zconftext.
669 */
670#define YY_DO_BEFORE_ACTION \
671 (yytext_ptr) = yy_bp; \
672 zconfleng = (size_t) (yy_cp - yy_bp); \
673 (yy_hold_char) = *yy_cp; \
674 *yy_cp = '\0'; \
675 (yy_c_buf_p) = yy_cp;
676
677#define YY_NUM_RULES 33
678#define YY_END_OF_BUFFER 34
679/* This struct is not used in this scanner,
680 but its presence is necessary. */
681struct yy_trans_info
682 {
683 flex_int32_t yy_verify;
684 flex_int32_t yy_nxt;
685 };
686static yyconst flex_int16_t yy_accept[61] =
687 { 0,
688 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
689 34, 5, 4, 2, 3, 7, 8, 6, 32, 29,
690 31, 24, 28, 27, 26, 22, 17, 13, 16, 20,
691 22, 11, 12, 19, 19, 14, 22, 22, 4, 2,
692 3, 3, 1, 6, 32, 29, 31, 30, 24, 23,
693 26, 25, 15, 20, 9, 19, 19, 21, 10, 18
694 } ;
695
696static yyconst flex_int32_t yy_ec[256] =
697 { 0,
698 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
699 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
700 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
701 1, 2, 4, 5, 6, 1, 1, 7, 8, 9,
702 10, 1, 1, 1, 11, 12, 12, 13, 13, 13,
703 13, 13, 13, 13, 13, 13, 13, 1, 1, 1,
704 14, 1, 1, 1, 13, 13, 13, 13, 13, 13,
705 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
706 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
707 1, 15, 1, 1, 13, 1, 13, 13, 13, 13,
708
709 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
710 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
711 13, 13, 1, 16, 1, 1, 1, 1, 1, 1,
712 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
713 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
714 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
715 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
716 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
717 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
718 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
719
720 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
721 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
722 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
723 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
724 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
725 1, 1, 1, 1, 1
726 } ;
727
728extern int zconf_flex_debug;
729int zconf_flex_debug = 0;
730
731/* The intent behind this definition is that it'll catch
732 * any uses of REJECT which flex missed.
733 */
734#define REJECT reject_used_but_not_detected
735#define yymore() yymore_used_but_not_detected
736#define YY_MORE_ADJ 0
737#define YY_RESTORE_YY_MORE_OFFSET
738char *zconftext;
739
740/*
741 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
742 * Released under the terms of the GNU GPL v2.0.
743 */
744
745#include <limits.h>
746#include <stdio.h>
747#include <stdlib.h>
748#include <string.h>
749#include <unistd.h>
750
751#define LKC_DIRECT_LINK
752#include "lkc.h"
753
754#define START_STRSIZE 16
755
756static struct {
757 struct file *file;
758 int lineno;
759} current_pos;
760
761static char *text;
762static int text_size, text_asize;
763
764struct buffer {
765 struct buffer *parent;
766 YY_BUFFER_STATE state;
767};
768
769struct buffer *current_buf;
770
771static int last_ts, first_ts;
772
773static void zconf_endhelp(void);
774static void zconf_endfile(void);
775
776void new_string(void)
777{
778 text = malloc(START_STRSIZE);
779 text_asize = START_STRSIZE;
780 text_size = 0;
781 *text = 0;
782}
783
784void append_string(const char *str, int size)
785{
786 int new_size = text_size + size + 1;
787 if (new_size > text_asize) {
788 new_size += START_STRSIZE - 1;
789 new_size &= -START_STRSIZE;
790 text = realloc(text, new_size);
791 text_asize = new_size;
792 }
793 memcpy(text + text_size, str, size);
794 text_size += size;
795 text[text_size] = 0;
796}
797
798void alloc_string(const char *str, int size)
799{
800 text = malloc(size + 1);
801 memcpy(text, str, size);
802 text[size] = 0;
803}
804
805#define INITIAL 0
806#define COMMAND 1
807#define HELP 2
808#define STRING 3
809#define PARAM 4
810
811#ifndef YY_NO_UNISTD_H
812/* Special case for "unistd.h", since it is non-ANSI. We include it way
813 * down here because we want the user's section 1 to have been scanned first.
814 * The user has a chance to override it with an option.
815 */
816#include <unistd.h>
817#endif
818
819#ifndef YY_EXTRA_TYPE
820#define YY_EXTRA_TYPE void *
821#endif
822
823/* Macros after this point can all be overridden by user definitions in
824 * section 1.
825 */
826
827#ifndef YY_SKIP_YYWRAP
828#ifdef __cplusplus
829extern "C" int zconfwrap (void );
830#else
831extern int zconfwrap (void );
832#endif
833#endif
834
835 static void yyunput (int c,char *buf_ptr );
836
837#ifndef yytext_ptr
838static void yy_flex_strncpy (char *,yyconst char *,int );
839#endif
840
841#ifdef YY_NEED_STRLEN
842static int yy_flex_strlen (yyconst char * );
843#endif
844
845#ifndef YY_NO_INPUT
846
847#ifdef __cplusplus
848static int yyinput (void );
849#else
850static int input (void );
851#endif
852
853#endif
854
855/* Amount of stuff to slurp up with each read. */
856#ifndef YY_READ_BUF_SIZE
857#define YY_READ_BUF_SIZE 8192
858#endif
859
860/* Copy whatever the last rule matched to the standard output. */
861#ifndef ECHO
862/* This used to be an fputs(), but since the string might contain NUL's,
863 * we now use fwrite().
864 */
865#define ECHO (void) fwrite( zconftext, zconfleng, 1, zconfout )
866#endif
867
868/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
869 * is returned in "result".
870 */
871#ifndef YY_INPUT
872#define YY_INPUT(buf,result,max_size) \
873 errno=0; \
874 while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \
875 { \
876 if( errno != EINTR) \
877 { \
878 YY_FATAL_ERROR( "input in flex scanner failed" ); \
879 break; \
880 } \
881 errno=0; \
882 clearerr(zconfin); \
883 }\
884\
885
886#endif
887
888/* No semi-colon after return; correct usage is to write "yyterminate();" -
889 * we don't want an extra ';' after the "return" because that will cause
890 * some compilers to complain about unreachable statements.
891 */
892#ifndef yyterminate
893#define yyterminate() return YY_NULL
894#endif
895
896/* Number of entries by which start-condition stack grows. */
897#ifndef YY_START_STACK_INCR
898#define YY_START_STACK_INCR 25
899#endif
900
901/* Report a fatal error. */
902#ifndef YY_FATAL_ERROR
903#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
904#endif
905
906/* end tables serialization structures and prototypes */
907
908/* Default declaration of generated scanner - a define so the user can
909 * easily add parameters.
910 */
911#ifndef YY_DECL
912#define YY_DECL_IS_OURS 1
913
914extern int zconflex (void);
915
916#define YY_DECL int zconflex (void)
917#endif /* !YY_DECL */
918
919/* Code executed at the beginning of each rule, after zconftext and zconfleng
920 * have been set up.
921 */
922#ifndef YY_USER_ACTION
923#define YY_USER_ACTION
924#endif
925
926/* Code executed at the end of each rule. */
927#ifndef YY_BREAK
928#define YY_BREAK break;
929#endif
930
931#define YY_RULE_SETUP \
932 YY_USER_ACTION
933
934/** The main scanner function which does all the work.
935 */
936YY_DECL
937{
938 register yy_state_type yy_current_state;
939 register char *yy_cp, *yy_bp;
940 register int yy_act;
941
942 int str = 0;
943 int ts, i;
944
945 if ( (yy_init) )
946 {
947 (yy_init) = 0;
948
949#ifdef YY_USER_INIT
950 YY_USER_INIT;
951#endif
952
953 if ( ! (yy_start) )
954 (yy_start) = 1; /* first start state */
955
956 if ( ! zconfin )
957 zconfin = stdin;
958
959 if ( ! zconfout )
960 zconfout = stdout;
961
962 if ( ! YY_CURRENT_BUFFER ) {
963 zconfensure_buffer_stack ();
964 YY_CURRENT_BUFFER_LVALUE =
965 zconf_create_buffer(zconfin,YY_BUF_SIZE );
966 }
967
968 zconf_load_buffer_state( );
969 }
970
971 while ( 1 ) /* loops until end-of-file is reached */
972 {
973 yy_cp = (yy_c_buf_p);
974
975 /* Support of zconftext. */
976 *yy_cp = (yy_hold_char);
977
978 /* yy_bp points to the position in yy_ch_buf of the start of
979 * the current run.
980 */
981 yy_bp = yy_cp;
982
983 yy_current_state = (yy_start);
984yy_match:
985 while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 )
986 ++yy_cp;
987
988 yy_current_state = -yy_current_state;
989
990yy_find_action:
991 yy_act = yy_accept[yy_current_state];
992
993 YY_DO_BEFORE_ACTION;
994
995do_action: /* This label is used only to access EOF actions. */
996
997 switch ( yy_act )
998 { /* beginning of action switch */
999case 1:
1000/* rule 1 can match eol */
1001case 2:
1002/* rule 2 can match eol */
1003YY_RULE_SETUP
1004{
1005 current_file->lineno++;
1006 return T_EOL;
1007}
1008 YY_BREAK
1009case 3:
1010YY_RULE_SETUP
1011
1012 YY_BREAK
1013case 4:
1014YY_RULE_SETUP
1015{
1016 BEGIN(COMMAND);
1017}
1018 YY_BREAK
1019case 5:
1020YY_RULE_SETUP
1021{
1022 unput(zconftext[0]);
1023 BEGIN(COMMAND);
1024}
1025 YY_BREAK
1026
1027case 6:
1028YY_RULE_SETUP
1029{
1030 struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
1031 BEGIN(PARAM);
1032 current_pos.file = current_file;
1033 current_pos.lineno = current_file->lineno;
1034 if (id && id->flags & TF_COMMAND) {
1035 zconflval.id = id;
1036 return id->token;
1037 }
1038 alloc_string(zconftext, zconfleng);
1039 zconflval.string = text;
1040 return T_WORD;
1041 }
1042 YY_BREAK
1043case 7:
1044YY_RULE_SETUP
1045
1046 YY_BREAK
1047case 8:
1048/* rule 8 can match eol */
1049YY_RULE_SETUP
1050{
1051 BEGIN(INITIAL);
1052 current_file->lineno++;
1053 return T_EOL;
1054 }
1055 YY_BREAK
1056
1057case 9:
1058YY_RULE_SETUP
1059return T_AND;
1060 YY_BREAK
1061case 10:
1062YY_RULE_SETUP
1063return T_OR;
1064 YY_BREAK
1065case 11:
1066YY_RULE_SETUP
1067return T_OPEN_PAREN;
1068 YY_BREAK
1069case 12:
1070YY_RULE_SETUP
1071return T_CLOSE_PAREN;
1072 YY_BREAK
1073case 13:
1074YY_RULE_SETUP
1075return T_NOT;
1076 YY_BREAK
1077case 14:
1078YY_RULE_SETUP
1079return T_EQUAL;
1080 YY_BREAK
1081case 15:
1082YY_RULE_SETUP
1083return T_UNEQUAL;
1084 YY_BREAK
1085case 16:
1086YY_RULE_SETUP
1087{
1088 str = zconftext[0];
1089 new_string();
1090 BEGIN(STRING);
1091 }
1092 YY_BREAK
1093case 17:
1094/* rule 17 can match eol */
1095YY_RULE_SETUP
1096BEGIN(INITIAL); current_file->lineno++; return T_EOL;
1097 YY_BREAK
1098case 18:
1099YY_RULE_SETUP
1100/* ignore */
1101 YY_BREAK
1102case 19:
1103YY_RULE_SETUP
1104{
1105 struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
1106 if (id && id->flags & TF_PARAM) {
1107 zconflval.id = id;
1108 return id->token;
1109 }
1110 alloc_string(zconftext, zconfleng);
1111 zconflval.string = text;
1112 return T_WORD;
1113 }
1114 YY_BREAK
1115case 20:
1116YY_RULE_SETUP
1117/* comment */
1118 YY_BREAK
1119case 21:
1120/* rule 21 can match eol */
1121YY_RULE_SETUP
1122current_file->lineno++;
1123 YY_BREAK
1124case 22:
1125YY_RULE_SETUP
1126
1127 YY_BREAK
1128case YY_STATE_EOF(PARAM):
1129{
1130 BEGIN(INITIAL);
1131 }
1132 YY_BREAK
1133
1134case 23:
1135/* rule 23 can match eol */
1136*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
1137(yy_c_buf_p) = yy_cp -= 1;
1138YY_DO_BEFORE_ACTION; /* set up zconftext again */
1139YY_RULE_SETUP
1140{
1141 append_string(zconftext, zconfleng);
1142 zconflval.string = text;
1143 return T_WORD_QUOTE;
1144 }
1145 YY_BREAK
1146case 24:
1147YY_RULE_SETUP
1148{
1149 append_string(zconftext, zconfleng);
1150 }
1151 YY_BREAK
1152case 25:
1153/* rule 25 can match eol */
1154*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
1155(yy_c_buf_p) = yy_cp -= 1;
1156YY_DO_BEFORE_ACTION; /* set up zconftext again */
1157YY_RULE_SETUP
1158{
1159 append_string(zconftext + 1, zconfleng - 1);
1160 zconflval.string = text;
1161 return T_WORD_QUOTE;
1162 }
1163 YY_BREAK
1164case 26:
1165YY_RULE_SETUP
1166{
1167 append_string(zconftext + 1, zconfleng - 1);
1168 }
1169 YY_BREAK
1170case 27:
1171YY_RULE_SETUP
1172{
1173 if (str == zconftext[0]) {
1174 BEGIN(PARAM);
1175 zconflval.string = text;
1176 return T_WORD_QUOTE;
1177 } else
1178 append_string(zconftext, 1);
1179 }
1180 YY_BREAK
1181case 28:
1182/* rule 28 can match eol */
1183YY_RULE_SETUP
1184{
1185 printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
1186 current_file->lineno++;
1187 BEGIN(INITIAL);
1188 return T_EOL;
1189 }
1190 YY_BREAK
1191case YY_STATE_EOF(STRING):
1192{
1193 BEGIN(INITIAL);
1194 }
1195 YY_BREAK
1196
1197case 29:
1198YY_RULE_SETUP
1199{
1200 ts = 0;
1201 for (i = 0; i < zconfleng; i++) {
1202 if (zconftext[i] == '\t')
1203 ts = (ts & ~7) + 8;
1204 else
1205 ts++;
1206 }
1207 last_ts = ts;
1208 if (first_ts) {
1209 if (ts < first_ts) {
1210 zconf_endhelp();
1211 return T_HELPTEXT;
1212 }
1213 ts -= first_ts;
1214 while (ts > 8) {
1215 append_string(" ", 8);
1216 ts -= 8;
1217 }
1218 append_string(" ", ts);
1219 }
1220 }
1221 YY_BREAK
1222case 30:
1223/* rule 30 can match eol */
1224*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
1225(yy_c_buf_p) = yy_cp -= 1;
1226YY_DO_BEFORE_ACTION; /* set up zconftext again */
1227YY_RULE_SETUP
1228{
1229 current_file->lineno++;
1230 zconf_endhelp();
1231 return T_HELPTEXT;
1232 }
1233 YY_BREAK
1234case 31:
1235/* rule 31 can match eol */
1236YY_RULE_SETUP
1237{
1238 current_file->lineno++;
1239 append_string("\n", 1);
1240 }
1241 YY_BREAK
1242case 32:
1243YY_RULE_SETUP
1244{
1245 append_string(zconftext, zconfleng);
1246 if (!first_ts)
1247 first_ts = last_ts;
1248 }
1249 YY_BREAK
1250case YY_STATE_EOF(HELP):
1251{
1252 zconf_endhelp();
1253 return T_HELPTEXT;
1254 }
1255 YY_BREAK
1256
1257case YY_STATE_EOF(INITIAL):
1258case YY_STATE_EOF(COMMAND):
1259{
1260 if (current_file) {
1261 zconf_endfile();
1262 return T_EOL;
1263 }
1264 fclose(zconfin);
1265 yyterminate();
1266}
1267 YY_BREAK
1268case 33:
1269YY_RULE_SETUP
1270YY_FATAL_ERROR( "flex scanner jammed" );
1271 YY_BREAK
1272
1273 case YY_END_OF_BUFFER:
1274 {
1275 /* Amount of text matched not including the EOB char. */
1276 int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
1277
1278 /* Undo the effects of YY_DO_BEFORE_ACTION. */
1279 *yy_cp = (yy_hold_char);
1280 YY_RESTORE_YY_MORE_OFFSET
1281
1282 if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
1283 {
1284 /* We're scanning a new file or input source. It's
1285 * possible that this happened because the user
1286 * just pointed zconfin at a new source and called
1287 * zconflex(). If so, then we have to assure
1288 * consistency between YY_CURRENT_BUFFER and our
1289 * globals. Here is the right place to do so, because
1290 * this is the first action (other than possibly a
1291 * back-up) that will match for the new input source.
1292 */
1293 (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
1294 YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin;
1295 YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
1296 }
1297
1298 /* Note that here we test for yy_c_buf_p "<=" to the position
1299 * of the first EOB in the buffer, since yy_c_buf_p will
1300 * already have been incremented past the NUL character
1301 * (since all states make transitions on EOB to the
1302 * end-of-buffer state). Contrast this with the test
1303 * in input().
1304 */
1305 if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
1306 { /* This was really a NUL. */
1307 yy_state_type yy_next_state;
1308
1309 (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
1310
1311 yy_current_state = yy_get_previous_state( );
1312
1313 /* Okay, we're now positioned to make the NUL
1314 * transition. We couldn't have
1315 * yy_get_previous_state() go ahead and do it
1316 * for us because it doesn't know how to deal
1317 * with the possibility of jamming (and we don't
1318 * want to build jamming into it because then it
1319 * will run more slowly).
1320 */
1321
1322 yy_next_state = yy_try_NUL_trans( yy_current_state );
1323
1324 yy_bp = (yytext_ptr) + YY_MORE_ADJ;
1325
1326 if ( yy_next_state )
1327 {
1328 /* Consume the NUL. */
1329 yy_cp = ++(yy_c_buf_p);
1330 yy_current_state = yy_next_state;
1331 goto yy_match;
1332 }
1333
1334 else
1335 {
1336 yy_cp = (yy_c_buf_p);
1337 goto yy_find_action;
1338 }
1339 }
1340
1341 else switch ( yy_get_next_buffer( ) )
1342 {
1343 case EOB_ACT_END_OF_FILE:
1344 {
1345 (yy_did_buffer_switch_on_eof) = 0;
1346
1347 if ( zconfwrap( ) )
1348 {
1349 /* Note: because we've taken care in
1350 * yy_get_next_buffer() to have set up
1351 * zconftext, we can now set up
1352 * yy_c_buf_p so that if some total
1353 * hoser (like flex itself) wants to
1354 * call the scanner after we return the
1355 * YY_NULL, it'll still work - another
1356 * YY_NULL will get returned.
1357 */
1358 (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
1359
1360 yy_act = YY_STATE_EOF(YY_START);
1361 goto do_action;
1362 }
1363
1364 else
1365 {
1366 if ( ! (yy_did_buffer_switch_on_eof) )
1367 YY_NEW_FILE;
1368 }
1369 break;
1370 }
1371
1372 case EOB_ACT_CONTINUE_SCAN:
1373 (yy_c_buf_p) =
1374 (yytext_ptr) + yy_amount_of_matched_text;
1375
1376 yy_current_state = yy_get_previous_state( );
1377
1378 yy_cp = (yy_c_buf_p);
1379 yy_bp = (yytext_ptr) + YY_MORE_ADJ;
1380 goto yy_match;
1381
1382 case EOB_ACT_LAST_MATCH:
1383 (yy_c_buf_p) =
1384 &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
1385
1386 yy_current_state = yy_get_previous_state( );
1387
1388 yy_cp = (yy_c_buf_p);
1389 yy_bp = (yytext_ptr) + YY_MORE_ADJ;
1390 goto yy_find_action;
1391 }
1392 break;
1393 }
1394
1395 default:
1396 YY_FATAL_ERROR(
1397 "fatal flex scanner internal error--no action found" );
1398 } /* end of action switch */
1399 } /* end of scanning one token */
1400} /* end of zconflex */
1401
1402/* yy_get_next_buffer - try to read in a new buffer
1403 *
1404 * Returns a code representing an action:
1405 * EOB_ACT_LAST_MATCH -
1406 * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
1407 * EOB_ACT_END_OF_FILE - end of file
1408 */
1409static int yy_get_next_buffer (void)
1410{
1411 register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
1412 register char *source = (yytext_ptr);
1413 register int number_to_move, i;
1414 int ret_val;
1415
1416 if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
1417 YY_FATAL_ERROR(
1418 "fatal flex scanner internal error--end of buffer missed" );
1419
1420 if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
1421 { /* Don't try to fill the buffer, so this is an EOF. */
1422 if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
1423 {
1424 /* We matched a single character, the EOB, so
1425 * treat this as a final EOF.
1426 */
1427 return EOB_ACT_END_OF_FILE;
1428 }
1429
1430 else
1431 {
1432 /* We matched some text prior to the EOB, first
1433 * process it.
1434 */
1435 return EOB_ACT_LAST_MATCH;
1436 }
1437 }
1438
1439 /* Try to read more data. */
1440
1441 /* First move last chars to start of buffer. */
1442 number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
1443
1444 for ( i = 0; i < number_to_move; ++i )
1445 *(dest++) = *(source++);
1446
1447 if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
1448 /* don't do the read, it's not guaranteed to return an EOF,
1449 * just force an EOF
1450 */
1451 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
1452
1453 else
1454 {
1455 size_t num_to_read =
1456 YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
1457
1458 while ( num_to_read <= 0 )
1459 { /* Not enough room in the buffer - grow it. */
1460
1461 /* just a shorter name for the current buffer */
1462 YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
1463
1464 int yy_c_buf_p_offset =
1465 (int) ((yy_c_buf_p) - b->yy_ch_buf);
1466
1467 if ( b->yy_is_our_buffer )
1468 {
1469 int new_size = b->yy_buf_size * 2;
1470
1471 if ( new_size <= 0 )
1472 b->yy_buf_size += b->yy_buf_size / 8;
1473 else
1474 b->yy_buf_size *= 2;
1475
1476 b->yy_ch_buf = (char *)
1477 /* Include room in for 2 EOB chars. */
1478 zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
1479 }
1480 else
1481 /* Can't grow it, we don't own it. */
1482 b->yy_ch_buf = 0;
1483
1484 if ( ! b->yy_ch_buf )
1485 YY_FATAL_ERROR(
1486 "fatal error - scanner input buffer overflow" );
1487
1488 (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
1489
1490 num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
1491 number_to_move - 1;
1492
1493 }
1494
1495 if ( num_to_read > YY_READ_BUF_SIZE )
1496 num_to_read = YY_READ_BUF_SIZE;
1497
1498 /* Read in more data. */
1499 YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
1500 (yy_n_chars), num_to_read );
1501
1502 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
1503 }
1504
1505 if ( (yy_n_chars) == 0 )
1506 {
1507 if ( number_to_move == YY_MORE_ADJ )
1508 {
1509 ret_val = EOB_ACT_END_OF_FILE;
1510 zconfrestart(zconfin );
1511 }
1512
1513 else
1514 {
1515 ret_val = EOB_ACT_LAST_MATCH;
1516 YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
1517 YY_BUFFER_EOF_PENDING;
1518 }
1519 }
1520
1521 else
1522 ret_val = EOB_ACT_CONTINUE_SCAN;
1523
1524 (yy_n_chars) += number_to_move;
1525 YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
1526 YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
1527
1528 (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
1529
1530 return ret_val;
1531}
1532
1533/* yy_get_previous_state - get the state just before the EOB char was reached */
1534
1535 static yy_state_type yy_get_previous_state (void)
1536{
1537 register yy_state_type yy_current_state;
1538 register char *yy_cp;
1539
1540 yy_current_state = (yy_start);
1541
1542 for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
1543 {
1544 yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)];
1545 }
1546
1547 return yy_current_state;
1548}
1549
1550/* yy_try_NUL_trans - try to make a transition on the NUL character
1551 *
1552 * synopsis
1553 * next_state = yy_try_NUL_trans( current_state );
1554 */
1555 static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
1556{
1557 register int yy_is_jam;
1558
1559 yy_current_state = yy_nxt[yy_current_state][1];
1560 yy_is_jam = (yy_current_state <= 0);
1561
1562 return yy_is_jam ? 0 : yy_current_state;
1563}
1564
1565 static void yyunput (int c, register char * yy_bp )
1566{
1567 register char *yy_cp;
1568
1569 yy_cp = (yy_c_buf_p);
1570
1571 /* undo effects of setting up zconftext */
1572 *yy_cp = (yy_hold_char);
1573
1574 if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
1575 { /* need to shift things up to make room */
1576 /* +2 for EOB chars. */
1577 register int number_to_move = (yy_n_chars) + 2;
1578 register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
1579 YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
1580 register char *source =
1581 &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
1582
1583 while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
1584 *--dest = *--source;
1585
1586 yy_cp += (int) (dest - source);
1587 yy_bp += (int) (dest - source);
1588 YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
1589 (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
1590
1591 if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
1592 YY_FATAL_ERROR( "flex scanner push-back overflow" );
1593 }
1594
1595 *--yy_cp = (char) c;
1596
1597 (yytext_ptr) = yy_bp;
1598 (yy_hold_char) = *yy_cp;
1599 (yy_c_buf_p) = yy_cp;
1600}
1601
1602#ifndef YY_NO_INPUT
1603#ifdef __cplusplus
1604 static int yyinput (void)
1605#else
1606 static int input (void)
1607#endif
1608
1609{
1610 int c;
1611
1612 *(yy_c_buf_p) = (yy_hold_char);
1613
1614 if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
1615 {
1616 /* yy_c_buf_p now points to the character we want to return.
1617 * If this occurs *before* the EOB characters, then it's a
1618 * valid NUL; if not, then we've hit the end of the buffer.
1619 */
1620 if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
1621 /* This was really a NUL. */
1622 *(yy_c_buf_p) = '\0';
1623
1624 else
1625 { /* need more input */
1626 int offset = (yy_c_buf_p) - (yytext_ptr);
1627 ++(yy_c_buf_p);
1628
1629 switch ( yy_get_next_buffer( ) )
1630 {
1631 case EOB_ACT_LAST_MATCH:
1632 /* This happens because yy_g_n_b()
1633 * sees that we've accumulated a
1634 * token and flags that we need to
1635 * try matching the token before
1636 * proceeding. But for input(),
1637 * there's no matching to consider.
1638 * So convert the EOB_ACT_LAST_MATCH
1639 * to EOB_ACT_END_OF_FILE.
1640 */
1641
1642 /* Reset buffer status. */
1643 zconfrestart(zconfin );
1644
1645 /*FALLTHROUGH*/
1646
1647 case EOB_ACT_END_OF_FILE:
1648 {
1649 if ( zconfwrap( ) )
1650 return EOF;
1651
1652 if ( ! (yy_did_buffer_switch_on_eof) )
1653 YY_NEW_FILE;
1654#ifdef __cplusplus
1655 return yyinput();
1656#else
1657 return input();
1658#endif
1659 }
1660
1661 case EOB_ACT_CONTINUE_SCAN:
1662 (yy_c_buf_p) = (yytext_ptr) + offset;
1663 break;
1664 }
1665 }
1666 }
1667
1668 c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
1669 *(yy_c_buf_p) = '\0'; /* preserve zconftext */
1670 (yy_hold_char) = *++(yy_c_buf_p);
1671
1672 return c;
1673}
1674#endif /* ifndef YY_NO_INPUT */
1675
1676/** Immediately switch to a different input stream.
1677 * @param input_file A readable stream.
1678 *
1679 * @note This function does not reset the start condition to @c INITIAL .
1680 */
1681 void zconfrestart (FILE * input_file )
1682{
1683
1684 if ( ! YY_CURRENT_BUFFER ){
1685 zconfensure_buffer_stack ();
1686 YY_CURRENT_BUFFER_LVALUE =
1687 zconf_create_buffer(zconfin,YY_BUF_SIZE );
1688 }
1689
1690 zconf_init_buffer(YY_CURRENT_BUFFER,input_file );
1691 zconf_load_buffer_state( );
1692}
1693
1694/** Switch to a different input buffer.
1695 * @param new_buffer The new input buffer.
1696 *
1697 */
1698 void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer )
1699{
1700
1701 /* TODO. We should be able to replace this entire function body
1702 * with
1703 * zconfpop_buffer_state();
1704 * zconfpush_buffer_state(new_buffer);
1705 */
1706 zconfensure_buffer_stack ();
1707 if ( YY_CURRENT_BUFFER == new_buffer )
1708 return;
1709
1710 if ( YY_CURRENT_BUFFER )
1711 {
1712 /* Flush out information for old buffer. */
1713 *(yy_c_buf_p) = (yy_hold_char);
1714 YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
1715 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
1716 }
1717
1718 YY_CURRENT_BUFFER_LVALUE = new_buffer;
1719 zconf_load_buffer_state( );
1720
1721 /* We don't actually know whether we did this switch during
1722 * EOF (zconfwrap()) processing, but the only time this flag
1723 * is looked at is after zconfwrap() is called, so it's safe
1724 * to go ahead and always set it.
1725 */
1726 (yy_did_buffer_switch_on_eof) = 1;
1727}
1728
1729static void zconf_load_buffer_state (void)
1730{
1731 (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
1732 (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
1733 zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
1734 (yy_hold_char) = *(yy_c_buf_p);
1735}
1736
1737/** Allocate and initialize an input buffer state.
1738 * @param file A readable stream.
1739 * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
1740 *
1741 * @return the allocated buffer state.
1742 */
1743 YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size )
1744{
1745 YY_BUFFER_STATE b;
1746
1747 b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) );
1748 if ( ! b )
1749 YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
1750
1751 b->yy_buf_size = size;
1752
1753 /* yy_ch_buf has to be 2 characters longer than the size given because
1754 * we need to put in 2 end-of-buffer characters.
1755 */
1756 b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 );
1757 if ( ! b->yy_ch_buf )
1758 YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
1759
1760 b->yy_is_our_buffer = 1;
1761
1762 zconf_init_buffer(b,file );
1763
1764 return b;
1765}
1766
1767/** Destroy the buffer.
1768 * @param b a buffer created with zconf_create_buffer()
1769 *
1770 */
1771 void zconf_delete_buffer (YY_BUFFER_STATE b )
1772{
1773
1774 if ( ! b )
1775 return;
1776
1777 if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
1778 YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
1779
1780 if ( b->yy_is_our_buffer )
1781 zconffree((void *) b->yy_ch_buf );
1782
1783 zconffree((void *) b );
1784}
1785
1786/* Initializes or reinitializes a buffer.
1787 * This function is sometimes called more than once on the same buffer,
1788 * such as during a zconfrestart() or at EOF.
1789 */
1790 static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file )
1791
1792{
1793 int oerrno = errno;
1794
1795 zconf_flush_buffer(b );
1796
1797 b->yy_input_file = file;
1798 b->yy_fill_buffer = 1;
1799
1800 /* If b is the current buffer, then zconf_init_buffer was _probably_
1801 * called from zconfrestart() or through yy_get_next_buffer.
1802 * In that case, we don't want to reset the lineno or column.
1803 */
1804 if (b != YY_CURRENT_BUFFER){
1805 b->yy_bs_lineno = 1;
1806 b->yy_bs_column = 0;
1807 }
1808
1809 b->yy_is_interactive = 0;
1810
1811 errno = oerrno;
1812}
1813
1814/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
1815 * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
1816 *
1817 */
1818 void zconf_flush_buffer (YY_BUFFER_STATE b )
1819{
1820 if ( ! b )
1821 return;
1822
1823 b->yy_n_chars = 0;
1824
1825 /* We always need two end-of-buffer characters. The first causes
1826 * a transition to the end-of-buffer state. The second causes
1827 * a jam in that state.
1828 */
1829 b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
1830 b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
1831
1832 b->yy_buf_pos = &b->yy_ch_buf[0];
1833
1834 b->yy_at_bol = 1;
1835 b->yy_buffer_status = YY_BUFFER_NEW;
1836
1837 if ( b == YY_CURRENT_BUFFER )
1838 zconf_load_buffer_state( );
1839}
1840
1841/** Pushes the new state onto the stack. The new state becomes
1842 * the current state. This function will allocate the stack
1843 * if necessary.
1844 * @param new_buffer The new state.
1845 *
1846 */
1847void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer )
1848{
1849 if (new_buffer == NULL)
1850 return;
1851
1852 zconfensure_buffer_stack();
1853
1854 /* This block is copied from zconf_switch_to_buffer. */
1855 if ( YY_CURRENT_BUFFER )
1856 {
1857 /* Flush out information for old buffer. */
1858 *(yy_c_buf_p) = (yy_hold_char);
1859 YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
1860 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
1861 }
1862
1863 /* Only push if top exists. Otherwise, replace top. */
1864 if (YY_CURRENT_BUFFER)
1865 (yy_buffer_stack_top)++;
1866 YY_CURRENT_BUFFER_LVALUE = new_buffer;
1867
1868 /* copied from zconf_switch_to_buffer. */
1869 zconf_load_buffer_state( );
1870 (yy_did_buffer_switch_on_eof) = 1;
1871}
1872
1873/** Removes and deletes the top of the stack, if present.
1874 * The next element becomes the new top.
1875 *
1876 */
1877void zconfpop_buffer_state (void)
1878{
1879 if (!YY_CURRENT_BUFFER)
1880 return;
1881
1882 zconf_delete_buffer(YY_CURRENT_BUFFER );
1883 YY_CURRENT_BUFFER_LVALUE = NULL;
1884 if ((yy_buffer_stack_top) > 0)
1885 --(yy_buffer_stack_top);
1886
1887 if (YY_CURRENT_BUFFER) {
1888 zconf_load_buffer_state( );
1889 (yy_did_buffer_switch_on_eof) = 1;
1890 }
1891}
1892
1893/* Allocates the stack if it does not exist.
1894 * Guarantees space for at least one push.
1895 */
1896static void zconfensure_buffer_stack (void)
1897{
1898 int num_to_alloc;
1899
1900 if (!(yy_buffer_stack)) {
1901
1902 /* First allocation is just for 2 elements, since we don't know if this
1903 * scanner will even need a stack. We use 2 instead of 1 to avoid an
1904 * immediate realloc on the next call.
1905 */
1906 num_to_alloc = 1;
1907 (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc
1908 (num_to_alloc * sizeof(struct yy_buffer_state*)
1909 );
1910
1911 memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
1912
1913 (yy_buffer_stack_max) = num_to_alloc;
1914 (yy_buffer_stack_top) = 0;
1915 return;
1916 }
1917
1918 if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
1919
1920 /* Increase the buffer to prepare for a possible push. */
1921 int grow_size = 8 /* arbitrary grow size */;
1922
1923 num_to_alloc = (yy_buffer_stack_max) + grow_size;
1924 (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc
1925 ((yy_buffer_stack),
1926 num_to_alloc * sizeof(struct yy_buffer_state*)
1927 );
1928
1929 /* zero only the new slots.*/
1930 memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
1931 (yy_buffer_stack_max) = num_to_alloc;
1932 }
1933}
1934
1935/** Setup the input buffer state to scan directly from a user-specified character buffer.
1936 * @param base the character buffer
1937 * @param size the size in bytes of the character buffer
1938 *
1939 * @return the newly allocated buffer state object.
1940 */
1941YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size )
1942{
1943 YY_BUFFER_STATE b;
1944
1945 if ( size < 2 ||
1946 base[size-2] != YY_END_OF_BUFFER_CHAR ||
1947 base[size-1] != YY_END_OF_BUFFER_CHAR )
1948 /* They forgot to leave room for the EOB's. */
1949 return 0;
1950
1951 b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) );
1952 if ( ! b )
1953 YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" );
1954
1955 b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
1956 b->yy_buf_pos = b->yy_ch_buf = base;
1957 b->yy_is_our_buffer = 0;
1958 b->yy_input_file = 0;
1959 b->yy_n_chars = b->yy_buf_size;
1960 b->yy_is_interactive = 0;
1961 b->yy_at_bol = 1;
1962 b->yy_fill_buffer = 0;
1963 b->yy_buffer_status = YY_BUFFER_NEW;
1964
1965 zconf_switch_to_buffer(b );
1966
1967 return b;
1968}
1969
1970/** Setup the input buffer state to scan a string. The next call to zconflex() will
1971 * scan from a @e copy of @a str.
1972 * @param yy_str a NUL-terminated string to scan
1973 *
1974 * @return the newly allocated buffer state object.
1975 * @note If you want to scan bytes that may contain NUL values, then use
1976 * zconf_scan_bytes() instead.
1977 */
1978YY_BUFFER_STATE zconf_scan_string (yyconst char * yy_str )
1979{
1980
1981 return zconf_scan_bytes(yy_str,strlen(yy_str) );
1982}
1983
1984/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
1985 * scan from a @e copy of @a bytes.
1986 * @param bytes the byte buffer to scan
1987 * @param len the number of bytes in the buffer pointed to by @a bytes.
1988 *
1989 * @return the newly allocated buffer state object.
1990 */
1991YY_BUFFER_STATE zconf_scan_bytes (yyconst char * bytes, int len )
1992{
1993 YY_BUFFER_STATE b;
1994 char *buf;
1995 yy_size_t n;
1996 int i;
1997
1998 /* Get memory for full buffer, including space for trailing EOB's. */
1999 n = len + 2;
2000 buf = (char *) zconfalloc(n );
2001 if ( ! buf )
2002 YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" );
2003
2004 for ( i = 0; i < len; ++i )
2005 buf[i] = bytes[i];
2006
2007 buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
2008
2009 b = zconf_scan_buffer(buf,n );
2010 if ( ! b )
2011 YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" );
2012
2013 /* It's okay to grow etc. this buffer, and we should throw it
2014 * away when we're done.
2015 */
2016 b->yy_is_our_buffer = 1;
2017
2018 return b;
2019}
2020
2021#ifndef YY_EXIT_FAILURE
2022#define YY_EXIT_FAILURE 2
2023#endif
2024
2025static void yy_fatal_error (yyconst char* msg )
2026{
2027 (void) fprintf( stderr, "%s\n", msg );
2028 exit( YY_EXIT_FAILURE );
2029}
2030
2031/* Redefine yyless() so it works in section 3 code. */
2032
2033#undef yyless
2034#define yyless(n) \
2035 do \
2036 { \
2037 /* Undo effects of setting up zconftext. */ \
2038 int yyless_macro_arg = (n); \
2039 YY_LESS_LINENO(yyless_macro_arg);\
2040 zconftext[zconfleng] = (yy_hold_char); \
2041 (yy_c_buf_p) = zconftext + yyless_macro_arg; \
2042 (yy_hold_char) = *(yy_c_buf_p); \
2043 *(yy_c_buf_p) = '\0'; \
2044 zconfleng = yyless_macro_arg; \
2045 } \
2046 while ( 0 )
2047
2048/* Accessor methods (get/set functions) to struct members. */
2049
2050/** Get the current line number.
2051 *
2052 */
2053int zconfget_lineno (void)
2054{
2055
2056 return zconflineno;
2057}
2058
2059/** Get the input stream.
2060 *
2061 */
2062FILE *zconfget_in (void)
2063{
2064 return zconfin;
2065}
2066
2067/** Get the output stream.
2068 *
2069 */
2070FILE *zconfget_out (void)
2071{
2072 return zconfout;
2073}
2074
2075/** Get the length of the current token.
2076 *
2077 */
2078int zconfget_leng (void)
2079{
2080 return zconfleng;
2081}
2082
2083/** Get the current token.
2084 *
2085 */
2086
2087char *zconfget_text (void)
2088{
2089 return zconftext;
2090}
2091
2092/** Set the current line number.
2093 * @param line_number
2094 *
2095 */
2096void zconfset_lineno (int line_number )
2097{
2098
2099 zconflineno = line_number;
2100}
2101
2102/** Set the input stream. This does not discard the current
2103 * input buffer.
2104 * @param in_str A readable stream.
2105 *
2106 * @see zconf_switch_to_buffer
2107 */
2108void zconfset_in (FILE * in_str )
2109{
2110 zconfin = in_str ;
2111}
2112
2113void zconfset_out (FILE * out_str )
2114{
2115 zconfout = out_str ;
2116}
2117
2118int zconfget_debug (void)
2119{
2120 return zconf_flex_debug;
2121}
2122
2123void zconfset_debug (int bdebug )
2124{
2125 zconf_flex_debug = bdebug ;
2126}
2127
2128/* zconflex_destroy is for both reentrant and non-reentrant scanners. */
2129int zconflex_destroy (void)
2130{
2131
2132 /* Pop the buffer stack, destroying each element. */
2133 while(YY_CURRENT_BUFFER){
2134 zconf_delete_buffer(YY_CURRENT_BUFFER );
2135 YY_CURRENT_BUFFER_LVALUE = NULL;
2136 zconfpop_buffer_state();
2137 }
2138
2139 /* Destroy the stack itself. */
2140 zconffree((yy_buffer_stack) );
2141 (yy_buffer_stack) = NULL;
2142
2143 return 0;
2144}
2145
2146/*
2147 * Internal utility routines.
2148 */
2149
2150#ifndef yytext_ptr
2151static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
2152{
2153 register int i;
2154 for ( i = 0; i < n; ++i )
2155 s1[i] = s2[i];
2156}
2157#endif
2158
2159#ifdef YY_NEED_STRLEN
2160static int yy_flex_strlen (yyconst char * s )
2161{
2162 register int n;
2163 for ( n = 0; s[n]; ++n )
2164 ;
2165
2166 return n;
2167}
2168#endif
2169
2170void *zconfalloc (yy_size_t size )
2171{
2172 return (void *) malloc( size );
2173}
2174
2175void *zconfrealloc (void * ptr, yy_size_t size )
2176{
2177 /* The cast to (char *) in the following accommodates both
2178 * implementations that use char* generic pointers, and those
2179 * that use void* generic pointers. It works with the latter
2180 * because both ANSI C and C++ allow castless assignment from
2181 * any pointer type to void*, and deal with argument conversions
2182 * as though doing an assignment.
2183 */
2184 return (void *) realloc( (char *) ptr, size );
2185}
2186
2187void zconffree (void * ptr )
2188{
2189 free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */
2190}
2191
2192#define YYTABLES_NAME "yytables"
2193
2194#undef YY_NEW_FILE
2195#undef YY_FLUSH_BUFFER
2196#undef yy_set_bol
2197#undef yy_new_buffer
2198#undef yy_set_interactive
2199#undef yytext_ptr
2200#undef YY_DO_BEFORE_ACTION
2201
2202#ifdef YY_DECL_IS_OURS
2203#undef YY_DECL_IS_OURS
2204#undef YY_DECL
2205#endif
2206
2207void zconf_starthelp(void)
2208{
2209 new_string();
2210 last_ts = first_ts = 0;
2211 BEGIN(HELP);
2212}
2213
2214static void zconf_endhelp(void)
2215{
2216 zconflval.string = text;
2217 BEGIN(INITIAL);
2218}
2219
2220/*
2221 * Try to open specified file with following names:
2222 * ./name
2223 * $(srctree)/name
2224 * The latter is used when srctree is separate from objtree
2225 * when compiling the kernel.
2226 * Return NULL if file is not found.
2227 */
2228FILE *zconf_fopen(const char *name)
2229{
2230 char *env, fullname[PATH_MAX+1];
2231 FILE *f;
2232
2233 f = fopen(name, "r");
2234 if (!f && name[0] != '/') {
2235 env = getenv(SRCTREE);
2236 if (env) {
2237 sprintf(fullname, "%s/%s", env, name);
2238 f = fopen(fullname, "r");
2239 }
2240 }
2241 return f;
2242}
2243
2244void zconf_initscan(const char *name)
2245{
2246 zconfin = zconf_fopen(name);
2247 if (!zconfin) {
2248 printf("can't find file %s\n", name);
2249 exit(1);
2250 }
2251
2252 current_buf = malloc(sizeof(*current_buf));
2253 memset(current_buf, 0, sizeof(*current_buf));
2254
2255 current_file = file_lookup(name);
2256 current_file->lineno = 1;
2257 current_file->flags = FILE_BUSY;
2258}
2259
2260void zconf_nextfile(const char *name)
2261{
2262 struct file *file = file_lookup(name);
2263 struct buffer *buf = malloc(sizeof(*buf));
2264 memset(buf, 0, sizeof(*buf));
2265
2266 current_buf->state = YY_CURRENT_BUFFER;
2267 zconfin = zconf_fopen(name);
2268 if (!zconfin) {
2269 printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
2270 exit(1);
2271 }
2272 zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
2273 buf->parent = current_buf;
2274 current_buf = buf;
2275
2276 if (file->flags & FILE_BUSY) {
2277 printf("recursive scan (%s)?\n", name);
2278 exit(1);
2279 }
2280 if (file->flags & FILE_SCANNED) {
2281 printf("file %s already scanned?\n", name);
2282 exit(1);
2283 }
2284 file->flags |= FILE_BUSY;
2285 file->lineno = 1;
2286 file->parent = current_file;
2287 current_file = file;
2288}
2289
2290static void zconf_endfile(void)
2291{
2292 struct buffer *parent;
2293
2294 current_file->flags |= FILE_SCANNED;
2295 current_file->flags &= ~FILE_BUSY;
2296 current_file = current_file->parent;
2297
2298 parent = current_buf->parent;
2299 if (parent) {
2300 fclose(zconfin);
2301 zconf_delete_buffer(YY_CURRENT_BUFFER);
2302 zconf_switch_to_buffer(parent->state);
2303 }
2304 free(current_buf);
2305 current_buf = parent;
2306}
2307
2308int zconf_lineno(void)
2309{
2310 return current_pos.lineno;
2311}
2312
2313char *zconf_curname(void)
2314{
2315 return current_pos.file ? current_pos.file->name : "<none>";
2316}
2317
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
new file mode 100644
index 000000000..527f60c99
--- /dev/null
+++ b/scripts/kconfig/lkc.h
@@ -0,0 +1,147 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#ifndef LKC_H
7#define LKC_H
8
9#include "expr.h"
10
11#ifndef KBUILD_NO_NLS
12# include <libintl.h>
13#else
14# define gettext(Msgid) ((const char *) (Msgid))
15# define textdomain(Domainname) ((const char *) (Domainname))
16# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
17#endif
18
19#ifdef __cplusplus
20extern "C" {
21#endif
22
23#ifdef LKC_DIRECT_LINK
24#define P(name,type,arg) extern type name arg
25#else
26#include "lkc_defs.h"
27#define P(name,type,arg) extern type (*name ## _p) arg
28#endif
29#include "lkc_proto.h"
30#undef P
31
32#define SRCTREE "srctree"
33
34#define PACKAGE "linux"
35#define LOCALEDIR "/usr/share/locale"
36
37#define _(text) gettext(text)
38#define N_(text) (text)
39
40
41#define TF_COMMAND 0x0001
42#define TF_PARAM 0x0002
43
44struct kconf_id {
45 int name;
46 int token;
47 unsigned int flags;
48 enum symbol_type stype;
49};
50
51int zconfparse(void);
52void zconfdump(FILE *out);
53
54extern int zconfdebug;
55void zconf_starthelp(void);
56FILE *zconf_fopen(const char *name);
57void zconf_initscan(const char *name);
58void zconf_nextfile(const char *name);
59int zconf_lineno(void);
60char *zconf_curname(void);
61
62/* confdata.c */
63extern const char conf_def_filename[];
64
65char *conf_get_default_confname(void);
66
67/* kconfig_load.c */
68void kconfig_load(void);
69
70/* menu.c */
71void menu_init(void);
72struct menu *menu_add_menu(void);
73void menu_end_menu(void);
74void menu_add_entry(struct symbol *sym);
75void menu_end_entry(void);
76void menu_add_dep(struct expr *dep);
77struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
78struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
79void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
80void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
81void menu_finalize(struct menu *parent);
82void menu_set_type(int type);
83
84/* util.c */
85struct file *file_lookup(const char *name);
86int file_write_dep(const char *name);
87
88struct gstr {
89 size_t len;
90 char *s;
91};
92struct gstr str_new(void);
93struct gstr str_assign(const char *s);
94void str_free(struct gstr *gs);
95void str_append(struct gstr *gs, const char *s);
96void str_printf(struct gstr *gs, const char *fmt, ...);
97const char *str_get(struct gstr *gs);
98
99/* symbol.c */
100void sym_init(void);
101void sym_clear_all_valid(void);
102void sym_set_changed(struct symbol *sym);
103struct symbol *sym_check_deps(struct symbol *sym);
104struct property *prop_alloc(enum prop_type type, struct symbol *sym);
105struct symbol *prop_get_symbol(struct property *prop);
106
107static inline tristate sym_get_tristate_value(struct symbol *sym)
108{
109 return sym->curr.tri;
110}
111
112
113static inline struct symbol *sym_get_choice_value(struct symbol *sym)
114{
115 return (struct symbol *)sym->curr.val;
116}
117
118static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
119{
120 return sym_set_tristate_value(chval, yes);
121}
122
123static inline bool sym_is_choice(struct symbol *sym)
124{
125 return sym->flags & SYMBOL_CHOICE ? true : false;
126}
127
128static inline bool sym_is_choice_value(struct symbol *sym)
129{
130 return sym->flags & SYMBOL_CHOICEVAL ? true : false;
131}
132
133static inline bool sym_is_optional(struct symbol *sym)
134{
135 return sym->flags & SYMBOL_OPTIONAL ? true : false;
136}
137
138static inline bool sym_has_value(struct symbol *sym)
139{
140 return sym->flags & SYMBOL_NEW ? false : true;
141}
142
143#ifdef __cplusplus
144}
145#endif
146
147#endif /* LKC_H */
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
new file mode 100644
index 000000000..b6a389c5f
--- /dev/null
+++ b/scripts/kconfig/lkc_proto.h
@@ -0,0 +1,41 @@
1
2/* confdata.c */
3P(conf_parse,void,(const char *name));
4P(conf_read,int,(const char *name));
5P(conf_read_simple,int,(const char *name));
6P(conf_write,int,(const char *name));
7
8/* menu.c */
9P(rootmenu,struct menu,);
10
11P(menu_is_visible,bool,(struct menu *menu));
12P(menu_get_prompt,const char *,(struct menu *menu));
13P(menu_get_root_menu,struct menu *,(struct menu *menu));
14P(menu_get_parent_menu,struct menu *,(struct menu *menu));
15
16/* symbol.c */
17P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
18P(sym_change_count,int,);
19
20P(sym_lookup,struct symbol *,(const char *name, int isconst));
21P(sym_find,struct symbol *,(const char *name));
22P(sym_re_search,struct symbol **,(const char *pattern));
23P(sym_type_name,const char *,(enum symbol_type type));
24P(sym_calc_value,void,(struct symbol *sym));
25P(sym_get_type,enum symbol_type,(struct symbol *sym));
26P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
27P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
28P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
29P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
30P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
31P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
32P(sym_is_changable,bool,(struct symbol *sym));
33P(sym_get_choice_prop,struct property *,(struct symbol *sym));
34P(sym_get_default_prop,struct property *,(struct symbol *sym));
35P(sym_get_string_value,const char *,(struct symbol *sym));
36
37P(prop_get_type_name,const char *,(enum prop_type type));
38
39/* expr.c */
40P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
41P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken));
diff --git a/scripts/kconfig/lxdialog/BIG.FAT.WARNING b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
new file mode 100644
index 000000000..a8999d82b
--- /dev/null
+++ b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
@@ -0,0 +1,4 @@
1This is NOT the official version of dialog. This version has been
2significantly modified from the original. It is for use by the Linux
3kernel configuration script. Please do not bother Savio Lam with
4questions about this program.
diff --git a/scripts/kconfig/lxdialog/Makefile b/scripts/kconfig/lxdialog/Makefile
new file mode 100644
index 000000000..a8b026326
--- /dev/null
+++ b/scripts/kconfig/lxdialog/Makefile
@@ -0,0 +1,21 @@
1# Makefile to build lxdialog package
2#
3
4check-lxdialog := $(srctree)/$(src)/check-lxdialog.sh
5
6# Use reursively expanded variables so we do not call gcc unless
7# we really need to do so. (Do not call gcc as part of make mrproper)
8HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
9HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
10
11HOST_EXTRACFLAGS += -DLOCALE
12
13PHONY += dochecklxdialog
14$(obj)/dochecklxdialog:
15 $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES)
16
17hostprogs-y := lxdialog
18always := $(hostprogs-y) dochecklxdialog
19
20lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
21 util.o lxdialog.o msgbox.o
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
new file mode 100644
index 000000000..120d624e6
--- /dev/null
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -0,0 +1,84 @@
1#!/bin/sh
2# Check ncurses compatibility
3
4# What library to link
5ldflags()
6{
7 $cc -print-file-name=libncursesw.so | grep -q /
8 if [ $? -eq 0 ]; then
9 echo '-lncursesw'
10 exit
11 fi
12 $cc -print-file-name=libncurses.so | grep -q /
13 if [ $? -eq 0 ]; then
14 echo '-lncurses'
15 exit
16 fi
17 $cc -print-file-name=libcurses.so | grep -q /
18 if [ $? -eq 0 ]; then
19 echo '-lcurses'
20 exit
21 fi
22 exit 1
23}
24
25# Where is ncurses.h?
26ccflags()
27{
28 if [ -f /usr/include/ncurses/ncurses.h ]; then
29 echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
30 elif [ -f /usr/include/ncurses/curses.h ]; then
31 echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
32 elif [ -f /usr/include/ncurses.h ]; then
33 echo '-DCURSES_LOC="<ncurses.h>"'
34 else
35 echo '-DCURSES_LOC="<curses.h>"'
36 fi
37}
38
39# Temp file, try to clean up after us
40tmp=.lxdialog.tmp
41trap "rm -f $tmp" 0 1 2 3 15
42
43# Check if we can link to ncurses
44check() {
45 echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null
46 if [ $? != 0 ]; then
47 echo " *** Unable to find the ncurses libraries." 1>&2
48 echo " *** make menuconfig require the ncurses libraries" 1>&2
49 echo " *** " 1>&2
50 echo " *** Install ncurses (ncurses-devel) and try again" 1>&2
51 echo " *** " 1>&2
52 exit 1
53 fi
54}
55
56usage() {
57 printf "Usage: $0 [-check compiler options|-header|-library]\n"
58}
59
60if [ $# == 0 ]; then
61 usage
62 exit 1
63fi
64
65cc=""
66case "$1" in
67 "-check")
68 shift
69 cc="$@"
70 check
71 ;;
72 "-ccflags")
73 ccflags
74 ;;
75 "-ldflags")
76 shift
77 cc="$@"
78 ldflags
79 ;;
80 "*")
81 usage
82 exit 1
83 ;;
84esac
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
new file mode 100644
index 000000000..be0200e9c
--- /dev/null
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -0,0 +1,333 @@
1/*
2 * checklist.c -- implements the checklist box
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
6 * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
7 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include "dialog.h"
25
26static int list_width, check_x, item_x;
27
28/*
29 * Print list item
30 */
31static void print_item(WINDOW * win, const char *item, int status, int choice,
32 int selected)
33{
34 int i;
35
36 /* Clear 'residue' of last item */
37 wattrset(win, menubox_attr);
38 wmove(win, choice, 0);
39 for (i = 0; i < list_width; i++)
40 waddch(win, ' ');
41
42 wmove(win, choice, check_x);
43 wattrset(win, selected ? check_selected_attr : check_attr);
44 wprintw(win, "(%c)", status ? 'X' : ' ');
45
46 wattrset(win, selected ? tag_selected_attr : tag_attr);
47 mvwaddch(win, choice, item_x, item[0]);
48 wattrset(win, selected ? item_selected_attr : item_attr);
49 waddstr(win, (char *)item + 1);
50 if (selected) {
51 wmove(win, choice, check_x + 1);
52 wrefresh(win);
53 }
54}
55
56/*
57 * Print the scroll indicators.
58 */
59static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
60 int y, int x, int height)
61{
62 wmove(win, y, x);
63
64 if (scroll > 0) {
65 wattrset(win, uarrow_attr);
66 waddch(win, ACS_UARROW);
67 waddstr(win, "(-)");
68 } else {
69 wattrset(win, menubox_attr);
70 waddch(win, ACS_HLINE);
71 waddch(win, ACS_HLINE);
72 waddch(win, ACS_HLINE);
73 waddch(win, ACS_HLINE);
74 }
75
76 y = y + height + 1;
77 wmove(win, y, x);
78
79 if ((height < item_no) && (scroll + choice < item_no - 1)) {
80 wattrset(win, darrow_attr);
81 waddch(win, ACS_DARROW);
82 waddstr(win, "(+)");
83 } else {
84 wattrset(win, menubox_border_attr);
85 waddch(win, ACS_HLINE);
86 waddch(win, ACS_HLINE);
87 waddch(win, ACS_HLINE);
88 waddch(win, ACS_HLINE);
89 }
90}
91
92/*
93 * Display the termination buttons
94 */
95static void print_buttons(WINDOW * dialog, int height, int width, int selected)
96{
97 int x = width / 2 - 11;
98 int y = height - 2;
99
100 print_button(dialog, "Select", y, x, selected == 0);
101 print_button(dialog, " Help ", y, x + 14, selected == 1);
102
103 wmove(dialog, y, x + 1 + 14 * selected);
104 wrefresh(dialog);
105}
106
107/*
108 * Display a dialog box with a list of options that can be turned on or off
109 * in the style of radiolist (only one option turned on at a time).
110 */
111int dialog_checklist(const char *title, const char *prompt, int height,
112 int width, int list_height, int item_no,
113 const char *const *items)
114{
115 int i, x, y, box_x, box_y;
116 int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
117 WINDOW *dialog, *list;
118
119 /* Allocate space for storing item on/off status */
120 if ((status = malloc(sizeof(int) * item_no)) == NULL) {
121 endwin();
122 fprintf(stderr,
123 "\nCan't allocate memory in dialog_checklist().\n");
124 exit(-1);
125 }
126
127 /* Initializes status */
128 for (i = 0; i < item_no; i++) {
129 status[i] = !strcasecmp(items[i * 3 + 2], "on");
130 if ((!choice && status[i])
131 || !strcasecmp(items[i * 3 + 2], "selected"))
132 choice = i + 1;
133 }
134 if (choice)
135 choice--;
136
137 max_choice = MIN(list_height, item_no);
138
139 /* center dialog box on screen */
140 x = (COLS - width) / 2;
141 y = (LINES - height) / 2;
142
143 draw_shadow(stdscr, y, x, height, width);
144
145 dialog = newwin(height, width, y, x);
146 keypad(dialog, TRUE);
147
148 draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
149 wattrset(dialog, border_attr);
150 mvwaddch(dialog, height - 3, 0, ACS_LTEE);
151 for (i = 0; i < width - 2; i++)
152 waddch(dialog, ACS_HLINE);
153 wattrset(dialog, dialog_attr);
154 waddch(dialog, ACS_RTEE);
155
156 print_title(dialog, title, width);
157
158 wattrset(dialog, dialog_attr);
159 print_autowrap(dialog, prompt, width - 2, 1, 3);
160
161 list_width = width - 6;
162 box_y = height - list_height - 5;
163 box_x = (width - list_width) / 2 - 1;
164
165 /* create new window for the list */
166 list = subwin(dialog, list_height, list_width, y + box_y + 1,
167 x + box_x + 1);
168
169 keypad(list, TRUE);
170
171 /* draw a box around the list items */
172 draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
173 menubox_border_attr, menubox_attr);
174
175 /* Find length of longest item in order to center checklist */
176 check_x = 0;
177 for (i = 0; i < item_no; i++)
178 check_x = MAX(check_x, +strlen(items[i * 3 + 1]) + 4);
179
180 check_x = (list_width - check_x) / 2;
181 item_x = check_x + 4;
182
183 if (choice >= list_height) {
184 scroll = choice - list_height + 1;
185 choice -= scroll;
186 }
187
188 /* Print the list */
189 for (i = 0; i < max_choice; i++) {
190 print_item(list, items[(scroll + i) * 3 + 1],
191 status[i + scroll], i, i == choice);
192 }
193
194 print_arrows(dialog, choice, item_no, scroll,
195 box_y, box_x + check_x + 5, list_height);
196
197 print_buttons(dialog, height, width, 0);
198
199 wnoutrefresh(dialog);
200 wnoutrefresh(list);
201 doupdate();
202
203 while (key != ESC) {
204 key = wgetch(dialog);
205
206 for (i = 0; i < max_choice; i++)
207 if (toupper(key) ==
208 toupper(items[(scroll + i) * 3 + 1][0]))
209 break;
210
211 if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
212 key == '+' || key == '-') {
213 if (key == KEY_UP || key == '-') {
214 if (!choice) {
215 if (!scroll)
216 continue;
217 /* Scroll list down */
218 if (list_height > 1) {
219 /* De-highlight current first item */
220 print_item(list, items[scroll * 3 + 1],
221 status[scroll], 0, FALSE);
222 scrollok(list, TRUE);
223 wscrl(list, -1);
224 scrollok(list, FALSE);
225 }
226 scroll--;
227 print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE);
228 print_arrows(dialog, choice, item_no,
229 scroll, box_y, box_x + check_x + 5, list_height);
230
231 wnoutrefresh(dialog);
232 wrefresh(list);
233
234 continue; /* wait for another key press */
235 } else
236 i = choice - 1;
237 } else if (key == KEY_DOWN || key == '+') {
238 if (choice == max_choice - 1) {
239 if (scroll + choice >= item_no - 1)
240 continue;
241 /* Scroll list up */
242 if (list_height > 1) {
243 /* De-highlight current last item before scrolling up */
244 print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
245 status[scroll + max_choice - 1],
246 max_choice - 1, FALSE);
247 scrollok(list, TRUE);
248 wscrl(list, 1);
249 scrollok(list, FALSE);
250 }
251 scroll++;
252 print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
253 status[scroll + max_choice - 1], max_choice - 1, TRUE);
254
255 print_arrows(dialog, choice, item_no,
256 scroll, box_y, box_x + check_x + 5, list_height);
257
258 wnoutrefresh(dialog);
259 wrefresh(list);
260
261 continue; /* wait for another key press */
262 } else
263 i = choice + 1;
264 }
265 if (i != choice) {
266 /* De-highlight current item */
267 print_item(list, items[(scroll + choice) * 3 + 1],
268 status[scroll + choice], choice, FALSE);
269 /* Highlight new item */
270 choice = i;
271 print_item(list, items[(scroll + choice) * 3 + 1],
272 status[scroll + choice], choice, TRUE);
273 wnoutrefresh(dialog);
274 wrefresh(list);
275 }
276 continue; /* wait for another key press */
277 }
278 switch (key) {
279 case 'H':
280 case 'h':
281 case '?':
282 fprintf(stderr, "%s", items[(scroll + choice) * 3]);
283 delwin(dialog);
284 free(status);
285 return 1;
286 case TAB:
287 case KEY_LEFT:
288 case KEY_RIGHT:
289 button = ((key == KEY_LEFT ? --button : ++button) < 0)
290 ? 1 : (button > 1 ? 0 : button);
291
292 print_buttons(dialog, height, width, button);
293 wrefresh(dialog);
294 break;
295 case 'S':
296 case 's':
297 case ' ':
298 case '\n':
299 if (!button) {
300 if (!status[scroll + choice]) {
301 for (i = 0; i < item_no; i++)
302 status[i] = 0;
303 status[scroll + choice] = 1;
304 for (i = 0; i < max_choice; i++)
305 print_item(list, items[(scroll + i) * 3 + 1],
306 status[scroll + i], i, i == choice);
307 }
308 wnoutrefresh(dialog);
309 wrefresh(list);
310
311 for (i = 0; i < item_no; i++)
312 if (status[i])
313 fprintf(stderr, "%s", items[i * 3]);
314 } else
315 fprintf(stderr, "%s", items[(scroll + choice) * 3]);
316 delwin(dialog);
317 free(status);
318 return button;
319 case 'X':
320 case 'x':
321 key = ESC;
322 case ESC:
323 break;
324 }
325
326 /* Now, update everything... */
327 doupdate();
328 }
329
330 delwin(dialog);
331 free(status);
332 return -1; /* ESC pressed */
333}
diff --git a/scripts/kconfig/lxdialog/colors.h b/scripts/kconfig/lxdialog/colors.h
new file mode 100644
index 000000000..db071df12
--- /dev/null
+++ b/scripts/kconfig/lxdialog/colors.h
@@ -0,0 +1,154 @@
1/*
2 * colors.h -- color attribute definitions
3 *
4 * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21/*
22 * Default color definitions
23 *
24 * *_FG = foreground
25 * *_BG = background
26 * *_HL = highlight?
27 */
28#define SCREEN_FG COLOR_CYAN
29#define SCREEN_BG COLOR_BLUE
30#define SCREEN_HL TRUE
31
32#define SHADOW_FG COLOR_BLACK
33#define SHADOW_BG COLOR_BLACK
34#define SHADOW_HL TRUE
35
36#define DIALOG_FG COLOR_BLACK
37#define DIALOG_BG COLOR_WHITE
38#define DIALOG_HL FALSE
39
40#define TITLE_FG COLOR_YELLOW
41#define TITLE_BG COLOR_WHITE
42#define TITLE_HL TRUE
43
44#define BORDER_FG COLOR_WHITE
45#define BORDER_BG COLOR_WHITE
46#define BORDER_HL TRUE
47
48#define BUTTON_ACTIVE_FG COLOR_WHITE
49#define BUTTON_ACTIVE_BG COLOR_BLUE
50#define BUTTON_ACTIVE_HL TRUE
51
52#define BUTTON_INACTIVE_FG COLOR_BLACK
53#define BUTTON_INACTIVE_BG COLOR_WHITE
54#define BUTTON_INACTIVE_HL FALSE
55
56#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
57#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
58#define BUTTON_KEY_ACTIVE_HL TRUE
59
60#define BUTTON_KEY_INACTIVE_FG COLOR_RED
61#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
62#define BUTTON_KEY_INACTIVE_HL FALSE
63
64#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
65#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
66#define BUTTON_LABEL_ACTIVE_HL TRUE
67
68#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
69#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
70#define BUTTON_LABEL_INACTIVE_HL TRUE
71
72#define INPUTBOX_FG COLOR_BLACK
73#define INPUTBOX_BG COLOR_WHITE
74#define INPUTBOX_HL FALSE
75
76#define INPUTBOX_BORDER_FG COLOR_BLACK
77#define INPUTBOX_BORDER_BG COLOR_WHITE
78#define INPUTBOX_BORDER_HL FALSE
79
80#define SEARCHBOX_FG COLOR_BLACK
81#define SEARCHBOX_BG COLOR_WHITE
82#define SEARCHBOX_HL FALSE
83
84#define SEARCHBOX_TITLE_FG COLOR_YELLOW
85#define SEARCHBOX_TITLE_BG COLOR_WHITE
86#define SEARCHBOX_TITLE_HL TRUE
87
88#define SEARCHBOX_BORDER_FG COLOR_WHITE
89#define SEARCHBOX_BORDER_BG COLOR_WHITE
90#define SEARCHBOX_BORDER_HL TRUE
91
92#define POSITION_INDICATOR_FG COLOR_YELLOW
93#define POSITION_INDICATOR_BG COLOR_WHITE
94#define POSITION_INDICATOR_HL TRUE
95
96#define MENUBOX_FG COLOR_BLACK
97#define MENUBOX_BG COLOR_WHITE
98#define MENUBOX_HL FALSE
99
100#define MENUBOX_BORDER_FG COLOR_WHITE
101#define MENUBOX_BORDER_BG COLOR_WHITE
102#define MENUBOX_BORDER_HL TRUE
103
104#define ITEM_FG COLOR_BLACK
105#define ITEM_BG COLOR_WHITE
106#define ITEM_HL FALSE
107
108#define ITEM_SELECTED_FG COLOR_WHITE
109#define ITEM_SELECTED_BG COLOR_BLUE
110#define ITEM_SELECTED_HL TRUE
111
112#define TAG_FG COLOR_YELLOW
113#define TAG_BG COLOR_WHITE
114#define TAG_HL TRUE
115
116#define TAG_SELECTED_FG COLOR_YELLOW
117#define TAG_SELECTED_BG COLOR_BLUE
118#define TAG_SELECTED_HL TRUE
119
120#define TAG_KEY_FG COLOR_YELLOW
121#define TAG_KEY_BG COLOR_WHITE
122#define TAG_KEY_HL TRUE
123
124#define TAG_KEY_SELECTED_FG COLOR_YELLOW
125#define TAG_KEY_SELECTED_BG COLOR_BLUE
126#define TAG_KEY_SELECTED_HL TRUE
127
128#define CHECK_FG COLOR_BLACK
129#define CHECK_BG COLOR_WHITE
130#define CHECK_HL FALSE
131
132#define CHECK_SELECTED_FG COLOR_WHITE
133#define CHECK_SELECTED_BG COLOR_BLUE
134#define CHECK_SELECTED_HL TRUE
135
136#define UARROW_FG COLOR_GREEN
137#define UARROW_BG COLOR_WHITE
138#define UARROW_HL TRUE
139
140#define DARROW_FG COLOR_GREEN
141#define DARROW_BG COLOR_WHITE
142#define DARROW_HL TRUE
143
144/* End of default color definitions */
145
146#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
147#define COLOR_NAME_LEN 10
148#define COLOR_COUNT 8
149
150/*
151 * Global variables
152 */
153
154extern int color_table[][3];
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
new file mode 100644
index 000000000..af3cf716e
--- /dev/null
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -0,0 +1,177 @@
1/*
2 * dialog.h -- common declarations for all dialog modules
3 *
4 * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <sys/types.h>
22#include <fcntl.h>
23#include <unistd.h>
24#include <ctype.h>
25#include <stdlib.h>
26#include <string.h>
27
28#ifdef __sun__
29#define CURS_MACROS
30#endif
31#include CURSES_LOC
32
33/*
34 * Colors in ncurses 1.9.9e do not work properly since foreground and
35 * background colors are OR'd rather than separately masked. This version
36 * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
37 * with standard curses. The simplest fix (to make this work with standard
38 * curses) uses the wbkgdset() function, not used in the original hack.
39 * Turn it off if we're building with 1.9.9e, since it just confuses things.
40 */
41#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
42#define OLD_NCURSES 1
43#undef wbkgdset
44#define wbkgdset(w,p) /*nothing */
45#else
46#define OLD_NCURSES 0
47#endif
48
49#define TR(params) _tracef params
50
51#define ESC 27
52#define TAB 9
53#define MAX_LEN 2048
54#define BUF_SIZE (10*1024)
55#define MIN(x,y) (x < y ? x : y)
56#define MAX(x,y) (x > y ? x : y)
57
58#ifndef ACS_ULCORNER
59#define ACS_ULCORNER '+'
60#endif
61#ifndef ACS_LLCORNER
62#define ACS_LLCORNER '+'
63#endif
64#ifndef ACS_URCORNER
65#define ACS_URCORNER '+'
66#endif
67#ifndef ACS_LRCORNER
68#define ACS_LRCORNER '+'
69#endif
70#ifndef ACS_HLINE
71#define ACS_HLINE '-'
72#endif
73#ifndef ACS_VLINE
74#define ACS_VLINE '|'
75#endif
76#ifndef ACS_LTEE
77#define ACS_LTEE '+'
78#endif
79#ifndef ACS_RTEE
80#define ACS_RTEE '+'
81#endif
82#ifndef ACS_UARROW
83#define ACS_UARROW '^'
84#endif
85#ifndef ACS_DARROW
86#define ACS_DARROW 'v'
87#endif
88
89/*
90 * Attribute names
91 */
92#define screen_attr attributes[0]
93#define shadow_attr attributes[1]
94#define dialog_attr attributes[2]
95#define title_attr attributes[3]
96#define border_attr attributes[4]
97#define button_active_attr attributes[5]
98#define button_inactive_attr attributes[6]
99#define button_key_active_attr attributes[7]
100#define button_key_inactive_attr attributes[8]
101#define button_label_active_attr attributes[9]
102#define button_label_inactive_attr attributes[10]
103#define inputbox_attr attributes[11]
104#define inputbox_border_attr attributes[12]
105#define searchbox_attr attributes[13]
106#define searchbox_title_attr attributes[14]
107#define searchbox_border_attr attributes[15]
108#define position_indicator_attr attributes[16]
109#define menubox_attr attributes[17]
110#define menubox_border_attr attributes[18]
111#define item_attr attributes[19]
112#define item_selected_attr attributes[20]
113#define tag_attr attributes[21]
114#define tag_selected_attr attributes[22]
115#define tag_key_attr attributes[23]
116#define tag_key_selected_attr attributes[24]
117#define check_attr attributes[25]
118#define check_selected_attr attributes[26]
119#define uarrow_attr attributes[27]
120#define darrow_attr attributes[28]
121
122/* number of attributes */
123#define ATTRIBUTE_COUNT 29
124
125/*
126 * Global variables
127 */
128extern bool use_colors;
129extern bool use_shadow;
130
131extern chtype attributes[];
132
133extern const char *backtitle;
134
135/*
136 * Function prototypes
137 */
138extern void create_rc(const char *filename);
139extern int parse_rc(void);
140
141void init_dialog(void);
142void end_dialog(void);
143void attr_clear(WINDOW * win, int height, int width, chtype attr);
144void dialog_clear(void);
145void color_setup(void);
146void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x);
147void print_button(WINDOW * win, const char *label, int y, int x, int selected);
148void print_title(WINDOW *dialog, const char *title, int width);
149void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box,
150 chtype border);
151void draw_shadow(WINDOW * win, int y, int x, int height, int width);
152
153int first_alpha(const char *string, const char *exempt);
154int dialog_yesno(const char *title, const char *prompt, int height, int width);
155int dialog_msgbox(const char *title, const char *prompt, int height,
156 int width, int pause);
157int dialog_textbox(const char *title, const char *file, int height, int width);
158int dialog_menu(const char *title, const char *prompt, int height, int width,
159 int menu_height, const char *choice, int item_no,
160 const char *const *items);
161int dialog_checklist(const char *title, const char *prompt, int height,
162 int width, int list_height, int item_no,
163 const char *const *items);
164extern char dialog_input_result[];
165int dialog_inputbox(const char *title, const char *prompt, int height,
166 int width, const char *init);
167
168/*
169 * This is the base for fictitious keys, which activate
170 * the buttons.
171 *
172 * Mouse-generated keys are the following:
173 * -- the first 32 are used as numbers, in addition to '0'-'9'
174 * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
175 * -- uppercase chars are used to invoke the button (M_EVENT + 'O')
176 */
177#define M_EVENT (KEY_MAX+1)
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
new file mode 100644
index 000000000..779503726
--- /dev/null
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -0,0 +1,224 @@
1/*
2 * inputbox.c -- implements the input box
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "dialog.h"
23
24char dialog_input_result[MAX_LEN + 1];
25
26/*
27 * Print the termination buttons
28 */
29static void print_buttons(WINDOW * dialog, int height, int width, int selected)
30{
31 int x = width / 2 - 11;
32 int y = height - 2;
33
34 print_button(dialog, " Ok ", y, x, selected == 0);
35 print_button(dialog, " Help ", y, x + 14, selected == 1);
36
37 wmove(dialog, y, x + 1 + 14 * selected);
38 wrefresh(dialog);
39}
40
41/*
42 * Display a dialog box for inputing a string
43 */
44int dialog_inputbox(const char *title, const char *prompt, int height, int width,
45 const char *init)
46{
47 int i, x, y, box_y, box_x, box_width;
48 int input_x = 0, scroll = 0, key = 0, button = -1;
49 char *instr = dialog_input_result;
50 WINDOW *dialog;
51
52 /* center dialog box on screen */
53 x = (COLS - width) / 2;
54 y = (LINES - height) / 2;
55
56 draw_shadow(stdscr, y, x, height, width);
57
58 dialog = newwin(height, width, y, x);
59 keypad(dialog, TRUE);
60
61 draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
62 wattrset(dialog, border_attr);
63 mvwaddch(dialog, height - 3, 0, ACS_LTEE);
64 for (i = 0; i < width - 2; i++)
65 waddch(dialog, ACS_HLINE);
66 wattrset(dialog, dialog_attr);
67 waddch(dialog, ACS_RTEE);
68
69 print_title(dialog, title, width);
70
71 wattrset(dialog, dialog_attr);
72 print_autowrap(dialog, prompt, width - 2, 1, 3);
73
74 /* Draw the input field box */
75 box_width = width - 6;
76 getyx(dialog, y, x);
77 box_y = y + 2;
78 box_x = (width - box_width) / 2;
79 draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, border_attr, dialog_attr);
80
81 print_buttons(dialog, height, width, 0);
82
83 /* Set up the initial value */
84 wmove(dialog, box_y, box_x);
85 wattrset(dialog, inputbox_attr);
86
87 if (!init)
88 instr[0] = '\0';
89 else
90 strcpy(instr, init);
91
92 input_x = strlen(instr);
93
94 if (input_x >= box_width) {
95 scroll = input_x - box_width + 1;
96 input_x = box_width - 1;
97 for (i = 0; i < box_width - 1; i++)
98 waddch(dialog, instr[scroll + i]);
99 } else {
100 waddstr(dialog, instr);
101 }
102
103 wmove(dialog, box_y, box_x + input_x);
104
105 wrefresh(dialog);
106
107 while (key != ESC) {
108 key = wgetch(dialog);
109
110 if (button == -1) { /* Input box selected */
111 switch (key) {
112 case TAB:
113 case KEY_UP:
114 case KEY_DOWN:
115 break;
116 case KEY_LEFT:
117 continue;
118 case KEY_RIGHT:
119 continue;
120 case KEY_BACKSPACE:
121 case 127:
122 if (input_x || scroll) {
123 wattrset(dialog, inputbox_attr);
124 if (!input_x) {
125 scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1);
126 wmove(dialog, box_y, box_x);
127 for (i = 0; i < box_width; i++)
128 waddch(dialog,
129 instr[scroll + input_x + i] ?
130 instr[scroll + input_x + i] : ' ');
131 input_x = strlen(instr) - scroll;
132 } else
133 input_x--;
134 instr[scroll + input_x] = '\0';
135 mvwaddch(dialog, box_y, input_x + box_x, ' ');
136 wmove(dialog, box_y, input_x + box_x);
137 wrefresh(dialog);
138 }
139 continue;
140 default:
141 if (key < 0x100 && isprint(key)) {
142 if (scroll + input_x < MAX_LEN) {
143 wattrset(dialog, inputbox_attr);
144 instr[scroll + input_x] = key;
145 instr[scroll + input_x + 1] = '\0';
146 if (input_x == box_width - 1) {
147 scroll++;
148 wmove(dialog, box_y, box_x);
149 for (i = 0; i < box_width - 1; i++)
150 waddch(dialog, instr [scroll + i]);
151 } else {
152 wmove(dialog, box_y, input_x++ + box_x);
153 waddch(dialog, key);
154 }
155 wrefresh(dialog);
156 } else
157 flash(); /* Alarm user about overflow */
158 continue;
159 }
160 }
161 }
162 switch (key) {
163 case 'O':
164 case 'o':
165 delwin(dialog);
166 return 0;
167 case 'H':
168 case 'h':
169 delwin(dialog);
170 return 1;
171 case KEY_UP:
172 case KEY_LEFT:
173 switch (button) {
174 case -1:
175 button = 1; /* Indicates "Cancel" button is selected */
176 print_buttons(dialog, height, width, 1);
177 break;
178 case 0:
179 button = -1; /* Indicates input box is selected */
180 print_buttons(dialog, height, width, 0);
181 wmove(dialog, box_y, box_x + input_x);
182 wrefresh(dialog);
183 break;
184 case 1:
185 button = 0; /* Indicates "OK" button is selected */
186 print_buttons(dialog, height, width, 0);
187 break;
188 }
189 break;
190 case TAB:
191 case KEY_DOWN:
192 case KEY_RIGHT:
193 switch (button) {
194 case -1:
195 button = 0; /* Indicates "OK" button is selected */
196 print_buttons(dialog, height, width, 0);
197 break;
198 case 0:
199 button = 1; /* Indicates "Cancel" button is selected */
200 print_buttons(dialog, height, width, 1);
201 break;
202 case 1:
203 button = -1; /* Indicates input box is selected */
204 print_buttons(dialog, height, width, 0);
205 wmove(dialog, box_y, box_x + input_x);
206 wrefresh(dialog);
207 break;
208 }
209 break;
210 case ' ':
211 case '\n':
212 delwin(dialog);
213 return (button == -1 ? 0 : button);
214 case 'X':
215 case 'x':
216 key = ESC;
217 case ESC:
218 break;
219 }
220 }
221
222 delwin(dialog);
223 return -1; /* ESC pressed */
224}
diff --git a/scripts/kconfig/lxdialog/lxdialog.c b/scripts/kconfig/lxdialog/lxdialog.c
new file mode 100644
index 000000000..79f6c5fb5
--- /dev/null
+++ b/scripts/kconfig/lxdialog/lxdialog.c
@@ -0,0 +1,204 @@
1/*
2 * dialog - Display simple dialog boxes from shell scripts
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "dialog.h"
23
24static void Usage(const char *name);
25
26typedef int (jumperFn) (const char *title, int argc, const char *const *argv);
27
28struct Mode {
29 char *name;
30 int argmin, argmax, argmod;
31 jumperFn *jumper;
32};
33
34jumperFn j_menu, j_radiolist, j_yesno, j_textbox, j_inputbox;
35jumperFn j_msgbox, j_infobox;
36
37static struct Mode modes[] = {
38 {"--menu", 9, 0, 3, j_menu},
39 {"--radiolist", 9, 0, 3, j_radiolist},
40 {"--yesno", 5, 5, 1, j_yesno},
41 {"--textbox", 5, 5, 1, j_textbox},
42 {"--inputbox", 5, 6, 1, j_inputbox},
43 {"--msgbox", 5, 5, 1, j_msgbox},
44 {"--infobox", 5, 5, 1, j_infobox},
45 {NULL, 0, 0, 0, NULL}
46};
47
48static struct Mode *modePtr;
49
50#ifdef LOCALE
51#include <locale.h>
52#endif
53
54int main(int argc, const char *const *argv)
55{
56 int offset = 0, opt_clear = 0, end_common_opts = 0, retval;
57 const char *title = NULL;
58
59#ifdef LOCALE
60 (void)setlocale(LC_ALL, "");
61#endif
62
63#ifdef TRACE
64 trace(TRACE_CALLS | TRACE_UPDATE);
65#endif
66 if (argc < 2) {
67 Usage(argv[0]);
68 exit(-1);
69 }
70
71 while (offset < argc - 1 && !end_common_opts) { /* Common options */
72 if (!strcmp(argv[offset + 1], "--title")) {
73 if (argc - offset < 3 || title != NULL) {
74 Usage(argv[0]);
75 exit(-1);
76 } else {
77 title = argv[offset + 2];
78 offset += 2;
79 }
80 } else if (!strcmp(argv[offset + 1], "--backtitle")) {
81 if (backtitle != NULL) {
82 Usage(argv[0]);
83 exit(-1);
84 } else {
85 backtitle = argv[offset + 2];
86 offset += 2;
87 }
88 } else if (!strcmp(argv[offset + 1], "--clear")) {
89 if (opt_clear) { /* Hey, "--clear" can't appear twice! */
90 Usage(argv[0]);
91 exit(-1);
92 } else if (argc == 2) { /* we only want to clear the screen */
93 init_dialog();
94 refresh(); /* init_dialog() will clear the screen for us */
95 end_dialog();
96 return 0;
97 } else {
98 opt_clear = 1;
99 offset++;
100 }
101 } else /* no more common options */
102 end_common_opts = 1;
103 }
104
105 if (argc - 1 == offset) { /* no more options */
106 Usage(argv[0]);
107 exit(-1);
108 }
109 /* use a table to look for the requested mode, to avoid code duplication */
110
111 for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
112 if (!strcmp(argv[offset + 1], modePtr->name))
113 break;
114
115 if (!modePtr->name)
116 Usage(argv[0]);
117 if (argc - offset < modePtr->argmin)
118 Usage(argv[0]);
119 if (modePtr->argmax && argc - offset > modePtr->argmax)
120 Usage(argv[0]);
121
122 init_dialog();
123 retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
124
125 if (opt_clear) { /* clear screen before exit */
126 attr_clear(stdscr, LINES, COLS, screen_attr);
127 refresh();
128 }
129 end_dialog();
130
131 exit(retval);
132}
133
134/*
135 * Print program usage
136 */
137static void Usage(const char *name)
138{
139 fprintf(stderr, "\
140\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
141\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
142\n modified/gutted for use as a Linux kernel config tool by \
143\n William Roadcap (roadcapw@cfw.com)\
144\n\
145\n* Display dialog boxes from shell scripts *\
146\n\
147\nUsage: %s --clear\
148\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
149\n\
150\nBox options:\
151\n\
152\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
153\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
154\n --textbox <file> <height> <width>\
155\n --inputbox <text> <height> <width> [<init>]\
156\n --yesno <text> <height> <width>\
157\n", name, name);
158 exit(-1);
159}
160
161/*
162 * These are the program jumpers
163 */
164
165int j_menu(const char *t, int ac, const char *const *av)
166{
167 return dialog_menu(t, av[2], atoi(av[3]), atoi(av[4]),
168 atoi(av[5]), av[6], (ac - 6) / 2, av + 7);
169}
170
171int j_radiolist(const char *t, int ac, const char *const *av)
172{
173 return dialog_checklist(t, av[2], atoi(av[3]), atoi(av[4]),
174 atoi(av[5]), (ac - 6) / 3, av + 6);
175}
176
177int j_textbox(const char *t, int ac, const char *const *av)
178{
179 return dialog_textbox(t, av[2], atoi(av[3]), atoi(av[4]));
180}
181
182int j_yesno(const char *t, int ac, const char *const *av)
183{
184 return dialog_yesno(t, av[2], atoi(av[3]), atoi(av[4]));
185}
186
187int j_inputbox(const char *t, int ac, const char *const *av)
188{
189 int ret = dialog_inputbox(t, av[2], atoi(av[3]), atoi(av[4]),
190 ac == 6 ? av[5] : (char *)NULL);
191 if (ret == 0)
192 fprintf(stderr, dialog_input_result);
193 return ret;
194}
195
196int j_msgbox(const char *t, int ac, const char *const *av)
197{
198 return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 1);
199}
200
201int j_infobox(const char *t, int ac, const char *const *av)
202{
203 return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 0);
204}
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
new file mode 100644
index 000000000..bf8052f4f
--- /dev/null
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -0,0 +1,426 @@
1/*
2 * menubox.c -- implements the menu box
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22/*
23 * Changes by Clifford Wolf (god@clifford.at)
24 *
25 * [ 1998-06-13 ]
26 *
27 * *) A bugfix for the Page-Down problem
28 *
29 * *) Formerly when I used Page Down and Page Up, the cursor would be set
30 * to the first position in the menu box. Now lxdialog is a bit
31 * smarter and works more like other menu systems (just have a look at
32 * it).
33 *
34 * *) Formerly if I selected something my scrolling would be broken because
35 * lxdialog is re-invoked by the Menuconfig shell script, can't
36 * remember the last scrolling position, and just sets it so that the
37 * cursor is at the bottom of the box. Now it writes the temporary file
38 * lxdialog.scrltmp which contains this information. The file is
39 * deleted by lxdialog if the user leaves a submenu or enters a new
40 * one, but it would be nice if Menuconfig could make another "rm -f"
41 * just to be sure. Just try it out - you will recognise a difference!
42 *
43 * [ 1998-06-14 ]
44 *
45 * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
46 * and menus change their size on the fly.
47 *
48 * *) If for some reason the last scrolling position is not saved by
49 * lxdialog, it sets the scrolling so that the selected item is in the
50 * middle of the menu box, not at the bottom.
51 *
52 * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
53 * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
54 * This fixes a bug in Menuconfig where using ' ' to descend into menus
55 * would leave mis-synchronized lxdialog.scrltmp files lying around,
56 * fscanf would read in 'scroll', and eventually that value would get used.
57 */
58
59#include "dialog.h"
60
61static int menu_width, item_x;
62
63/*
64 * Print menu item
65 */
66static void do_print_item(WINDOW * win, const char *item, int choice,
67 int selected, int hotkey)
68{
69 int j;
70 char *menu_item = malloc(menu_width + 1);
71
72 strncpy(menu_item, item, menu_width - item_x);
73 menu_item[menu_width] = 0;
74 j = first_alpha(menu_item, "YyNnMmHh");
75
76 /* Clear 'residue' of last item */
77 wattrset(win, menubox_attr);
78 wmove(win, choice, 0);
79#if OLD_NCURSES
80 {
81 int i;
82 for (i = 0; i < menu_width; i++)
83 waddch(win, ' ');
84 }
85#else
86 wclrtoeol(win);
87#endif
88 wattrset(win, selected ? item_selected_attr : item_attr);
89 mvwaddstr(win, choice, item_x, menu_item);
90 if (hotkey) {
91 wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
92 mvwaddch(win, choice, item_x + j, menu_item[j]);
93 }
94 if (selected) {
95 wmove(win, choice, item_x + 1);
96 }
97 free(menu_item);
98 wrefresh(win);
99}
100
101#define print_item(index, choice, selected) \
102do {\
103 int hotkey = (items[(index) * 2][0] != ':'); \
104 do_print_item(menu, items[(index) * 2 + 1], choice, selected, hotkey); \
105} while (0)
106
107/*
108 * Print the scroll indicators.
109 */
110static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
111 int height)
112{
113 int cur_y, cur_x;
114
115 getyx(win, cur_y, cur_x);
116
117 wmove(win, y, x);
118
119 if (scroll > 0) {
120 wattrset(win, uarrow_attr);
121 waddch(win, ACS_UARROW);
122 waddstr(win, "(-)");
123 } else {
124 wattrset(win, menubox_attr);
125 waddch(win, ACS_HLINE);
126 waddch(win, ACS_HLINE);
127 waddch(win, ACS_HLINE);
128 waddch(win, ACS_HLINE);
129 }
130
131 y = y + height + 1;
132 wmove(win, y, x);
133 wrefresh(win);
134
135 if ((height < item_no) && (scroll + height < item_no)) {
136 wattrset(win, darrow_attr);
137 waddch(win, ACS_DARROW);
138 waddstr(win, "(+)");
139 } else {
140 wattrset(win, menubox_border_attr);
141 waddch(win, ACS_HLINE);
142 waddch(win, ACS_HLINE);
143 waddch(win, ACS_HLINE);
144 waddch(win, ACS_HLINE);
145 }
146
147 wmove(win, cur_y, cur_x);
148 wrefresh(win);
149}
150
151/*
152 * Display the termination buttons.
153 */
154static void print_buttons(WINDOW * win, int height, int width, int selected)
155{
156 int x = width / 2 - 16;
157 int y = height - 2;
158
159 print_button(win, "Select", y, x, selected == 0);
160 print_button(win, " Exit ", y, x + 12, selected == 1);
161 print_button(win, " Help ", y, x + 24, selected == 2);
162
163 wmove(win, y, x + 1 + 12 * selected);
164 wrefresh(win);
165}
166
167/* scroll up n lines (n may be negative) */
168static void do_scroll(WINDOW *win, int *scroll, int n)
169{
170 /* Scroll menu up */
171 scrollok(win, TRUE);
172 wscrl(win, n);
173 scrollok(win, FALSE);
174 *scroll = *scroll + n;
175 wrefresh(win);
176}
177
178/*
179 * Display a menu for choosing among a number of options
180 */
181int dialog_menu(const char *title, const char *prompt, int height, int width,
182 int menu_height, const char *current, int item_no,
183 const char *const *items)
184{
185 int i, j, x, y, box_x, box_y;
186 int key = 0, button = 0, scroll = 0, choice = 0;
187 int first_item = 0, max_choice;
188 WINDOW *dialog, *menu;
189 FILE *f;
190
191 max_choice = MIN(menu_height, item_no);
192
193 /* center dialog box on screen */
194 x = (COLS - width) / 2;
195 y = (LINES - height) / 2;
196
197 draw_shadow(stdscr, y, x, height, width);
198
199 dialog = newwin(height, width, y, x);
200 keypad(dialog, TRUE);
201
202 draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
203 wattrset(dialog, border_attr);
204 mvwaddch(dialog, height - 3, 0, ACS_LTEE);
205 for (i = 0; i < width - 2; i++)
206 waddch(dialog, ACS_HLINE);
207 wattrset(dialog, dialog_attr);
208 wbkgdset(dialog, dialog_attr & A_COLOR);
209 waddch(dialog, ACS_RTEE);
210
211 print_title(dialog, title, width);
212
213 wattrset(dialog, dialog_attr);
214 print_autowrap(dialog, prompt, width - 2, 1, 3);
215
216 menu_width = width - 6;
217 box_y = height - menu_height - 5;
218 box_x = (width - menu_width) / 2 - 1;
219
220 /* create new window for the menu */
221 menu = subwin(dialog, menu_height, menu_width,
222 y + box_y + 1, x + box_x + 1);
223 keypad(menu, TRUE);
224
225 /* draw a box around the menu items */
226 draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
227 menubox_border_attr, menubox_attr);
228
229 item_x = (menu_width - 70) / 2;
230
231 /* Set choice to default item */
232 for (i = 0; i < item_no; i++)
233 if (strcmp(current, items[i * 2]) == 0)
234 choice = i;
235
236 /* get the scroll info from the temp file */
237 if ((f = fopen("lxdialog.scrltmp", "r")) != NULL) {
238 if ((fscanf(f, "%d\n", &scroll) == 1) && (scroll <= choice) &&
239 (scroll + max_choice > choice) && (scroll >= 0) &&
240 (scroll + max_choice <= item_no)) {
241 first_item = scroll;
242 choice = choice - scroll;
243 fclose(f);
244 } else {
245 scroll = 0;
246 remove("lxdialog.scrltmp");
247 fclose(f);
248 f = NULL;
249 }
250 }
251 if ((choice >= max_choice) || (f == NULL && choice >= max_choice / 2)) {
252 if (choice >= item_no - max_choice / 2)
253 scroll = first_item = item_no - max_choice;
254 else
255 scroll = first_item = choice - max_choice / 2;
256 choice = choice - scroll;
257 }
258
259 /* Print the menu */
260 for (i = 0; i < max_choice; i++) {
261 print_item(first_item + i, i, i == choice);
262 }
263
264 wnoutrefresh(menu);
265
266 print_arrows(dialog, item_no, scroll,
267 box_y, box_x + item_x + 1, menu_height);
268
269 print_buttons(dialog, height, width, 0);
270 wmove(menu, choice, item_x + 1);
271 wrefresh(menu);
272
273 while (key != ESC) {
274 key = wgetch(menu);
275
276 if (key < 256 && isalpha(key))
277 key = tolower(key);
278
279 if (strchr("ynmh", key))
280 i = max_choice;
281 else {
282 for (i = choice + 1; i < max_choice; i++) {
283 j = first_alpha(items[(scroll + i) * 2 + 1], "YyNnMmHh");
284 if (key == tolower(items[(scroll + i) * 2 + 1][j]))
285 break;
286 }
287 if (i == max_choice)
288 for (i = 0; i < max_choice; i++) {
289 j = first_alpha(items [(scroll + i) * 2 + 1], "YyNnMmHh");
290 if (key == tolower(items[(scroll + i) * 2 + 1][j]))
291 break;
292 }
293 }
294
295 if (i < max_choice ||
296 key == KEY_UP || key == KEY_DOWN ||
297 key == '-' || key == '+' ||
298 key == KEY_PPAGE || key == KEY_NPAGE) {
299 /* Remove highligt of current item */
300 print_item(scroll + choice, choice, FALSE);
301
302 if (key == KEY_UP || key == '-') {
303 if (choice < 2 && scroll) {
304 /* Scroll menu down */
305 do_scroll(menu, &scroll, -1);
306
307 print_item(scroll, 0, FALSE);
308 } else
309 choice = MAX(choice - 1, 0);
310
311 } else if (key == KEY_DOWN || key == '+') {
312 print_item(scroll+choice, choice, FALSE);
313
314 if ((choice > max_choice - 3) &&
315 (scroll + max_choice < item_no)) {
316 /* Scroll menu up */
317 do_scroll(menu, &scroll, 1);
318
319 print_item(scroll+max_choice - 1,
320 max_choice - 1, FALSE);
321 } else
322 choice = MIN(choice + 1, max_choice - 1);
323
324 } else if (key == KEY_PPAGE) {
325 scrollok(menu, TRUE);
326 for (i = 0; (i < max_choice); i++) {
327 if (scroll > 0) {
328 do_scroll(menu, &scroll, -1);
329 print_item(scroll, 0, FALSE);
330 } else {
331 if (choice > 0)
332 choice--;
333 }
334 }
335
336 } else if (key == KEY_NPAGE) {
337 for (i = 0; (i < max_choice); i++) {
338 if (scroll + max_choice < item_no) {
339 do_scroll(menu, &scroll, 1);
340 print_item(scroll+max_choice-1,
341 max_choice - 1, FALSE);
342 } else {
343 if (choice + 1 < max_choice)
344 choice++;
345 }
346 }
347 } else
348 choice = i;
349
350 print_item(scroll + choice, choice, TRUE);
351
352 print_arrows(dialog, item_no, scroll,
353 box_y, box_x + item_x + 1, menu_height);
354
355 wnoutrefresh(dialog);
356 wrefresh(menu);
357
358 continue; /* wait for another key press */
359 }
360
361 switch (key) {
362 case KEY_LEFT:
363 case TAB:
364 case KEY_RIGHT:
365 button = ((key == KEY_LEFT ? --button : ++button) < 0)
366 ? 2 : (button > 2 ? 0 : button);
367
368 print_buttons(dialog, height, width, button);
369 wrefresh(menu);
370 break;
371 case ' ':
372 case 's':
373 case 'y':
374 case 'n':
375 case 'm':
376 case '/':
377 /* save scroll info */
378 if ((f = fopen("lxdialog.scrltmp", "w")) != NULL) {
379 fprintf(f, "%d\n", scroll);
380 fclose(f);
381 }
382 delwin(dialog);
383 fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
384 switch (key) {
385 case 's':
386 return 3;
387 case 'y':
388 return 3;
389 case 'n':
390 return 4;
391 case 'm':
392 return 5;
393 case ' ':
394 return 6;
395 case '/':
396 return 7;
397 }
398 return 0;
399 case 'h':
400 case '?':
401 button = 2;
402 case '\n':
403 delwin(dialog);
404 if (button == 2)
405 fprintf(stderr, "%s \"%s\"\n",
406 items[(scroll + choice) * 2],
407 items[(scroll + choice) * 2 + 1] +
408 first_alpha(items [(scroll + choice) * 2 + 1], ""));
409 else
410 fprintf(stderr, "%s\n",
411 items[(scroll + choice) * 2]);
412
413 remove("lxdialog.scrltmp");
414 return button;
415 case 'e':
416 case 'x':
417 key = ESC;
418 case ESC:
419 break;
420 }
421 }
422
423 delwin(dialog);
424 remove("lxdialog.scrltmp");
425 return -1; /* ESC pressed */
426}
diff --git a/scripts/kconfig/lxdialog/msgbox.c b/scripts/kconfig/lxdialog/msgbox.c
new file mode 100644
index 000000000..7323f5471
--- /dev/null
+++ b/scripts/kconfig/lxdialog/msgbox.c
@@ -0,0 +1,71 @@
1/*
2 * msgbox.c -- implements the message box and info box
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "dialog.h"
23
24/*
25 * Display a message box. Program will pause and display an "OK" button
26 * if the parameter 'pause' is non-zero.
27 */
28int dialog_msgbox(const char *title, const char *prompt, int height, int width,
29 int pause)
30{
31 int i, x, y, key = 0;
32 WINDOW *dialog;
33
34 /* center dialog box on screen */
35 x = (COLS - width) / 2;
36 y = (LINES - height) / 2;
37
38 draw_shadow(stdscr, y, x, height, width);
39
40 dialog = newwin(height, width, y, x);
41 keypad(dialog, TRUE);
42
43 draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
44
45 print_title(dialog, title, width);
46
47 wattrset(dialog, dialog_attr);
48 print_autowrap(dialog, prompt, width - 2, 1, 2);
49
50 if (pause) {
51 wattrset(dialog, border_attr);
52 mvwaddch(dialog, height - 3, 0, ACS_LTEE);
53 for (i = 0; i < width - 2; i++)
54 waddch(dialog, ACS_HLINE);
55 wattrset(dialog, dialog_attr);
56 waddch(dialog, ACS_RTEE);
57
58 print_button(dialog, " Ok ", height - 2, width / 2 - 4, TRUE);
59
60 wrefresh(dialog);
61 while (key != ESC && key != '\n' && key != ' ' &&
62 key != 'O' && key != 'o' && key != 'X' && key != 'x')
63 key = wgetch(dialog);
64 } else {
65 key = '\n';
66 wrefresh(dialog);
67 }
68
69 delwin(dialog);
70 return key == ESC ? -1 : 0;
71}
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
new file mode 100644
index 000000000..77848bb8e
--- /dev/null
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -0,0 +1,533 @@
1/*
2 * textbox.c -- implements the text box
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "dialog.h"
23
24static void back_lines(int n);
25static void print_page(WINDOW * win, int height, int width);
26static void print_line(WINDOW * win, int row, int width);
27static char *get_line(void);
28static void print_position(WINDOW * win, int height, int width);
29
30static int hscroll, fd, file_size, bytes_read;
31static int begin_reached = 1, end_reached, page_length;
32static char *buf, *page;
33
34/*
35 * Display text from a file in a dialog box.
36 */
37int dialog_textbox(const char *title, const char *file, int height, int width)
38{
39 int i, x, y, cur_x, cur_y, fpos, key = 0;
40 int passed_end;
41 char search_term[MAX_LEN + 1];
42 WINDOW *dialog, *text;
43
44 search_term[0] = '\0'; /* no search term entered yet */
45
46 /* Open input file for reading */
47 if ((fd = open(file, O_RDONLY)) == -1) {
48 endwin();
49 fprintf(stderr, "\nCan't open input file in dialog_textbox().\n");
50 exit(-1);
51 }
52 /* Get file size. Actually, 'file_size' is the real file size - 1,
53 since it's only the last byte offset from the beginning */
54 if ((file_size = lseek(fd, 0, SEEK_END)) == -1) {
55 endwin();
56 fprintf(stderr, "\nError getting file size in dialog_textbox().\n");
57 exit(-1);
58 }
59 /* Restore file pointer to beginning of file after getting file size */
60 if (lseek(fd, 0, SEEK_SET) == -1) {
61 endwin();
62 fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
63 exit(-1);
64 }
65 /* Allocate space for read buffer */
66 if ((buf = malloc(BUF_SIZE + 1)) == NULL) {
67 endwin();
68 fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n");
69 exit(-1);
70 }
71 if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
72 endwin();
73 fprintf(stderr, "\nError reading file in dialog_textbox().\n");
74 exit(-1);
75 }
76 buf[bytes_read] = '\0'; /* mark end of valid data */
77 page = buf; /* page is pointer to start of page to be displayed */
78
79 /* center dialog box on screen */
80 x = (COLS - width) / 2;
81 y = (LINES - height) / 2;
82
83 draw_shadow(stdscr, y, x, height, width);
84
85 dialog = newwin(height, width, y, x);
86 keypad(dialog, TRUE);
87
88 /* Create window for text region, used for scrolling text */
89 text = subwin(dialog, height - 4, width - 2, y + 1, x + 1);
90 wattrset(text, dialog_attr);
91 wbkgdset(text, dialog_attr & A_COLOR);
92
93 keypad(text, TRUE);
94
95 /* register the new window, along with its borders */
96 draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
97
98 wattrset(dialog, border_attr);
99 mvwaddch(dialog, height - 3, 0, ACS_LTEE);
100 for (i = 0; i < width - 2; i++)
101 waddch(dialog, ACS_HLINE);
102 wattrset(dialog, dialog_attr);
103 wbkgdset(dialog, dialog_attr & A_COLOR);
104 waddch(dialog, ACS_RTEE);
105
106 print_title(dialog, title, width);
107
108 print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
109 wnoutrefresh(dialog);
110 getyx(dialog, cur_y, cur_x); /* Save cursor position */
111
112 /* Print first page of text */
113 attr_clear(text, height - 4, width - 2, dialog_attr);
114 print_page(text, height - 4, width - 2);
115 print_position(dialog, height, width);
116 wmove(dialog, cur_y, cur_x); /* Restore cursor position */
117 wrefresh(dialog);
118
119 while ((key != ESC) && (key != '\n')) {
120 key = wgetch(dialog);
121 switch (key) {
122 case 'E': /* Exit */
123 case 'e':
124 case 'X':
125 case 'x':
126 delwin(dialog);
127 free(buf);
128 close(fd);
129 return 0;
130 case 'g': /* First page */
131 case KEY_HOME:
132 if (!begin_reached) {
133 begin_reached = 1;
134 /* First page not in buffer? */
135 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
136 endwin();
137 fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
138 exit(-1);
139 }
140 if (fpos > bytes_read) { /* Yes, we have to read it in */
141 if (lseek(fd, 0, SEEK_SET) == -1) {
142 endwin();
143 fprintf(stderr, "\nError moving file pointer in "
144 "dialog_textbox().\n");
145 exit(-1);
146 }
147 if ((bytes_read =
148 read(fd, buf, BUF_SIZE)) == -1) {
149 endwin();
150 fprintf(stderr, "\nError reading file in dialog_textbox().\n");
151 exit(-1);
152 }
153 buf[bytes_read] = '\0';
154 }
155 page = buf;
156 print_page(text, height - 4, width - 2);
157 print_position(dialog, height, width);
158 wmove(dialog, cur_y, cur_x); /* Restore cursor position */
159 wrefresh(dialog);
160 }
161 break;
162 case 'G': /* Last page */
163 case KEY_END:
164
165 end_reached = 1;
166 /* Last page not in buffer? */
167 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
168 endwin();
169 fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
170 exit(-1);
171 }
172 if (fpos < file_size) { /* Yes, we have to read it in */
173 if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) {
174 endwin();
175 fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
176 exit(-1);
177 }
178 if ((bytes_read =
179 read(fd, buf, BUF_SIZE)) == -1) {
180 endwin();
181 fprintf(stderr, "\nError reading file in dialog_textbox().\n");
182 exit(-1);
183 }
184 buf[bytes_read] = '\0';
185 }
186 page = buf + bytes_read;
187 back_lines(height - 4);
188 print_page(text, height - 4, width - 2);
189 print_position(dialog, height, width);
190 wmove(dialog, cur_y, cur_x); /* Restore cursor position */
191 wrefresh(dialog);
192 break;
193 case 'K': /* Previous line */
194 case 'k':
195 case KEY_UP:
196 if (!begin_reached) {
197 back_lines(page_length + 1);
198
199 /* We don't call print_page() here but use scrolling to ensure
200 faster screen update. However, 'end_reached' and
201 'page_length' should still be updated, and 'page' should
202 point to start of next page. This is done by calling
203 get_line() in the following 'for' loop. */
204 scrollok(text, TRUE);
205 wscrl(text, -1); /* Scroll text region down one line */
206 scrollok(text, FALSE);
207 page_length = 0;
208 passed_end = 0;
209 for (i = 0; i < height - 4; i++) {
210 if (!i) {
211 /* print first line of page */
212 print_line(text, 0, width - 2);
213 wnoutrefresh(text);
214 } else
215 /* Called to update 'end_reached' and 'page' */
216 get_line();
217 if (!passed_end)
218 page_length++;
219 if (end_reached && !passed_end)
220 passed_end = 1;
221 }
222
223 print_position(dialog, height, width);
224 wmove(dialog, cur_y, cur_x); /* Restore cursor position */
225 wrefresh(dialog);
226 }
227 break;
228 case 'B': /* Previous page */
229 case 'b':
230 case KEY_PPAGE:
231 if (begin_reached)
232 break;
233 back_lines(page_length + height - 4);
234 print_page(text, height - 4, width - 2);
235 print_position(dialog, height, width);
236 wmove(dialog, cur_y, cur_x);
237 wrefresh(dialog);
238 break;
239 case 'J': /* Next line */
240 case 'j':
241 case KEY_DOWN:
242 if (!end_reached) {
243 begin_reached = 0;
244 scrollok(text, TRUE);
245 scroll(text); /* Scroll text region up one line */
246 scrollok(text, FALSE);
247 print_line(text, height - 5, width - 2);
248 wnoutrefresh(text);
249 print_position(dialog, height, width);
250 wmove(dialog, cur_y, cur_x); /* Restore cursor position */
251 wrefresh(dialog);
252 }
253 break;
254 case KEY_NPAGE: /* Next page */
255 case ' ':
256 if (end_reached)
257 break;
258
259 begin_reached = 0;
260 print_page(text, height - 4, width - 2);
261 print_position(dialog, height, width);
262 wmove(dialog, cur_y, cur_x);
263 wrefresh(dialog);
264 break;
265 case '0': /* Beginning of line */
266 case 'H': /* Scroll left */
267 case 'h':
268 case KEY_LEFT:
269 if (hscroll <= 0)
270 break;
271
272 if (key == '0')
273 hscroll = 0;
274 else
275 hscroll--;
276 /* Reprint current page to scroll horizontally */
277 back_lines(page_length);
278 print_page(text, height - 4, width - 2);
279 wmove(dialog, cur_y, cur_x);
280 wrefresh(dialog);
281 break;
282 case 'L': /* Scroll right */
283 case 'l':
284 case KEY_RIGHT:
285 if (hscroll >= MAX_LEN)
286 break;
287 hscroll++;
288 /* Reprint current page to scroll horizontally */
289 back_lines(page_length);
290 print_page(text, height - 4, width - 2);
291 wmove(dialog, cur_y, cur_x);
292 wrefresh(dialog);
293 break;
294 case ESC:
295 break;
296 }
297 }
298
299 delwin(dialog);
300 free(buf);
301 close(fd);
302 return -1; /* ESC pressed */
303}
304
305/*
306 * Go back 'n' lines in text file. Called by dialog_textbox().
307 * 'page' will be updated to point to the desired line in 'buf'.
308 */
309static void back_lines(int n)
310{
311 int i, fpos;
312
313 begin_reached = 0;
314 /* We have to distinguish between end_reached and !end_reached
315 since at end of file, the line is not ended by a '\n'.
316 The code inside 'if' basically does a '--page' to move one
317 character backward so as to skip '\n' of the previous line */
318 if (!end_reached) {
319 /* Either beginning of buffer or beginning of file reached? */
320 if (page == buf) {
321 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
322 endwin();
323 fprintf(stderr, "\nError moving file pointer in "
324 "back_lines().\n");
325 exit(-1);
326 }
327 if (fpos > bytes_read) { /* Not beginning of file yet */
328 /* We've reached beginning of buffer, but not beginning of
329 file yet, so read previous part of file into buffer.
330 Note that we only move backward for BUF_SIZE/2 bytes,
331 but not BUF_SIZE bytes to avoid re-reading again in
332 print_page() later */
333 /* Really possible to move backward BUF_SIZE/2 bytes? */
334 if (fpos < BUF_SIZE / 2 + bytes_read) {
335 /* No, move less then */
336 if (lseek(fd, 0, SEEK_SET) == -1) {
337 endwin();
338 fprintf(stderr, "\nError moving file pointer in "
339 "back_lines().\n");
340 exit(-1);
341 }
342 page = buf + fpos - bytes_read;
343 } else { /* Move backward BUF_SIZE/2 bytes */
344 if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
345 endwin();
346 fprintf(stderr, "\nError moving file pointer "
347 "in back_lines().\n");
348 exit(-1);
349 }
350 page = buf + BUF_SIZE / 2;
351 }
352 if ((bytes_read =
353 read(fd, buf, BUF_SIZE)) == -1) {
354 endwin();
355 fprintf(stderr, "\nError reading file in back_lines().\n");
356 exit(-1);
357 }
358 buf[bytes_read] = '\0';
359 } else { /* Beginning of file reached */
360 begin_reached = 1;
361 return;
362 }
363 }
364 if (*(--page) != '\n') { /* '--page' here */
365 /* Something's wrong... */
366 endwin();
367 fprintf(stderr, "\nInternal error in back_lines().\n");
368 exit(-1);
369 }
370 }
371 /* Go back 'n' lines */
372 for (i = 0; i < n; i++)
373 do {
374 if (page == buf) {
375 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
376 endwin();
377 fprintf(stderr, "\nError moving file pointer in back_lines().\n");
378 exit(-1);
379 }
380 if (fpos > bytes_read) {
381 /* Really possible to move backward BUF_SIZE/2 bytes? */
382 if (fpos < BUF_SIZE / 2 + bytes_read) {
383 /* No, move less then */
384 if (lseek(fd, 0, SEEK_SET) == -1) {
385 endwin();
386 fprintf(stderr, "\nError moving file pointer "
387 "in back_lines().\n");
388 exit(-1);
389 }
390 page = buf + fpos - bytes_read;
391 } else { /* Move backward BUF_SIZE/2 bytes */
392 if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
393 endwin();
394 fprintf(stderr, "\nError moving file pointer"
395 " in back_lines().\n");
396 exit(-1);
397 }
398 page = buf + BUF_SIZE / 2;
399 }
400 if ((bytes_read =
401 read(fd, buf, BUF_SIZE)) == -1) {
402 endwin();
403 fprintf(stderr, "\nError reading file in "
404 "back_lines().\n");
405 exit(-1);
406 }
407 buf[bytes_read] = '\0';
408 } else { /* Beginning of file reached */
409 begin_reached = 1;
410 return;
411 }
412 }
413 } while (*(--page) != '\n');
414 page++;
415}
416
417/*
418 * Print a new page of text. Called by dialog_textbox().
419 */
420static void print_page(WINDOW * win, int height, int width)
421{
422 int i, passed_end = 0;
423
424 page_length = 0;
425 for (i = 0; i < height; i++) {
426 print_line(win, i, width);
427 if (!passed_end)
428 page_length++;
429 if (end_reached && !passed_end)
430 passed_end = 1;
431 }
432 wnoutrefresh(win);
433}
434
435/*
436 * Print a new line of text. Called by dialog_textbox() and print_page().
437 */
438static void print_line(WINDOW * win, int row, int width)
439{
440 int y, x;
441 char *line;
442
443 line = get_line();
444 line += MIN(strlen(line), hscroll); /* Scroll horizontally */
445 wmove(win, row, 0); /* move cursor to correct line */
446 waddch(win, ' ');
447 waddnstr(win, line, MIN(strlen(line), width - 2));
448
449 getyx(win, y, x);
450 /* Clear 'residue' of previous line */
451#if OLD_NCURSES
452 {
453 int i;
454 for (i = 0; i < width - x; i++)
455 waddch(win, ' ');
456 }
457#else
458 wclrtoeol(win);
459#endif
460}
461
462/*
463 * Return current line of text. Called by dialog_textbox() and print_line().
464 * 'page' should point to start of current line before calling, and will be
465 * updated to point to start of next line.
466 */
467static char *get_line(void)
468{
469 int i = 0, fpos;
470 static char line[MAX_LEN + 1];
471
472 end_reached = 0;
473 while (*page != '\n') {
474 if (*page == '\0') {
475 /* Either end of file or end of buffer reached */
476 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
477 endwin();
478 fprintf(stderr, "\nError moving file pointer in "
479 "get_line().\n");
480 exit(-1);
481 }
482 if (fpos < file_size) { /* Not end of file yet */
483 /* We've reached end of buffer, but not end of file yet,
484 so read next part of file into buffer */
485 if ((bytes_read =
486 read(fd, buf, BUF_SIZE)) == -1) {
487 endwin();
488 fprintf(stderr, "\nError reading file in get_line().\n");
489 exit(-1);
490 }
491 buf[bytes_read] = '\0';
492 page = buf;
493 } else {
494 if (!end_reached)
495 end_reached = 1;
496 break;
497 }
498 } else if (i < MAX_LEN)
499 line[i++] = *(page++);
500 else {
501 /* Truncate lines longer than MAX_LEN characters */
502 if (i == MAX_LEN)
503 line[i++] = '\0';
504 page++;
505 }
506 }
507 if (i <= MAX_LEN)
508 line[i] = '\0';
509 if (!end_reached)
510 page++; /* move pass '\n' */
511
512 return line;
513}
514
515/*
516 * Print current position
517 */
518static void print_position(WINDOW * win, int height, int width)
519{
520 int fpos, percent;
521
522 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
523 endwin();
524 fprintf(stderr, "\nError moving file pointer in print_position().\n");
525 exit(-1);
526 }
527 wattrset(win, position_indicator_attr);
528 wbkgdset(win, position_indicator_attr & A_COLOR);
529 percent = !file_size ?
530 100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
531 wmove(win, height - 3, width - 9);
532 wprintw(win, "(%3d%%)", percent);
533}
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
new file mode 100644
index 000000000..f82cebb9f
--- /dev/null
+++ b/scripts/kconfig/lxdialog/util.c
@@ -0,0 +1,362 @@
1/*
2 * util.c
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "dialog.h"
23
24/* use colors by default? */
25bool use_colors = 1;
26
27const char *backtitle = NULL;
28
29/*
30 * Attribute values, default is for mono display
31 */
32chtype attributes[] = {
33 A_NORMAL, /* screen_attr */
34 A_NORMAL, /* shadow_attr */
35 A_NORMAL, /* dialog_attr */
36 A_BOLD, /* title_attr */
37 A_NORMAL, /* border_attr */
38 A_REVERSE, /* button_active_attr */
39 A_DIM, /* button_inactive_attr */
40 A_REVERSE, /* button_key_active_attr */
41 A_BOLD, /* button_key_inactive_attr */
42 A_REVERSE, /* button_label_active_attr */
43 A_NORMAL, /* button_label_inactive_attr */
44 A_NORMAL, /* inputbox_attr */
45 A_NORMAL, /* inputbox_border_attr */
46 A_NORMAL, /* searchbox_attr */
47 A_BOLD, /* searchbox_title_attr */
48 A_NORMAL, /* searchbox_border_attr */
49 A_BOLD, /* position_indicator_attr */
50 A_NORMAL, /* menubox_attr */
51 A_NORMAL, /* menubox_border_attr */
52 A_NORMAL, /* item_attr */
53 A_REVERSE, /* item_selected_attr */
54 A_BOLD, /* tag_attr */
55 A_REVERSE, /* tag_selected_attr */
56 A_BOLD, /* tag_key_attr */
57 A_REVERSE, /* tag_key_selected_attr */
58 A_BOLD, /* check_attr */
59 A_REVERSE, /* check_selected_attr */
60 A_BOLD, /* uarrow_attr */
61 A_BOLD /* darrow_attr */
62};
63
64#include "colors.h"
65
66/*
67 * Table of color values
68 */
69int color_table[][3] = {
70 {SCREEN_FG, SCREEN_BG, SCREEN_HL},
71 {SHADOW_FG, SHADOW_BG, SHADOW_HL},
72 {DIALOG_FG, DIALOG_BG, DIALOG_HL},
73 {TITLE_FG, TITLE_BG, TITLE_HL},
74 {BORDER_FG, BORDER_BG, BORDER_HL},
75 {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
76 {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
77 {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
78 {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG,
79 BUTTON_KEY_INACTIVE_HL},
80 {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG,
81 BUTTON_LABEL_ACTIVE_HL},
82 {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
83 BUTTON_LABEL_INACTIVE_HL},
84 {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
85 {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
86 {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
87 {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
88 {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
89 {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
90 {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
91 {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
92 {ITEM_FG, ITEM_BG, ITEM_HL},
93 {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
94 {TAG_FG, TAG_BG, TAG_HL},
95 {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
96 {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
97 {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
98 {CHECK_FG, CHECK_BG, CHECK_HL},
99 {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
100 {UARROW_FG, UARROW_BG, UARROW_HL},
101 {DARROW_FG, DARROW_BG, DARROW_HL},
102}; /* color_table */
103
104/*
105 * Set window to attribute 'attr'
106 */
107void attr_clear(WINDOW * win, int height, int width, chtype attr)
108{
109 int i, j;
110
111 wattrset(win, attr);
112 for (i = 0; i < height; i++) {
113 wmove(win, i, 0);
114 for (j = 0; j < width; j++)
115 waddch(win, ' ');
116 }
117 touchwin(win);
118}
119
120void dialog_clear(void)
121{
122 attr_clear(stdscr, LINES, COLS, screen_attr);
123 /* Display background title if it exists ... - SLH */
124 if (backtitle != NULL) {
125 int i;
126
127 wattrset(stdscr, screen_attr);
128 mvwaddstr(stdscr, 0, 1, (char *)backtitle);
129 wmove(stdscr, 1, 1);
130 for (i = 1; i < COLS - 1; i++)
131 waddch(stdscr, ACS_HLINE);
132 }
133 wnoutrefresh(stdscr);
134}
135
136/*
137 * Do some initialization for dialog
138 */
139void init_dialog(void)
140{
141 initscr(); /* Init curses */
142 keypad(stdscr, TRUE);
143 cbreak();
144 noecho();
145
146 if (use_colors) /* Set up colors */
147 color_setup();
148
149 dialog_clear();
150}
151
152/*
153 * Setup for color display
154 */
155void color_setup(void)
156{
157 int i;
158
159 if (has_colors()) { /* Terminal supports color? */
160 start_color();
161
162 /* Initialize color pairs */
163 for (i = 0; i < ATTRIBUTE_COUNT; i++)
164 init_pair(i + 1, color_table[i][0], color_table[i][1]);
165
166 /* Setup color attributes */
167 for (i = 0; i < ATTRIBUTE_COUNT; i++)
168 attributes[i] = C_ATTR(color_table[i][2], i + 1);
169 }
170}
171
172/*
173 * End using dialog functions.
174 */
175void end_dialog(void)
176{
177 endwin();
178}
179
180/* Print the title of the dialog. Center the title and truncate
181 * tile if wider than dialog (- 2 chars).
182 **/
183void print_title(WINDOW *dialog, const char *title, int width)
184{
185 if (title) {
186 int tlen = MIN(width - 2, strlen(title));
187 wattrset(dialog, title_attr);
188 mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
189 mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
190 waddch(dialog, ' ');
191 }
192}
193
194/*
195 * Print a string of text in a window, automatically wrap around to the
196 * next line if the string is too long to fit on one line. Newline
197 * characters '\n' are replaced by spaces. We start on a new line
198 * if there is no room for at least 4 nonblanks following a double-space.
199 */
200void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
201{
202 int newl, cur_x, cur_y;
203 int i, prompt_len, room, wlen;
204 char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
205
206 strcpy(tempstr, prompt);
207
208 prompt_len = strlen(tempstr);
209
210 /*
211 * Remove newlines
212 */
213 for (i = 0; i < prompt_len; i++) {
214 if (tempstr[i] == '\n')
215 tempstr[i] = ' ';
216 }
217
218 if (prompt_len <= width - x * 2) { /* If prompt is short */
219 wmove(win, y, (width - prompt_len) / 2);
220 waddstr(win, tempstr);
221 } else {
222 cur_x = x;
223 cur_y = y;
224 newl = 1;
225 word = tempstr;
226 while (word && *word) {
227 sp = index(word, ' ');
228 if (sp)
229 *sp++ = 0;
230
231 /* Wrap to next line if either the word does not fit,
232 or it is the first word of a new sentence, and it is
233 short, and the next word does not fit. */
234 room = width - cur_x;
235 wlen = strlen(word);
236 if (wlen > room ||
237 (newl && wlen < 4 && sp
238 && wlen + 1 + strlen(sp) > room
239 && (!(sp2 = index(sp, ' '))
240 || wlen + 1 + (sp2 - sp) > room))) {
241 cur_y++;
242 cur_x = x;
243 }
244 wmove(win, cur_y, cur_x);
245 waddstr(win, word);
246 getyx(win, cur_y, cur_x);
247 cur_x++;
248 if (sp && *sp == ' ') {
249 cur_x++; /* double space */
250 while (*++sp == ' ') ;
251 newl = 1;
252 } else
253 newl = 0;
254 word = sp;
255 }
256 }
257}
258
259/*
260 * Print a button
261 */
262void print_button(WINDOW * win, const char *label, int y, int x, int selected)
263{
264 int i, temp;
265
266 wmove(win, y, x);
267 wattrset(win, selected ? button_active_attr : button_inactive_attr);
268 waddstr(win, "<");
269 temp = strspn(label, " ");
270 label += temp;
271 wattrset(win, selected ? button_label_active_attr
272 : button_label_inactive_attr);
273 for (i = 0; i < temp; i++)
274 waddch(win, ' ');
275 wattrset(win, selected ? button_key_active_attr
276 : button_key_inactive_attr);
277 waddch(win, label[0]);
278 wattrset(win, selected ? button_label_active_attr
279 : button_label_inactive_attr);
280 waddstr(win, (char *)label + 1);
281 wattrset(win, selected ? button_active_attr : button_inactive_attr);
282 waddstr(win, ">");
283 wmove(win, y, x + temp + 1);
284}
285
286/*
287 * Draw a rectangular box with line drawing characters
288 */
289void
290draw_box(WINDOW * win, int y, int x, int height, int width,
291 chtype box, chtype border)
292{
293 int i, j;
294
295 wattrset(win, 0);
296 for (i = 0; i < height; i++) {
297 wmove(win, y + i, x);
298 for (j = 0; j < width; j++)
299 if (!i && !j)
300 waddch(win, border | ACS_ULCORNER);
301 else if (i == height - 1 && !j)
302 waddch(win, border | ACS_LLCORNER);
303 else if (!i && j == width - 1)
304 waddch(win, box | ACS_URCORNER);
305 else if (i == height - 1 && j == width - 1)
306 waddch(win, box | ACS_LRCORNER);
307 else if (!i)
308 waddch(win, border | ACS_HLINE);
309 else if (i == height - 1)
310 waddch(win, box | ACS_HLINE);
311 else if (!j)
312 waddch(win, border | ACS_VLINE);
313 else if (j == width - 1)
314 waddch(win, box | ACS_VLINE);
315 else
316 waddch(win, box | ' ');
317 }
318}
319
320/*
321 * Draw shadows along the right and bottom edge to give a more 3D look
322 * to the boxes
323 */
324void draw_shadow(WINDOW * win, int y, int x, int height, int width)
325{
326 int i;
327
328 if (has_colors()) { /* Whether terminal supports color? */
329 wattrset(win, shadow_attr);
330 wmove(win, y + height, x + 2);
331 for (i = 0; i < width; i++)
332 waddch(win, winch(win) & A_CHARTEXT);
333 for (i = y + 1; i < y + height + 1; i++) {
334 wmove(win, i, x + width);
335 waddch(win, winch(win) & A_CHARTEXT);
336 waddch(win, winch(win) & A_CHARTEXT);
337 }
338 wnoutrefresh(win);
339 }
340}
341
342/*
343 * Return the position of the first alphabetic character in a string.
344 */
345int first_alpha(const char *string, const char *exempt)
346{
347 int i, in_paren = 0, c;
348
349 for (i = 0; i < strlen(string); i++) {
350 c = tolower(string[i]);
351
352 if (strchr("<[(", c))
353 ++in_paren;
354 if (strchr(">])", c) && in_paren > 0)
355 --in_paren;
356
357 if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
358 return i;
359 }
360
361 return 0;
362}
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c
new file mode 100644
index 000000000..cb2568aae
--- /dev/null
+++ b/scripts/kconfig/lxdialog/yesno.c
@@ -0,0 +1,102 @@
1/*
2 * yesno.c -- implements the yes/no box
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "dialog.h"
23
24/*
25 * Display termination buttons
26 */
27static void print_buttons(WINDOW * dialog, int height, int width, int selected)
28{
29 int x = width / 2 - 10;
30 int y = height - 2;
31
32 print_button(dialog, " Yes ", y, x, selected == 0);
33 print_button(dialog, " No ", y, x + 13, selected == 1);
34
35 wmove(dialog, y, x + 1 + 13 * selected);
36 wrefresh(dialog);
37}
38
39/*
40 * Display a dialog box with two buttons - Yes and No
41 */
42int dialog_yesno(const char *title, const char *prompt, int height, int width)
43{
44 int i, x, y, key = 0, button = 0;
45 WINDOW *dialog;
46
47 /* center dialog box on screen */
48 x = (COLS - width) / 2;
49 y = (LINES - height) / 2;
50
51 draw_shadow(stdscr, y, x, height, width);
52
53 dialog = newwin(height, width, y, x);
54 keypad(dialog, TRUE);
55
56 draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
57 wattrset(dialog, border_attr);
58 mvwaddch(dialog, height - 3, 0, ACS_LTEE);
59 for (i = 0; i < width - 2; i++)
60 waddch(dialog, ACS_HLINE);
61 wattrset(dialog, dialog_attr);
62 waddch(dialog, ACS_RTEE);
63
64 print_title(dialog, title, width);
65
66 wattrset(dialog, dialog_attr);
67 print_autowrap(dialog, prompt, width - 2, 1, 3);
68
69 print_buttons(dialog, height, width, 0);
70
71 while (key != ESC) {
72 key = wgetch(dialog);
73 switch (key) {
74 case 'Y':
75 case 'y':
76 delwin(dialog);
77 return 0;
78 case 'N':
79 case 'n':
80 delwin(dialog);
81 return 1;
82
83 case TAB:
84 case KEY_LEFT:
85 case KEY_RIGHT:
86 button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button);
87
88 print_buttons(dialog, height, width, button);
89 wrefresh(dialog);
90 break;
91 case ' ':
92 case '\n':
93 delwin(dialog);
94 return button;
95 case ESC:
96 break;
97 }
98 }
99
100 delwin(dialog);
101 return -1; /* ESC pressed */
102}
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
new file mode 100644
index 000000000..7f973195e
--- /dev/null
+++ b/scripts/kconfig/mconf.c
@@ -0,0 +1,1098 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 *
5 * Introduced single menu mode (show all sub-menus in one large tree).
6 * 2002-11-06 Petr Baudis <pasky@ucw.cz>
7 *
8 * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
9 */
10
11#include <sys/ioctl.h>
12#include <sys/wait.h>
13#include <ctype.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <limits.h>
17#include <signal.h>
18#include <stdarg.h>
19#include <stdlib.h>
20#include <string.h>
21#include <termios.h>
22#include <unistd.h>
23#include <locale.h>
24
25#define LKC_DIRECT_LINK
26#include "lkc.h"
27
28static char menu_backtitle[128];
29static const char mconf_readme[] = N_(
30"Overview\n"
31"--------\n"
32"Some kernel features may be built directly into the kernel.\n"
33"Some may be made into loadable runtime modules. Some features\n"
34"may be completely removed altogether. There are also certain\n"
35"kernel parameters which are not really features, but must be\n"
36"entered in as decimal or hexadecimal numbers or possibly text.\n"
37"\n"
38"Menu items beginning with [*], <M> or [ ] represent features\n"
39"configured to be built in, modularized or removed respectively.\n"
40"Pointed brackets <> represent module capable features.\n"
41"\n"
42"To change any of these features, highlight it with the cursor\n"
43"keys and press <Y> to build it in, <M> to make it a module or\n"
44"<N> to removed it. You may also press the <Space Bar> to cycle\n"
45"through the available options (ie. Y->N->M->Y).\n"
46"\n"
47"Some additional keyboard hints:\n"
48"\n"
49"Menus\n"
50"----------\n"
51"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
52" you wish to change or submenu wish to select and press <Enter>.\n"
53" Submenus are designated by \"--->\".\n"
54"\n"
55" Shortcut: Press the option's highlighted letter (hotkey).\n"
56" Pressing a hotkey more than once will sequence\n"
57" through all visible items which use that hotkey.\n"
58"\n"
59" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
60" unseen options into view.\n"
61"\n"
62"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
63" and press <ENTER>.\n"
64"\n"
65" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
66" using those letters. You may press a single <ESC>, but\n"
67" there is a delayed response which you may find annoying.\n"
68"\n"
69" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
70" <Exit> and <Help>\n"
71"\n"
72"o To get help with an item, use the cursor keys to highlight <Help>\n"
73" and Press <ENTER>.\n"
74"\n"
75" Shortcut: Press <H> or <?>.\n"
76"\n"
77"\n"
78"Radiolists (Choice lists)\n"
79"-----------\n"
80"o Use the cursor keys to select the option you wish to set and press\n"
81" <S> or the <SPACE BAR>.\n"
82"\n"
83" Shortcut: Press the first letter of the option you wish to set then\n"
84" press <S> or <SPACE BAR>.\n"
85"\n"
86"o To see available help for the item, use the cursor keys to highlight\n"
87" <Help> and Press <ENTER>.\n"
88"\n"
89" Shortcut: Press <H> or <?>.\n"
90"\n"
91" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
92" <Help>\n"
93"\n"
94"\n"
95"Data Entry\n"
96"-----------\n"
97"o Enter the requested information and press <ENTER>\n"
98" If you are entering hexadecimal values, it is not necessary to\n"
99" add the '0x' prefix to the entry.\n"
100"\n"
101"o For help, use the <TAB> or cursor keys to highlight the help option\n"
102" and press <ENTER>. You can try <TAB><H> as well.\n"
103"\n"
104"\n"
105"Text Box (Help Window)\n"
106"--------\n"
107"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
108" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
109" who are familiar with less and lynx.\n"
110"\n"
111"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
112"\n"
113"\n"
114"Alternate Configuration Files\n"
115"-----------------------------\n"
116"Menuconfig supports the use of alternate configuration files for\n"
117"those who, for various reasons, find it necessary to switch\n"
118"between different kernel configurations.\n"
119"\n"
120"At the end of the main menu you will find two options. One is\n"
121"for saving the current configuration to a file of your choosing.\n"
122"The other option is for loading a previously saved alternate\n"
123"configuration.\n"
124"\n"
125"Even if you don't use alternate configuration files, but you\n"
126"find during a Menuconfig session that you have completely messed\n"
127"up your settings, you may use the \"Load Alternate...\" option to\n"
128"restore your previously saved settings from \".config\" without\n"
129"restarting Menuconfig.\n"
130"\n"
131"Other information\n"
132"-----------------\n"
133"If you use Menuconfig in an XTERM window make sure you have your\n"
134"$TERM variable set to point to a xterm definition which supports color.\n"
135"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
136"display correctly in a RXVT window because rxvt displays only one\n"
137"intensity of color, bright.\n"
138"\n"
139"Menuconfig will display larger menus on screens or xterms which are\n"
140"set to display more than the standard 25 row by 80 column geometry.\n"
141"In order for this to work, the \"stty size\" command must be able to\n"
142"display the screen's current row and column geometry. I STRONGLY\n"
143"RECOMMEND that you make sure you do NOT have the shell variables\n"
144"LINES and COLUMNS exported into your environment. Some distributions\n"
145"export those variables via /etc/profile. Some ncurses programs can\n"
146"become confused when those variables (LINES & COLUMNS) don't reflect\n"
147"the true screen size.\n"
148"\n"
149"Optional personality available\n"
150"------------------------------\n"
151"If you prefer to have all of the kernel options listed in a single\n"
152"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
153"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
154"\n"
155"make MENUCONFIG_MODE=single_menu menuconfig\n"
156"\n"
157"<Enter> will then unroll the appropriate category, or enfold it if it\n"
158"is already unrolled.\n"
159"\n"
160"Note that this mode can eventually be a little more CPU expensive\n"
161"(especially with a larger number of unrolled categories) than the\n"
162"default mode.\n"),
163menu_instructions[] = N_(
164 "Arrow keys navigate the menu. "
165 "<Enter> selects submenus --->. "
166 "Highlighted letters are hotkeys. "
167 "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
168 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
169 "Legend: [*] built-in [ ] excluded <M> module < > module capable"),
170radiolist_instructions[] = N_(
171 "Use the arrow keys to navigate this window or "
172 "press the hotkey of the item you wish to select "
173 "followed by the <SPACE BAR>. "
174 "Press <?> for additional information about this option."),
175inputbox_instructions_int[] = N_(
176 "Please enter a decimal value. "
177 "Fractions will not be accepted. "
178 "Use the <TAB> key to move from the input field to the buttons below it."),
179inputbox_instructions_hex[] = N_(
180 "Please enter a hexadecimal value. "
181 "Use the <TAB> key to move from the input field to the buttons below it."),
182inputbox_instructions_string[] = N_(
183 "Please enter a string value. "
184 "Use the <TAB> key to move from the input field to the buttons below it."),
185setmod_text[] = N_(
186 "This feature depends on another which has been configured as a module.\n"
187 "As a result, this feature will be built as a module."),
188nohelp_text[] = N_(
189 "There is no help available for this kernel option.\n"),
190load_config_text[] = N_(
191 "Enter the name of the configuration file you wish to load. "
192 "Accept the name shown to restore the configuration you "
193 "last retrieved. Leave blank to abort."),
194load_config_help[] = N_(
195 "\n"
196 "For various reasons, one may wish to keep several different kernel\n"
197 "configurations available on a single machine.\n"
198 "\n"
199 "If you have saved a previous configuration in a file other than the\n"
200 "kernel's default, entering the name of the file here will allow you\n"
201 "to modify that configuration.\n"
202 "\n"
203 "If you are uncertain, then you have probably never used alternate\n"
204 "configuration files. You should therefor leave this blank to abort.\n"),
205save_config_text[] = N_(
206 "Enter a filename to which this configuration should be saved "
207 "as an alternate. Leave blank to abort."),
208save_config_help[] = N_(
209 "\n"
210 "For various reasons, one may wish to keep different kernel\n"
211 "configurations available on a single machine.\n"
212 "\n"
213 "Entering a file name here will allow you to later retrieve, modify\n"
214 "and use the current configuration as an alternate to whatever\n"
215 "configuration options you have selected at that time.\n"
216 "\n"
217 "If you are uncertain what all this means then you should probably\n"
218 "leave this blank.\n"),
219search_help[] = N_(
220 "\n"
221 "Search for CONFIG_ symbols and display their relations.\n"
222 "Regular expressions are allowed.\n"
223 "Example: search for \"^FOO\"\n"
224 "Result:\n"
225 "-----------------------------------------------------------------\n"
226 "Symbol: FOO [=m]\n"
227 "Prompt: Foo bus is used to drive the bar HW\n"
228 "Defined at drivers/pci/Kconfig:47\n"
229 "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
230 "Location:\n"
231 " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
232 " -> PCI support (PCI [=y])\n"
233 " -> PCI access mode (<choice> [=y])\n"
234 "Selects: LIBCRC32\n"
235 "Selected by: BAR\n"
236 "-----------------------------------------------------------------\n"
237 "o The line 'Prompt:' shows the text used in the menu structure for\n"
238 " this CONFIG_ symbol\n"
239 "o The 'Defined at' line tell at what file / line number the symbol\n"
240 " is defined\n"
241 "o The 'Depends on:' line tell what symbols needs to be defined for\n"
242 " this symbol to be visible in the menu (selectable)\n"
243 "o The 'Location:' lines tell where in the menu structure this symbol\n"
244 " is located\n"
245 " A location followed by a [=y] indicate that this is a selectable\n"
246 " menu item - and current value is displayed inside brackets.\n"
247 "o The 'Selects:' line tell what symbol will be automatically\n"
248 " selected if this symbol is selected (y or m)\n"
249 "o The 'Selected by' line tell what symbol has selected this symbol\n"
250 "\n"
251 "Only relevant lines are shown.\n"
252 "\n\n"
253 "Search examples:\n"
254 "Examples: USB => find all CONFIG_ symbols containing USB\n"
255 " ^USB => find all CONFIG_ symbols starting with USB\n"
256 " USB$ => find all CONFIG_ symbols ending with USB\n"
257 "\n");
258
259static char buf[4096], *bufptr = buf;
260static char input_buf[4096];
261static char filename[PATH_MAX+1] = ".config";
262static char *args[1024], **argptr = args;
263static int indent;
264static struct termios ios_org;
265static int rows = 0, cols = 0;
266static struct menu *current_menu;
267static int child_count;
268static int do_resize;
269static int single_menu_mode;
270
271static void conf(struct menu *menu);
272static void conf_choice(struct menu *menu);
273static void conf_string(struct menu *menu);
274static void conf_load(void);
275static void conf_save(void);
276static void show_textbox(const char *title, const char *text, int r, int c);
277static void show_helptext(const char *title, const char *text);
278static void show_help(struct menu *menu);
279static void show_file(const char *filename, const char *title, int r, int c);
280
281static void cprint_init(void);
282static int cprint1(const char *fmt, ...);
283static void cprint_done(void);
284static int cprint(const char *fmt, ...);
285
286static void init_wsize(void)
287{
288 struct winsize ws;
289 char *env;
290
291 if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
292 rows = ws.ws_row;
293 cols = ws.ws_col;
294 }
295
296 if (!rows) {
297 env = getenv("LINES");
298 if (env)
299 rows = atoi(env);
300 if (!rows)
301 rows = 24;
302 }
303 if (!cols) {
304 env = getenv("COLUMNS");
305 if (env)
306 cols = atoi(env);
307 if (!cols)
308 cols = 80;
309 }
310
311 if (rows < 19 || cols < 80) {
312 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
313 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
314 exit(1);
315 }
316
317 rows -= 4;
318 cols -= 5;
319}
320
321static void cprint_init(void)
322{
323 bufptr = buf;
324 argptr = args;
325 memset(args, 0, sizeof(args));
326 indent = 0;
327 child_count = 0;
328 cprint("./scripts/kconfig/lxdialog/lxdialog");
329 cprint("--backtitle");
330 cprint(menu_backtitle);
331}
332
333static int cprint1(const char *fmt, ...)
334{
335 va_list ap;
336 int res;
337
338 if (!*argptr)
339 *argptr = bufptr;
340 va_start(ap, fmt);
341 res = vsprintf(bufptr, fmt, ap);
342 va_end(ap);
343 bufptr += res;
344
345 return res;
346}
347
348static void cprint_done(void)
349{
350 *bufptr++ = 0;
351 argptr++;
352}
353
354static int cprint(const char *fmt, ...)
355{
356 va_list ap;
357 int res;
358
359 *argptr++ = bufptr;
360 va_start(ap, fmt);
361 res = vsprintf(bufptr, fmt, ap);
362 va_end(ap);
363 bufptr += res;
364 *bufptr++ = 0;
365
366 return res;
367}
368
369static void get_prompt_str(struct gstr *r, struct property *prop)
370{
371 int i, j;
372 struct menu *submenu[8], *menu;
373
374 str_printf(r, "Prompt: %s\n", prop->text);
375 str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
376 prop->menu->lineno);
377 if (!expr_is_yes(prop->visible.expr)) {
378 str_append(r, " Depends on: ");
379 expr_gstr_print(prop->visible.expr, r);
380 str_append(r, "\n");
381 }
382 menu = prop->menu->parent;
383 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
384 submenu[i++] = menu;
385 if (i > 0) {
386 str_printf(r, " Location:\n");
387 for (j = 4; --i >= 0; j += 2) {
388 menu = submenu[i];
389 str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
390 if (menu->sym) {
391 str_printf(r, " (%s [=%s])", menu->sym->name ?
392 menu->sym->name : "<choice>",
393 sym_get_string_value(menu->sym));
394 }
395 str_append(r, "\n");
396 }
397 }
398}
399
400static void get_symbol_str(struct gstr *r, struct symbol *sym)
401{
402 bool hit;
403 struct property *prop;
404
405 str_printf(r, "Symbol: %s [=%s]\n", sym->name,
406 sym_get_string_value(sym));
407 for_all_prompts(sym, prop)
408 get_prompt_str(r, prop);
409 hit = false;
410 for_all_properties(sym, prop, P_SELECT) {
411 if (!hit) {
412 str_append(r, " Selects: ");
413 hit = true;
414 } else
415 str_printf(r, " && ");
416 expr_gstr_print(prop->expr, r);
417 }
418 if (hit)
419 str_append(r, "\n");
420 if (sym->rev_dep.expr) {
421 str_append(r, " Selected by: ");
422 expr_gstr_print(sym->rev_dep.expr, r);
423 str_append(r, "\n");
424 }
425 str_append(r, "\n\n");
426}
427
428static struct gstr get_relations_str(struct symbol **sym_arr)
429{
430 struct symbol *sym;
431 struct gstr res = str_new();
432 int i;
433
434 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
435 get_symbol_str(&res, sym);
436 if (!i)
437 str_append(&res, "No matches found.\n");
438 return res;
439}
440
441pid_t pid;
442
443static void winch_handler(int sig)
444{
445 if (!do_resize) {
446 kill(pid, SIGINT);
447 do_resize = 1;
448 }
449}
450
451static int exec_conf(void)
452{
453 int pipefd[2], stat, size;
454 struct sigaction sa;
455 sigset_t sset, osset;
456
457 sigemptyset(&sset);
458 sigaddset(&sset, SIGINT);
459 sigprocmask(SIG_BLOCK, &sset, &osset);
460
461 signal(SIGINT, SIG_DFL);
462
463 sa.sa_handler = winch_handler;
464 sigemptyset(&sa.sa_mask);
465 sa.sa_flags = SA_RESTART;
466 sigaction(SIGWINCH, &sa, NULL);
467
468 *argptr++ = NULL;
469
470 pipe(pipefd);
471 pid = fork();
472 if (pid == 0) {
473 sigprocmask(SIG_SETMASK, &osset, NULL);
474 dup2(pipefd[1], 2);
475 close(pipefd[0]);
476 close(pipefd[1]);
477 execv(args[0], args);
478 _exit(EXIT_FAILURE);
479 }
480
481 close(pipefd[1]);
482 bufptr = input_buf;
483 while (1) {
484 size = input_buf + sizeof(input_buf) - bufptr;
485 size = read(pipefd[0], bufptr, size);
486 if (size <= 0) {
487 if (size < 0) {
488 if (errno == EINTR || errno == EAGAIN)
489 continue;
490 perror("read");
491 }
492 break;
493 }
494 bufptr += size;
495 }
496 *bufptr++ = 0;
497 close(pipefd[0]);
498 waitpid(pid, &stat, 0);
499
500 if (do_resize) {
501 init_wsize();
502 do_resize = 0;
503 sigprocmask(SIG_SETMASK, &osset, NULL);
504 return -1;
505 }
506 if (WIFSIGNALED(stat)) {
507 printf("\finterrupted(%d)\n", WTERMSIG(stat));
508 exit(1);
509 }
510#if 0
511 printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf);
512 sleep(1);
513#endif
514 sigpending(&sset);
515 if (sigismember(&sset, SIGINT)) {
516 printf("\finterrupted\n");
517 exit(1);
518 }
519 sigprocmask(SIG_SETMASK, &osset, NULL);
520
521 return WEXITSTATUS(stat);
522}
523
524static void search_conf(void)
525{
526 struct symbol **sym_arr;
527 int stat;
528 struct gstr res;
529
530again:
531 cprint_init();
532 cprint("--title");
533 cprint(_("Search Configuration Parameter"));
534 cprint("--inputbox");
535 cprint(_("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"));
536 cprint("10");
537 cprint("75");
538 cprint("");
539 stat = exec_conf();
540 if (stat < 0)
541 goto again;
542 switch (stat) {
543 case 0:
544 break;
545 case 1:
546 show_helptext(_("Search Configuration"), search_help);
547 goto again;
548 default:
549 return;
550 }
551
552 sym_arr = sym_re_search(input_buf);
553 res = get_relations_str(sym_arr);
554 free(sym_arr);
555 show_textbox(_("Search Results"), str_get(&res), 0, 0);
556 str_free(&res);
557}
558
559static void build_conf(struct menu *menu)
560{
561 struct symbol *sym;
562 struct property *prop;
563 struct menu *child;
564 int type, tmp, doint = 2;
565 tristate val;
566 char ch;
567
568 if (!menu_is_visible(menu))
569 return;
570
571 sym = menu->sym;
572 prop = menu->prompt;
573 if (!sym) {
574 if (prop && menu != current_menu) {
575 const char *prompt = menu_get_prompt(menu);
576 switch (prop->type) {
577 case P_MENU:
578 child_count++;
579 cprint("m%p", menu);
580
581 if (single_menu_mode) {
582 cprint1("%s%*c%s",
583 menu->data ? "-->" : "++>",
584 indent + 1, ' ', prompt);
585 } else
586 cprint1(" %*c%s --->", indent + 1, ' ', prompt);
587
588 cprint_done();
589 if (single_menu_mode && menu->data)
590 goto conf_childs;
591 return;
592 default:
593 if (prompt) {
594 child_count++;
595 cprint(":%p", menu);
596 cprint("---%*c%s", indent + 1, ' ', prompt);
597 }
598 }
599 } else
600 doint = 0;
601 goto conf_childs;
602 }
603
604 type = sym_get_type(sym);
605 if (sym_is_choice(sym)) {
606 struct symbol *def_sym = sym_get_choice_value(sym);
607 struct menu *def_menu = NULL;
608
609 child_count++;
610 for (child = menu->list; child; child = child->next) {
611 if (menu_is_visible(child) && child->sym == def_sym)
612 def_menu = child;
613 }
614
615 val = sym_get_tristate_value(sym);
616 if (sym_is_changable(sym)) {
617 cprint("t%p", menu);
618 switch (type) {
619 case S_BOOLEAN:
620 cprint1("[%c]", val == no ? ' ' : '*');
621 break;
622 case S_TRISTATE:
623 switch (val) {
624 case yes: ch = '*'; break;
625 case mod: ch = 'M'; break;
626 default: ch = ' '; break;
627 }
628 cprint1("<%c>", ch);
629 break;
630 }
631 } else {
632 cprint("%c%p", def_menu ? 't' : ':', menu);
633 cprint1(" ");
634 }
635
636 cprint1("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
637 if (val == yes) {
638 if (def_menu) {
639 cprint1(" (%s)", menu_get_prompt(def_menu));
640 cprint1(" --->");
641 cprint_done();
642 if (def_menu->list) {
643 indent += 2;
644 build_conf(def_menu);
645 indent -= 2;
646 }
647 } else
648 cprint_done();
649 return;
650 }
651 cprint_done();
652 } else {
653 if (menu == current_menu) {
654 cprint(":%p", menu);
655 cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
656 goto conf_childs;
657 }
658 child_count++;
659 val = sym_get_tristate_value(sym);
660 if (sym_is_choice_value(sym) && val == yes) {
661 cprint(":%p", menu);
662 cprint1(" ");
663 } else {
664 switch (type) {
665 case S_BOOLEAN:
666 cprint("t%p", menu);
667 if (sym_is_changable(sym))
668 cprint1("[%c]", val == no ? ' ' : '*');
669 else
670 cprint1("---");
671 break;
672 case S_TRISTATE:
673 cprint("t%p", menu);
674 switch (val) {
675 case yes: ch = '*'; break;
676 case mod: ch = 'M'; break;
677 default: ch = ' '; break;
678 }
679 if (sym_is_changable(sym))
680 cprint1("<%c>", ch);
681 else
682 cprint1("---");
683 break;
684 default:
685 cprint("s%p", menu);
686 tmp = cprint1("(%s)", sym_get_string_value(sym));
687 tmp = indent - tmp + 4;
688 if (tmp < 0)
689 tmp = 0;
690 cprint1("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
691 (sym_has_value(sym) || !sym_is_changable(sym)) ?
692 "" : " (NEW)");
693 cprint_done();
694 goto conf_childs;
695 }
696 }
697 cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
698 (sym_has_value(sym) || !sym_is_changable(sym)) ?
699 "" : " (NEW)");
700 if (menu->prompt->type == P_MENU) {
701 cprint1(" --->");
702 cprint_done();
703 return;
704 }
705 cprint_done();
706 }
707
708conf_childs:
709 indent += doint;
710 for (child = menu->list; child; child = child->next)
711 build_conf(child);
712 indent -= doint;
713}
714
715static void conf(struct menu *menu)
716{
717 struct menu *submenu;
718 const char *prompt = menu_get_prompt(menu);
719 struct symbol *sym;
720 char active_entry[40];
721 int stat, type, i;
722
723 unlink("lxdialog.scrltmp");
724 active_entry[0] = 0;
725 while (1) {
726 cprint_init();
727 cprint("--title");
728 cprint("%s", prompt ? prompt : _("Main Menu"));
729 cprint("--menu");
730 cprint(_(menu_instructions));
731 cprint("%d", rows);
732 cprint("%d", cols);
733 cprint("%d", rows - 10);
734 cprint("%s", active_entry);
735 current_menu = menu;
736 build_conf(menu);
737 if (!child_count)
738 break;
739 if (menu == &rootmenu) {
740 cprint(":");
741 cprint("--- ");
742 cprint("L");
743 cprint(_(" Load an Alternate Configuration File"));
744 cprint("S");
745 cprint(_(" Save Configuration to an Alternate File"));
746 }
747 stat = exec_conf();
748 if (stat < 0)
749 continue;
750
751 if (stat == 1 || stat == 255)
752 break;
753
754 type = input_buf[0];
755 if (!type)
756 continue;
757
758 for (i = 0; input_buf[i] && !isspace(input_buf[i]); i++)
759 ;
760 if (i >= sizeof(active_entry))
761 i = sizeof(active_entry) - 1;
762 input_buf[i] = 0;
763 strcpy(active_entry, input_buf);
764
765 sym = NULL;
766 submenu = NULL;
767 if (sscanf(input_buf + 1, "%p", &submenu) == 1)
768 sym = submenu->sym;
769
770 switch (stat) {
771 case 0:
772 switch (type) {
773 case 'm':
774 if (single_menu_mode)
775 submenu->data = (void *) (long) !submenu->data;
776 else
777 conf(submenu);
778 break;
779 case 't':
780 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
781 conf_choice(submenu);
782 else if (submenu->prompt->type == P_MENU)
783 conf(submenu);
784 break;
785 case 's':
786 conf_string(submenu);
787 break;
788 case 'L':
789 conf_load();
790 break;
791 case 'S':
792 conf_save();
793 break;
794 }
795 break;
796 case 2:
797 if (sym)
798 show_help(submenu);
799 else
800 show_helptext("README", _(mconf_readme));
801 break;
802 case 3:
803 if (type == 't') {
804 if (sym_set_tristate_value(sym, yes))
805 break;
806 if (sym_set_tristate_value(sym, mod))
807 show_textbox(NULL, setmod_text, 6, 74);
808 }
809 break;
810 case 4:
811 if (type == 't')
812 sym_set_tristate_value(sym, no);
813 break;
814 case 5:
815 if (type == 't')
816 sym_set_tristate_value(sym, mod);
817 break;
818 case 6:
819 if (type == 't')
820 sym_toggle_tristate_value(sym);
821 else if (type == 'm')
822 conf(submenu);
823 break;
824 case 7:
825 search_conf();
826 break;
827 }
828 }
829}
830
831static void show_textbox(const char *title, const char *text, int r, int c)
832{
833 int fd;
834
835 fd = creat(".help.tmp", 0777);
836 write(fd, text, strlen(text));
837 close(fd);
838 show_file(".help.tmp", title, r, c);
839 unlink(".help.tmp");
840}
841
842static void show_helptext(const char *title, const char *text)
843{
844 show_textbox(title, text, 0, 0);
845}
846
847static void show_help(struct menu *menu)
848{
849 struct gstr help = str_new();
850 struct symbol *sym = menu->sym;
851
852 if (sym->help)
853 {
854 if (sym->name) {
855 str_printf(&help, "CONFIG_%s:\n\n", sym->name);
856 str_append(&help, _(sym->help));
857 str_append(&help, "\n");
858 }
859 } else {
860 str_append(&help, nohelp_text);
861 }
862 get_symbol_str(&help, sym);
863 show_helptext(menu_get_prompt(menu), str_get(&help));
864 str_free(&help);
865}
866
867static void show_file(const char *filename, const char *title, int r, int c)
868{
869 do {
870 cprint_init();
871 if (title) {
872 cprint("--title");
873 cprint("%s", title);
874 }
875 cprint("--textbox");
876 cprint("%s", filename);
877 cprint("%d", r ? r : rows);
878 cprint("%d", c ? c : cols);
879 } while (exec_conf() < 0);
880}
881
882static void conf_choice(struct menu *menu)
883{
884 const char *prompt = menu_get_prompt(menu);
885 struct menu *child;
886 struct symbol *active;
887 int stat;
888
889 active = sym_get_choice_value(menu->sym);
890 while (1) {
891 cprint_init();
892 cprint("--title");
893 cprint("%s", prompt ? prompt : _("Main Menu"));
894 cprint("--radiolist");
895 cprint(_(radiolist_instructions));
896 cprint("15");
897 cprint("70");
898 cprint("6");
899
900 current_menu = menu;
901 for (child = menu->list; child; child = child->next) {
902 if (!menu_is_visible(child))
903 continue;
904 cprint("%p", child);
905 cprint("%s", menu_get_prompt(child));
906 if (child->sym == sym_get_choice_value(menu->sym))
907 cprint("ON");
908 else if (child->sym == active)
909 cprint("SELECTED");
910 else
911 cprint("OFF");
912 }
913
914 stat = exec_conf();
915 switch (stat) {
916 case 0:
917 if (sscanf(input_buf, "%p", &child) != 1)
918 break;
919 sym_set_tristate_value(child->sym, yes);
920 return;
921 case 1:
922 if (sscanf(input_buf, "%p", &child) == 1) {
923 show_help(child);
924 active = child->sym;
925 } else
926 show_help(menu);
927 break;
928 case 255:
929 return;
930 }
931 }
932}
933
934static void conf_string(struct menu *menu)
935{
936 const char *prompt = menu_get_prompt(menu);
937 int stat;
938
939 while (1) {
940 cprint_init();
941 cprint("--title");
942 cprint("%s", prompt ? prompt : _("Main Menu"));
943 cprint("--inputbox");
944 switch (sym_get_type(menu->sym)) {
945 case S_INT:
946 cprint(_(inputbox_instructions_int));
947 break;
948 case S_HEX:
949 cprint(_(inputbox_instructions_hex));
950 break;
951 case S_STRING:
952 cprint(_(inputbox_instructions_string));
953 break;
954 default:
955 /* panic? */;
956 }
957 cprint("10");
958 cprint("75");
959 cprint("%s", sym_get_string_value(menu->sym));
960 stat = exec_conf();
961 switch (stat) {
962 case 0:
963 if (sym_set_string_value(menu->sym, input_buf))
964 return;
965 show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
966 break;
967 case 1:
968 show_help(menu);
969 break;
970 case 255:
971 return;
972 }
973 }
974}
975
976static void conf_load(void)
977{
978 int stat;
979
980 while (1) {
981 cprint_init();
982 cprint("--inputbox");
983 cprint(load_config_text);
984 cprint("11");
985 cprint("55");
986 cprint("%s", filename);
987 stat = exec_conf();
988 switch(stat) {
989 case 0:
990 if (!input_buf[0])
991 return;
992 if (!conf_read(input_buf))
993 return;
994 show_textbox(NULL, _("File does not exist!"), 5, 38);
995 break;
996 case 1:
997 show_helptext(_("Load Alternate Configuration"), load_config_help);
998 break;
999 case 255:
1000 return;
1001 }
1002 }
1003}
1004
1005static void conf_save(void)
1006{
1007 int stat;
1008
1009 while (1) {
1010 cprint_init();
1011 cprint("--inputbox");
1012 cprint(save_config_text);
1013 cprint("11");
1014 cprint("55");
1015 cprint("%s", filename);
1016 stat = exec_conf();
1017 switch(stat) {
1018 case 0:
1019 if (!input_buf[0])
1020 return;
1021 if (!conf_write(input_buf))
1022 return;
1023 show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
1024 break;
1025 case 1:
1026 show_helptext(_("Save Alternate Configuration"), save_config_help);
1027 break;
1028 case 255:
1029 return;
1030 }
1031 }
1032}
1033
1034static void conf_cleanup(void)
1035{
1036 tcsetattr(1, TCSAFLUSH, &ios_org);
1037 unlink(".help.tmp");
1038 unlink("lxdialog.scrltmp");
1039}
1040
1041int main(int ac, char **av)
1042{
1043 struct symbol *sym;
1044 char *mode;
1045 int stat;
1046
1047 setlocale(LC_ALL, "");
1048 bindtextdomain(PACKAGE, LOCALEDIR);
1049 textdomain(PACKAGE);
1050
1051 conf_parse(av[1]);
1052 conf_read(NULL);
1053
1054 sym = sym_lookup("KERNELVERSION", 0);
1055 sym_calc_value(sym);
1056 sprintf(menu_backtitle, _("Linux Kernel v%s Configuration"),
1057 sym_get_string_value(sym));
1058
1059 mode = getenv("MENUCONFIG_MODE");
1060 if (mode) {
1061 if (!strcasecmp(mode, "single_menu"))
1062 single_menu_mode = 1;
1063 }
1064
1065 tcgetattr(1, &ios_org);
1066 atexit(conf_cleanup);
1067 init_wsize();
1068 conf(&rootmenu);
1069
1070 do {
1071 cprint_init();
1072 cprint("--yesno");
1073 cprint(_("Do you wish to save your new kernel configuration?"));
1074 cprint("5");
1075 cprint("60");
1076 stat = exec_conf();
1077 } while (stat < 0);
1078
1079 if (stat == 0) {
1080 if (conf_write(NULL)) {
1081 fprintf(stderr, _("\n\n"
1082 "Error during writing of the kernel configuration.\n"
1083 "Your kernel configuration changes were NOT saved."
1084 "\n\n"));
1085 return 1;
1086 }
1087 printf(_("\n\n"
1088 "*** End of Linux kernel configuration.\n"
1089 "*** Execute 'make' to build the kernel or try 'make help'."
1090 "\n\n"));
1091 } else {
1092 fprintf(stderr, _("\n\n"
1093 "Your kernel configuration changes were NOT saved."
1094 "\n\n"));
1095 }
1096
1097 return 0;
1098}
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
new file mode 100644
index 000000000..0fce20cb7
--- /dev/null
+++ b/scripts/kconfig/menu.c
@@ -0,0 +1,397 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <stdlib.h>
7#include <string.h>
8
9#define LKC_DIRECT_LINK
10#include "lkc.h"
11
12struct menu rootmenu;
13static struct menu **last_entry_ptr;
14
15struct file *file_list;
16struct file *current_file;
17
18static void menu_warn(struct menu *menu, const char *fmt, ...)
19{
20 va_list ap;
21 va_start(ap, fmt);
22 fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
23 vfprintf(stderr, fmt, ap);
24 fprintf(stderr, "\n");
25 va_end(ap);
26}
27
28static void prop_warn(struct property *prop, const char *fmt, ...)
29{
30 va_list ap;
31 va_start(ap, fmt);
32 fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
33 vfprintf(stderr, fmt, ap);
34 fprintf(stderr, "\n");
35 va_end(ap);
36}
37
38void menu_init(void)
39{
40 current_entry = current_menu = &rootmenu;
41 last_entry_ptr = &rootmenu.list;
42}
43
44void menu_add_entry(struct symbol *sym)
45{
46 struct menu *menu;
47
48 menu = malloc(sizeof(*menu));
49 memset(menu, 0, sizeof(*menu));
50 menu->sym = sym;
51 menu->parent = current_menu;
52 menu->file = current_file;
53 menu->lineno = zconf_lineno();
54
55 *last_entry_ptr = menu;
56 last_entry_ptr = &menu->next;
57 current_entry = menu;
58}
59
60void menu_end_entry(void)
61{
62}
63
64struct menu *menu_add_menu(void)
65{
66 menu_end_entry();
67 last_entry_ptr = &current_entry->list;
68 return current_menu = current_entry;
69}
70
71void menu_end_menu(void)
72{
73 last_entry_ptr = &current_menu->next;
74 current_menu = current_menu->parent;
75}
76
77struct expr *menu_check_dep(struct expr *e)
78{
79 if (!e)
80 return e;
81
82 switch (e->type) {
83 case E_NOT:
84 e->left.expr = menu_check_dep(e->left.expr);
85 break;
86 case E_OR:
87 case E_AND:
88 e->left.expr = menu_check_dep(e->left.expr);
89 e->right.expr = menu_check_dep(e->right.expr);
90 break;
91 case E_SYMBOL:
92 /* change 'm' into 'm' && MODULES */
93 if (e->left.sym == &symbol_mod)
94 return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
95 break;
96 default:
97 break;
98 }
99 return e;
100}
101
102void menu_add_dep(struct expr *dep)
103{
104 current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
105}
106
107void menu_set_type(int type)
108{
109 struct symbol *sym = current_entry->sym;
110
111 if (sym->type == type)
112 return;
113 if (sym->type == S_UNKNOWN) {
114 sym->type = type;
115 return;
116 }
117 menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n",
118 sym->name ? sym->name : "<choice>",
119 sym_type_name(sym->type), sym_type_name(type));
120}
121
122struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
123{
124 struct property *prop = prop_alloc(type, current_entry->sym);
125
126 prop->menu = current_entry;
127 prop->text = prompt;
128 prop->expr = expr;
129 prop->visible.expr = menu_check_dep(dep);
130
131 if (prompt) {
132 if (current_entry->prompt)
133 menu_warn(current_entry, "prompt redefined\n");
134 current_entry->prompt = prop;
135 }
136
137 return prop;
138}
139
140struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
141{
142 return menu_add_prop(type, prompt, NULL, dep);
143}
144
145void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
146{
147 menu_add_prop(type, NULL, expr, dep);
148}
149
150void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
151{
152 menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
153}
154
155static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
156{
157 return sym2->type == S_INT || sym2->type == S_HEX ||
158 (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
159}
160
161void sym_check_prop(struct symbol *sym)
162{
163 struct property *prop;
164 struct symbol *sym2;
165 for (prop = sym->prop; prop; prop = prop->next) {
166 switch (prop->type) {
167 case P_DEFAULT:
168 if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
169 prop->expr->type != E_SYMBOL)
170 prop_warn(prop,
171 "default for config symbol '%'"
172 " must be a single symbol", sym->name);
173 break;
174 case P_SELECT:
175 sym2 = prop_get_symbol(prop);
176 if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
177 prop_warn(prop,
178 "config symbol '%s' uses select, but is "
179 "not boolean or tristate", sym->name);
180 else if (sym2->type == S_UNKNOWN)
181 prop_warn(prop,
182 "'select' used by config symbol '%s' "
183 "refer to undefined symbol '%s'",
184 sym->name, sym2->name);
185 else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
186 prop_warn(prop,
187 "'%s' has wrong type. 'select' only "
188 "accept arguments of boolean and "
189 "tristate type", sym2->name);
190 break;
191 case P_RANGE:
192 if (sym->type != S_INT && sym->type != S_HEX)
193 prop_warn(prop, "range is only allowed "
194 "for int or hex symbols");
195 if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
196 !menu_range_valid_sym(sym, prop->expr->right.sym))
197 prop_warn(prop, "range is invalid");
198 break;
199 default:
200 ;
201 }
202 }
203}
204
205void menu_finalize(struct menu *parent)
206{
207 struct menu *menu, *last_menu;
208 struct symbol *sym;
209 struct property *prop;
210 struct expr *parentdep, *basedep, *dep, *dep2, **ep;
211
212 sym = parent->sym;
213 if (parent->list) {
214 if (sym && sym_is_choice(sym)) {
215 /* find the first choice value and find out choice type */
216 for (menu = parent->list; menu; menu = menu->next) {
217 if (menu->sym) {
218 current_entry = parent;
219 menu_set_type(menu->sym->type);
220 current_entry = menu;
221 menu_set_type(sym->type);
222 break;
223 }
224 }
225 parentdep = expr_alloc_symbol(sym);
226 } else if (parent->prompt)
227 parentdep = parent->prompt->visible.expr;
228 else
229 parentdep = parent->dep;
230
231 for (menu = parent->list; menu; menu = menu->next) {
232 basedep = expr_transform(menu->dep);
233 basedep = expr_alloc_and(expr_copy(parentdep), basedep);
234 basedep = expr_eliminate_dups(basedep);
235 menu->dep = basedep;
236 if (menu->sym)
237 prop = menu->sym->prop;
238 else
239 prop = menu->prompt;
240 for (; prop; prop = prop->next) {
241 if (prop->menu != menu)
242 continue;
243 dep = expr_transform(prop->visible.expr);
244 dep = expr_alloc_and(expr_copy(basedep), dep);
245 dep = expr_eliminate_dups(dep);
246 if (menu->sym && menu->sym->type != S_TRISTATE)
247 dep = expr_trans_bool(dep);
248 prop->visible.expr = dep;
249 if (prop->type == P_SELECT) {
250 struct symbol *es = prop_get_symbol(prop);
251 es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
252 expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
253 }
254 }
255 }
256 for (menu = parent->list; menu; menu = menu->next)
257 menu_finalize(menu);
258 } else if (sym) {
259 basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
260 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
261 basedep = expr_eliminate_dups(expr_transform(basedep));
262 last_menu = NULL;
263 for (menu = parent->next; menu; menu = menu->next) {
264 dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
265 if (!expr_contains_symbol(dep, sym))
266 break;
267 if (expr_depends_symbol(dep, sym))
268 goto next;
269 dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
270 dep = expr_eliminate_dups(expr_transform(dep));
271 dep2 = expr_copy(basedep);
272 expr_eliminate_eq(&dep, &dep2);
273 expr_free(dep);
274 if (!expr_is_yes(dep2)) {
275 expr_free(dep2);
276 break;
277 }
278 expr_free(dep2);
279 next:
280 menu_finalize(menu);
281 menu->parent = parent;
282 last_menu = menu;
283 }
284 if (last_menu) {
285 parent->list = parent->next;
286 parent->next = last_menu->next;
287 last_menu->next = NULL;
288 }
289 }
290 for (menu = parent->list; menu; menu = menu->next) {
291 if (sym && sym_is_choice(sym) && menu->sym) {
292 menu->sym->flags |= SYMBOL_CHOICEVAL;
293 if (!menu->prompt)
294 menu_warn(menu, "choice value must have a prompt");
295 for (prop = menu->sym->prop; prop; prop = prop->next) {
296 if (prop->type == P_PROMPT && prop->menu != menu) {
297 prop_warn(prop, "choice values "
298 "currently only support a "
299 "single prompt");
300 }
301 if (prop->type == P_DEFAULT)
302 prop_warn(prop, "defaults for choice "
303 "values not supported");
304 }
305 current_entry = menu;
306 menu_set_type(sym->type);
307 menu_add_symbol(P_CHOICE, sym, NULL);
308 prop = sym_get_choice_prop(sym);
309 for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
310 ;
311 *ep = expr_alloc_one(E_CHOICE, NULL);
312 (*ep)->right.sym = menu->sym;
313 }
314 if (menu->list && (!menu->prompt || !menu->prompt->text)) {
315 for (last_menu = menu->list; ; last_menu = last_menu->next) {
316 last_menu->parent = parent;
317 if (!last_menu->next)
318 break;
319 }
320 last_menu->next = menu->next;
321 menu->next = menu->list;
322 menu->list = NULL;
323 }
324 }
325
326 if (sym && !(sym->flags & SYMBOL_WARNED)) {
327 if (sym->type == S_UNKNOWN)
328 menu_warn(parent, "config symbol defined "
329 "without type\n");
330
331 if (sym_is_choice(sym) && !parent->prompt)
332 menu_warn(parent, "choice must have a prompt\n");
333
334 /* Check properties connected to this symbol */
335 sym_check_prop(sym);
336 sym->flags |= SYMBOL_WARNED;
337 }
338
339 if (sym && !sym_is_optional(sym) && parent->prompt) {
340 sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
341 expr_alloc_and(parent->prompt->visible.expr,
342 expr_alloc_symbol(&symbol_mod)));
343 }
344}
345
346bool menu_is_visible(struct menu *menu)
347{
348 struct menu *child;
349 struct symbol *sym;
350 tristate visible;
351
352 if (!menu->prompt)
353 return false;
354 sym = menu->sym;
355 if (sym) {
356 sym_calc_value(sym);
357 visible = menu->prompt->visible.tri;
358 } else
359 visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
360
361 if (visible != no)
362 return true;
363 if (!sym || sym_get_tristate_value(menu->sym) == no)
364 return false;
365
366 for (child = menu->list; child; child = child->next)
367 if (menu_is_visible(child))
368 return true;
369 return false;
370}
371
372const char *menu_get_prompt(struct menu *menu)
373{
374 if (menu->prompt)
375 return _(menu->prompt->text);
376 else if (menu->sym)
377 return _(menu->sym->name);
378 return NULL;
379}
380
381struct menu *menu_get_root_menu(struct menu *menu)
382{
383 return &rootmenu;
384}
385
386struct menu *menu_get_parent_menu(struct menu *menu)
387{
388 enum prop_type type;
389
390 for (; menu != &rootmenu; menu = menu->parent) {
391 type = menu->prompt ? menu->prompt->type : 0;
392 if (type == P_MENU)
393 break;
394 }
395 return menu;
396}
397
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
new file mode 100644
index 000000000..4590cd316
--- /dev/null
+++ b/scripts/kconfig/qconf.cc
@@ -0,0 +1,1426 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <qapplication.h>
7#include <qmainwindow.h>
8#include <qtoolbar.h>
9#include <qvbox.h>
10#include <qsplitter.h>
11#include <qlistview.h>
12#include <qtextview.h>
13#include <qlineedit.h>
14#include <qmenubar.h>
15#include <qmessagebox.h>
16#include <qaction.h>
17#include <qheader.h>
18#include <qfiledialog.h>
19#include <qregexp.h>
20
21#include <stdlib.h>
22
23#include "lkc.h"
24#include "qconf.h"
25
26#include "qconf.moc"
27#include "images.c"
28
29#ifdef _
30# undef _
31# define _ qgettext
32#endif
33
34static QApplication *configApp;
35
36static inline QString qgettext(const char* str)
37{
38 return QString::fromLocal8Bit(gettext(str));
39}
40
41static inline QString qgettext(const QString& str)
42{
43 return QString::fromLocal8Bit(gettext(str.latin1()));
44}
45
46ConfigSettings::ConfigSettings()
47 : showAll(false), showName(false), showRange(false), showData(false)
48{
49}
50
51#if QT_VERSION >= 300
52/**
53 * Reads the list column settings from the application settings.
54 */
55void ConfigSettings::readListSettings()
56{
57 showAll = readBoolEntry("/kconfig/qconf/showAll", false);
58 showName = readBoolEntry("/kconfig/qconf/showName", false);
59 showRange = readBoolEntry("/kconfig/qconf/showRange", false);
60 showData = readBoolEntry("/kconfig/qconf/showData", false);
61}
62
63/**
64 * Reads a list of integer values from the application settings.
65 */
66QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
67{
68 QValueList<int> result;
69 QStringList entryList = readListEntry(key, ok);
70 if (ok) {
71 QStringList::Iterator it;
72 for (it = entryList.begin(); it != entryList.end(); ++it)
73 result.push_back((*it).toInt());
74 }
75
76 return result;
77}
78
79/**
80 * Writes a list of integer values to the application settings.
81 */
82bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
83{
84 QStringList stringList;
85 QValueList<int>::ConstIterator it;
86
87 for (it = value.begin(); it != value.end(); ++it)
88 stringList.push_back(QString::number(*it));
89 return writeEntry(key, stringList);
90}
91#endif
92
93
94/*
95 * update all the children of a menu entry
96 * removes/adds the entries from the parent widget as necessary
97 *
98 * parent: either the menu list widget or a menu entry widget
99 * menu: entry to be updated
100 */
101template <class P>
102void ConfigList::updateMenuList(P* parent, struct menu* menu)
103{
104 struct menu* child;
105 ConfigItem* item;
106 ConfigItem* last;
107 bool visible;
108 enum prop_type type;
109
110 if (!menu) {
111 while ((item = parent->firstChild()))
112 delete item;
113 return;
114 }
115
116 last = parent->firstChild();
117 if (last && !last->goParent)
118 last = 0;
119 for (child = menu->list; child; child = child->next) {
120 item = last ? last->nextSibling() : parent->firstChild();
121 type = child->prompt ? child->prompt->type : P_UNKNOWN;
122
123 switch (mode) {
124 case menuMode:
125 if (!(child->flags & MENU_ROOT))
126 goto hide;
127 break;
128 case symbolMode:
129 if (child->flags & MENU_ROOT)
130 goto hide;
131 break;
132 default:
133 break;
134 }
135
136 visible = menu_is_visible(child);
137 if (showAll || visible) {
138 if (!item || item->menu != child)
139 item = new ConfigItem(parent, last, child, visible);
140 else
141 item->testUpdateMenu(visible);
142
143 if (mode == fullMode || mode == menuMode || type != P_MENU)
144 updateMenuList(item, child);
145 else
146 updateMenuList(item, 0);
147 last = item;
148 continue;
149 }
150 hide:
151 if (item && item->menu == child) {
152 last = parent->firstChild();
153 if (last == item)
154 last = 0;
155 else while (last->nextSibling() != item)
156 last = last->nextSibling();
157 delete item;
158 }
159 }
160}
161
162#if QT_VERSION >= 300
163/*
164 * set the new data
165 * TODO check the value
166 */
167void ConfigItem::okRename(int col)
168{
169 Parent::okRename(col);
170 sym_set_string_value(menu->sym, text(dataColIdx).latin1());
171}
172#endif
173
174/*
175 * update the displayed of a menu entry
176 */
177void ConfigItem::updateMenu(void)
178{
179 ConfigList* list;
180 struct symbol* sym;
181 struct property *prop;
182 QString prompt;
183 int type;
184 tristate expr;
185
186 list = listView();
187 if (goParent) {
188 setPixmap(promptColIdx, list->menuBackPix);
189 prompt = "..";
190 goto set_prompt;
191 }
192
193 sym = menu->sym;
194 prop = menu->prompt;
195 prompt = QString::fromLocal8Bit(menu_get_prompt(menu));
196
197 if (prop) switch (prop->type) {
198 case P_MENU:
199 if (list->mode == singleMode || list->mode == symbolMode) {
200 /* a menuconfig entry is displayed differently
201 * depending whether it's at the view root or a child.
202 */
203 if (sym && list->rootEntry == menu)
204 break;
205 setPixmap(promptColIdx, list->menuPix);
206 } else {
207 if (sym)
208 break;
209 setPixmap(promptColIdx, 0);
210 }
211 goto set_prompt;
212 case P_COMMENT:
213 setPixmap(promptColIdx, 0);
214 goto set_prompt;
215 default:
216 ;
217 }
218 if (!sym)
219 goto set_prompt;
220
221 setText(nameColIdx, QString::fromLocal8Bit(sym->name));
222
223 type = sym_get_type(sym);
224 switch (type) {
225 case S_BOOLEAN:
226 case S_TRISTATE:
227 char ch;
228
229 if (!sym_is_changable(sym) && !list->showAll) {
230 setPixmap(promptColIdx, 0);
231 setText(noColIdx, QString::null);
232 setText(modColIdx, QString::null);
233 setText(yesColIdx, QString::null);
234 break;
235 }
236 expr = sym_get_tristate_value(sym);
237 switch (expr) {
238 case yes:
239 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
240 setPixmap(promptColIdx, list->choiceYesPix);
241 else
242 setPixmap(promptColIdx, list->symbolYesPix);
243 setText(yesColIdx, "Y");
244 ch = 'Y';
245 break;
246 case mod:
247 setPixmap(promptColIdx, list->symbolModPix);
248 setText(modColIdx, "M");
249 ch = 'M';
250 break;
251 default:
252 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
253 setPixmap(promptColIdx, list->choiceNoPix);
254 else
255 setPixmap(promptColIdx, list->symbolNoPix);
256 setText(noColIdx, "N");
257 ch = 'N';
258 break;
259 }
260 if (expr != no)
261 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
262 if (expr != mod)
263 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
264 if (expr != yes)
265 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
266
267 setText(dataColIdx, QChar(ch));
268 break;
269 case S_INT:
270 case S_HEX:
271 case S_STRING:
272 const char* data;
273
274 data = sym_get_string_value(sym);
275
276#if QT_VERSION >= 300
277 int i = list->mapIdx(dataColIdx);
278 if (i >= 0)
279 setRenameEnabled(i, TRUE);
280#endif
281 setText(dataColIdx, data);
282 if (type == S_STRING)
283 prompt = QString("%1: %2").arg(prompt).arg(data);
284 else
285 prompt = QString("(%2) %1").arg(prompt).arg(data);
286 break;
287 }
288 if (!sym_has_value(sym) && visible)
289 prompt += " (NEW)";
290set_prompt:
291 setText(promptColIdx, prompt);
292}
293
294void ConfigItem::testUpdateMenu(bool v)
295{
296 ConfigItem* i;
297
298 visible = v;
299 if (!menu)
300 return;
301
302 sym_calc_value(menu->sym);
303 if (menu->flags & MENU_CHANGED) {
304 /* the menu entry changed, so update all list items */
305 menu->flags &= ~MENU_CHANGED;
306 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
307 i->updateMenu();
308 } else if (listView()->updateAll)
309 updateMenu();
310}
311
312void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
313{
314 ConfigList* list = listView();
315
316 if (visible) {
317 if (isSelected() && !list->hasFocus() && list->mode == menuMode)
318 Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
319 else
320 Parent::paintCell(p, cg, column, width, align);
321 } else
322 Parent::paintCell(p, list->disabledColorGroup, column, width, align);
323}
324
325/*
326 * construct a menu entry
327 */
328void ConfigItem::init(void)
329{
330 if (menu) {
331 ConfigList* list = listView();
332 nextItem = (ConfigItem*)menu->data;
333 menu->data = this;
334
335 if (list->mode != fullMode)
336 setOpen(TRUE);
337 sym_calc_value(menu->sym);
338 }
339 updateMenu();
340}
341
342/*
343 * destruct a menu entry
344 */
345ConfigItem::~ConfigItem(void)
346{
347 if (menu) {
348 ConfigItem** ip = (ConfigItem**)&menu->data;
349 for (; *ip; ip = &(*ip)->nextItem) {
350 if (*ip == this) {
351 *ip = nextItem;
352 break;
353 }
354 }
355 }
356}
357
358void ConfigLineEdit::show(ConfigItem* i)
359{
360 item = i;
361 if (sym_get_string_value(item->menu->sym))
362 setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
363 else
364 setText(QString::null);
365 Parent::show();
366 setFocus();
367}
368
369void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
370{
371 switch (e->key()) {
372 case Key_Escape:
373 break;
374 case Key_Return:
375 case Key_Enter:
376 sym_set_string_value(item->menu->sym, text().latin1());
377 parent()->updateList(item);
378 break;
379 default:
380 Parent::keyPressEvent(e);
381 return;
382 }
383 e->accept();
384 parent()->list->setFocus();
385 hide();
386}
387
388ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv, ConfigSettings* configSettings)
389 : Parent(p), cview(cv),
390 updateAll(false),
391 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
392 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
393 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
394 showAll(false), showName(false), showRange(false), showData(false),
395 rootEntry(0)
396{
397 int i;
398
399 setSorting(-1);
400 setRootIsDecorated(TRUE);
401 disabledColorGroup = palette().active();
402 disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
403 inactivedColorGroup = palette().active();
404 inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
405
406 connect(this, SIGNAL(selectionChanged(void)),
407 SLOT(updateSelection(void)));
408
409 if (configSettings) {
410 showAll = configSettings->showAll;
411 showName = configSettings->showName;
412 showRange = configSettings->showRange;
413 showData = configSettings->showData;
414 }
415
416 for (i = 0; i < colNr; i++)
417 colMap[i] = colRevMap[i] = -1;
418 addColumn(promptColIdx, "Option");
419
420 reinit();
421}
422
423void ConfigList::reinit(void)
424{
425 removeColumn(dataColIdx);
426 removeColumn(yesColIdx);
427 removeColumn(modColIdx);
428 removeColumn(noColIdx);
429 removeColumn(nameColIdx);
430
431 if (showName)
432 addColumn(nameColIdx, "Name");
433 if (showRange) {
434 addColumn(noColIdx, "N");
435 addColumn(modColIdx, "M");
436 addColumn(yesColIdx, "Y");
437 }
438 if (showData)
439 addColumn(dataColIdx, "Value");
440
441 updateListAll();
442}
443
444void ConfigList::updateSelection(void)
445{
446 struct menu *menu;
447 enum prop_type type;
448
449 ConfigItem* item = (ConfigItem*)selectedItem();
450 if (!item)
451 return;
452
453 cview->setHelp(item);
454
455 menu = item->menu;
456 if (!menu)
457 return;
458 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
459 if (mode == menuMode && type == P_MENU)
460 emit menuSelected(menu);
461}
462
463void ConfigList::updateList(ConfigItem* item)
464{
465 ConfigItem* last = 0;
466
467 if (!rootEntry)
468 goto update;
469
470 if (rootEntry != &rootmenu && (mode == singleMode ||
471 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
472 item = firstChild();
473 if (!item)
474 item = new ConfigItem(this, 0, true);
475 last = item;
476 }
477 if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
478 rootEntry->sym && rootEntry->prompt) {
479 item = last ? last->nextSibling() : firstChild();
480 if (!item)
481 item = new ConfigItem(this, last, rootEntry, true);
482 else
483 item->testUpdateMenu(true);
484
485 updateMenuList(item, rootEntry);
486 triggerUpdate();
487 return;
488 }
489update:
490 updateMenuList(this, rootEntry);
491 triggerUpdate();
492}
493
494void ConfigList::setAllOpen(bool open)
495{
496 QListViewItemIterator it(this);
497
498 for (; it.current(); it++)
499 it.current()->setOpen(open);
500}
501
502void ConfigList::setValue(ConfigItem* item, tristate val)
503{
504 struct symbol* sym;
505 int type;
506 tristate oldval;
507
508 sym = item->menu ? item->menu->sym : 0;
509 if (!sym)
510 return;
511
512 type = sym_get_type(sym);
513 switch (type) {
514 case S_BOOLEAN:
515 case S_TRISTATE:
516 oldval = sym_get_tristate_value(sym);
517
518 if (!sym_set_tristate_value(sym, val))
519 return;
520 if (oldval == no && item->menu->list)
521 item->setOpen(TRUE);
522 parent()->updateList(item);
523 break;
524 }
525}
526
527void ConfigList::changeValue(ConfigItem* item)
528{
529 struct symbol* sym;
530 struct menu* menu;
531 int type, oldexpr, newexpr;
532
533 menu = item->menu;
534 if (!menu)
535 return;
536 sym = menu->sym;
537 if (!sym) {
538 if (item->menu->list)
539 item->setOpen(!item->isOpen());
540 return;
541 }
542
543 type = sym_get_type(sym);
544 switch (type) {
545 case S_BOOLEAN:
546 case S_TRISTATE:
547 oldexpr = sym_get_tristate_value(sym);
548 newexpr = sym_toggle_tristate_value(sym);
549 if (item->menu->list) {
550 if (oldexpr == newexpr)
551 item->setOpen(!item->isOpen());
552 else if (oldexpr == no)
553 item->setOpen(TRUE);
554 }
555 if (oldexpr != newexpr)
556 parent()->updateList(item);
557 break;
558 case S_INT:
559 case S_HEX:
560 case S_STRING:
561#if QT_VERSION >= 300
562 if (colMap[dataColIdx] >= 0)
563 item->startRename(colMap[dataColIdx]);
564 else
565#endif
566 parent()->lineEdit->show(item);
567 break;
568 }
569}
570
571void ConfigList::setRootMenu(struct menu *menu)
572{
573 enum prop_type type;
574
575 if (rootEntry == menu)
576 return;
577 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
578 if (type != P_MENU)
579 return;
580 updateMenuList(this, 0);
581 rootEntry = menu;
582 updateListAll();
583 setSelected(currentItem(), hasFocus());
584}
585
586void ConfigList::setParentMenu(void)
587{
588 ConfigItem* item;
589 struct menu *oldroot;
590
591 oldroot = rootEntry;
592 if (rootEntry == &rootmenu)
593 return;
594 setRootMenu(menu_get_parent_menu(rootEntry->parent));
595
596 QListViewItemIterator it(this);
597 for (; (item = (ConfigItem*)it.current()); it++) {
598 if (item->menu == oldroot) {
599 setCurrentItem(item);
600 ensureItemVisible(item);
601 break;
602 }
603 }
604}
605
606void ConfigList::keyPressEvent(QKeyEvent* ev)
607{
608 QListViewItem* i = currentItem();
609 ConfigItem* item;
610 struct menu *menu;
611 enum prop_type type;
612
613 if (ev->key() == Key_Escape && mode != fullMode) {
614 emit parentSelected();
615 ev->accept();
616 return;
617 }
618
619 if (!i) {
620 Parent::keyPressEvent(ev);
621 return;
622 }
623 item = (ConfigItem*)i;
624
625 switch (ev->key()) {
626 case Key_Return:
627 case Key_Enter:
628 if (item->goParent) {
629 emit parentSelected();
630 break;
631 }
632 menu = item->menu;
633 if (!menu)
634 break;
635 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
636 if (type == P_MENU && rootEntry != menu &&
637 mode != fullMode && mode != menuMode) {
638 emit menuSelected(menu);
639 break;
640 }
641 case Key_Space:
642 changeValue(item);
643 break;
644 case Key_N:
645 setValue(item, no);
646 break;
647 case Key_M:
648 setValue(item, mod);
649 break;
650 case Key_Y:
651 setValue(item, yes);
652 break;
653 default:
654 Parent::keyPressEvent(ev);
655 return;
656 }
657 ev->accept();
658}
659
660void ConfigList::contentsMousePressEvent(QMouseEvent* e)
661{
662 //QPoint p(contentsToViewport(e->pos()));
663 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
664 Parent::contentsMousePressEvent(e);
665}
666
667void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
668{
669 QPoint p(contentsToViewport(e->pos()));
670 ConfigItem* item = (ConfigItem*)itemAt(p);
671 struct menu *menu;
672 enum prop_type ptype;
673 const QPixmap* pm;
674 int idx, x;
675
676 if (!item)
677 goto skip;
678
679 menu = item->menu;
680 x = header()->offset() + p.x();
681 idx = colRevMap[header()->sectionAt(x)];
682 switch (idx) {
683 case promptColIdx:
684 pm = item->pixmap(promptColIdx);
685 if (pm) {
686 int off = header()->sectionPos(0) + itemMargin() +
687 treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
688 if (x >= off && x < off + pm->width()) {
689 if (item->goParent) {
690 emit parentSelected();
691 break;
692 } else if (!menu)
693 break;
694 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
695 if (ptype == P_MENU && rootEntry != menu &&
696 mode != fullMode && mode != menuMode)
697 emit menuSelected(menu);
698 else
699 changeValue(item);
700 }
701 }
702 break;
703 case noColIdx:
704 setValue(item, no);
705 break;
706 case modColIdx:
707 setValue(item, mod);
708 break;
709 case yesColIdx:
710 setValue(item, yes);
711 break;
712 case dataColIdx:
713 changeValue(item);
714 break;
715 }
716
717skip:
718 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
719 Parent::contentsMouseReleaseEvent(e);
720}
721
722void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
723{
724 //QPoint p(contentsToViewport(e->pos()));
725 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
726 Parent::contentsMouseMoveEvent(e);
727}
728
729void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
730{
731 QPoint p(contentsToViewport(e->pos()));
732 ConfigItem* item = (ConfigItem*)itemAt(p);
733 struct menu *menu;
734 enum prop_type ptype;
735
736 if (!item)
737 goto skip;
738 if (item->goParent) {
739 emit parentSelected();
740 goto skip;
741 }
742 menu = item->menu;
743 if (!menu)
744 goto skip;
745 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
746 if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
747 emit menuSelected(menu);
748 else if (menu->sym)
749 changeValue(item);
750
751skip:
752 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
753 Parent::contentsMouseDoubleClickEvent(e);
754}
755
756void ConfigList::focusInEvent(QFocusEvent *e)
757{
758 Parent::focusInEvent(e);
759
760 QListViewItem* item = currentItem();
761 if (!item)
762 return;
763
764 setSelected(item, TRUE);
765 emit gotFocus();
766}
767
768ConfigView* ConfigView::viewList;
769
770ConfigView::ConfigView(QWidget* parent, ConfigMainWindow* cview,
771 ConfigSettings *configSettings)
772 : Parent(parent)
773{
774 list = new ConfigList(this, cview, configSettings);
775 lineEdit = new ConfigLineEdit(this);
776 lineEdit->hide();
777
778 this->nextView = viewList;
779 viewList = this;
780}
781
782ConfigView::~ConfigView(void)
783{
784 ConfigView** vp;
785
786 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
787 if (*vp == this) {
788 *vp = nextView;
789 break;
790 }
791 }
792}
793
794void ConfigView::updateList(ConfigItem* item)
795{
796 ConfigView* v;
797
798 for (v = viewList; v; v = v->nextView)
799 v->list->updateList(item);
800}
801
802void ConfigView::updateListAll(void)
803{
804 ConfigView* v;
805
806 for (v = viewList; v; v = v->nextView)
807 v->list->updateListAll();
808}
809
810/*
811 * Construct the complete config widget
812 */
813ConfigMainWindow::ConfigMainWindow(void)
814{
815 QMenuBar* menu;
816 bool ok;
817 int x, y, width, height;
818
819 QWidget *d = configApp->desktop();
820
821 ConfigSettings* configSettings = new ConfigSettings();
822#if QT_VERSION >= 300
823 width = configSettings->readNumEntry("/kconfig/qconf/window width", d->width() - 64);
824 height = configSettings->readNumEntry("/kconfig/qconf/window height", d->height() - 64);
825 resize(width, height);
826 x = configSettings->readNumEntry("/kconfig/qconf/window x", 0, &ok);
827 if (ok)
828 y = configSettings->readNumEntry("/kconfig/qconf/window y", 0, &ok);
829 if (ok)
830 move(x, y);
831 showDebug = configSettings->readBoolEntry("/kconfig/qconf/showDebug", false);
832
833 // read list settings into configSettings, will be used later for ConfigList setup
834 configSettings->readListSettings();
835#else
836 width = d->width() - 64;
837 height = d->height() - 64;
838 resize(width, height);
839 showDebug = false;
840#endif
841
842 split1 = new QSplitter(this);
843 split1->setOrientation(QSplitter::Horizontal);
844 setCentralWidget(split1);
845
846 menuView = new ConfigView(split1, this, configSettings);
847 menuList = menuView->list;
848
849 split2 = new QSplitter(split1);
850 split2->setOrientation(QSplitter::Vertical);
851
852 // create config tree
853 configView = new ConfigView(split2, this, configSettings);
854 configList = configView->list;
855
856 helpText = new QTextView(split2);
857 helpText->setTextFormat(Qt::RichText);
858
859 setTabOrder(configList, helpText);
860 configList->setFocus();
861
862 menu = menuBar();
863 toolBar = new QToolBar("Tools", this);
864
865 backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
866 connect(backAction, SIGNAL(activated()), SLOT(goBack()));
867 backAction->setEnabled(FALSE);
868 QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
869 connect(quitAction, SIGNAL(activated()), SLOT(close()));
870 QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
871 connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
872 QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
873 connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
874 QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
875 connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
876 QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
877 connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
878 QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
879 connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
880 QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
881 connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
882
883 QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
884 showNameAction->setToggleAction(TRUE);
885 showNameAction->setOn(configList->showName);
886 connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool)));
887 QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
888 showRangeAction->setToggleAction(TRUE);
889 showRangeAction->setOn(configList->showRange);
890 connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool)));
891 QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
892 showDataAction->setToggleAction(TRUE);
893 showDataAction->setOn(configList->showData);
894 connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool)));
895 QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
896 showAllAction->setToggleAction(TRUE);
897 showAllAction->setOn(configList->showAll);
898 connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool)));
899 QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
900 showDebugAction->setToggleAction(TRUE);
901 showDebugAction->setOn(showDebug);
902 connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
903
904 QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this);
905 connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
906 QAction *showAboutAction = new QAction(NULL, "About", 0, this);
907 connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
908
909 // init tool bar
910 backAction->addTo(toolBar);
911 toolBar->addSeparator();
912 loadAction->addTo(toolBar);
913 saveAction->addTo(toolBar);
914 toolBar->addSeparator();
915 singleViewAction->addTo(toolBar);
916 splitViewAction->addTo(toolBar);
917 fullViewAction->addTo(toolBar);
918
919 // create config menu
920 QPopupMenu* config = new QPopupMenu(this);
921 menu->insertItem("&File", config);
922 loadAction->addTo(config);
923 saveAction->addTo(config);
924 saveAsAction->addTo(config);
925 config->insertSeparator();
926 quitAction->addTo(config);
927
928 // create options menu
929 QPopupMenu* optionMenu = new QPopupMenu(this);
930 menu->insertItem("&Option", optionMenu);
931 showNameAction->addTo(optionMenu);
932 showRangeAction->addTo(optionMenu);
933 showDataAction->addTo(optionMenu);
934 optionMenu->insertSeparator();
935 showAllAction->addTo(optionMenu);
936 showDebugAction->addTo(optionMenu);
937
938 // create help menu
939 QPopupMenu* helpMenu = new QPopupMenu(this);
940 menu->insertSeparator();
941 menu->insertItem("&Help", helpMenu);
942 showIntroAction->addTo(helpMenu);
943 showAboutAction->addTo(helpMenu);
944
945 connect(configList, SIGNAL(menuSelected(struct menu *)),
946 SLOT(changeMenu(struct menu *)));
947 connect(configList, SIGNAL(parentSelected()),
948 SLOT(goBack()));
949 connect(menuList, SIGNAL(menuSelected(struct menu *)),
950 SLOT(changeMenu(struct menu *)));
951
952 connect(configList, SIGNAL(gotFocus(void)),
953 SLOT(listFocusChanged(void)));
954 connect(menuList, SIGNAL(gotFocus(void)),
955 SLOT(listFocusChanged(void)));
956
957#if QT_VERSION >= 300
958 QString listMode = configSettings->readEntry("/kconfig/qconf/listMode", "symbol");
959 if (listMode == "single")
960 showSingleView();
961 else if (listMode == "full")
962 showFullView();
963 else /*if (listMode == "split")*/
964 showSplitView();
965
966 // UI setup done, restore splitter positions
967 QValueList<int> sizes = configSettings->readSizes("/kconfig/qconf/split1", &ok);
968 if (ok)
969 split1->setSizes(sizes);
970
971 sizes = configSettings->readSizes("/kconfig/qconf/split2", &ok);
972 if (ok)
973 split2->setSizes(sizes);
974#else
975 showSplitView();
976#endif
977 delete configSettings;
978}
979
980static QString print_filter(const QString &str)
981{
982 QRegExp re("[<>&\"\\n]");
983 QString res = str;
984 for (int i = 0; (i = res.find(re, i)) >= 0;) {
985 switch (res[i].latin1()) {
986 case '<':
987 res.replace(i, 1, "&lt;");
988 i += 4;
989 break;
990 case '>':
991 res.replace(i, 1, "&gt;");
992 i += 4;
993 break;
994 case '&':
995 res.replace(i, 1, "&amp;");
996 i += 5;
997 break;
998 case '"':
999 res.replace(i, 1, "&quot;");
1000 i += 6;
1001 break;
1002 case '\n':
1003 res.replace(i, 1, "<br>");
1004 i += 4;
1005 break;
1006 }
1007 }
1008 return res;
1009}
1010
1011static void expr_print_help(void *data, const char *str)
1012{
1013 reinterpret_cast<QString*>(data)->append(print_filter(str));
1014}
1015
1016/*
1017 * display a new help entry as soon as a new menu entry is selected
1018 */
1019void ConfigMainWindow::setHelp(QListViewItem* item)
1020{
1021 struct symbol* sym;
1022 struct menu* menu = 0;
1023
1024 configList->parent()->lineEdit->hide();
1025 if (item)
1026 menu = ((ConfigItem*)item)->menu;
1027 if (!menu) {
1028 helpText->setText(QString::null);
1029 return;
1030 }
1031
1032 QString head, debug, help;
1033 menu = ((ConfigItem*)item)->menu;
1034 sym = menu->sym;
1035 if (sym) {
1036 if (menu->prompt) {
1037 head += "<big><b>";
1038 head += print_filter(_(menu->prompt->text));
1039 head += "</b></big>";
1040 if (sym->name) {
1041 head += " (";
1042 head += print_filter(_(sym->name));
1043 head += ")";
1044 }
1045 } else if (sym->name) {
1046 head += "<big><b>";
1047 head += print_filter(_(sym->name));
1048 head += "</b></big>";
1049 }
1050 head += "<br><br>";
1051
1052 if (showDebug) {
1053 debug += "type: ";
1054 debug += print_filter(sym_type_name(sym->type));
1055 if (sym_is_choice(sym))
1056 debug += " (choice)";
1057 debug += "<br>";
1058 if (sym->rev_dep.expr) {
1059 debug += "reverse dep: ";
1060 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1061 debug += "<br>";
1062 }
1063 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1064 switch (prop->type) {
1065 case P_PROMPT:
1066 case P_MENU:
1067 debug += "prompt: ";
1068 debug += print_filter(_(prop->text));
1069 debug += "<br>";
1070 break;
1071 case P_DEFAULT:
1072 debug += "default: ";
1073 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1074 debug += "<br>";
1075 break;
1076 case P_CHOICE:
1077 if (sym_is_choice(sym)) {
1078 debug += "choice: ";
1079 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1080 debug += "<br>";
1081 }
1082 break;
1083 case P_SELECT:
1084 debug += "select: ";
1085 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1086 debug += "<br>";
1087 break;
1088 case P_RANGE:
1089 debug += "range: ";
1090 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1091 debug += "<br>";
1092 break;
1093 default:
1094 debug += "unknown property: ";
1095 debug += prop_get_type_name(prop->type);
1096 debug += "<br>";
1097 }
1098 if (prop->visible.expr) {
1099 debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
1100 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1101 debug += "<br>";
1102 }
1103 }
1104 debug += "<br>";
1105 }
1106
1107 help = print_filter(_(sym->help));
1108 } else if (menu->prompt) {
1109 head += "<big><b>";
1110 head += print_filter(_(menu->prompt->text));
1111 head += "</b></big><br><br>";
1112 if (showDebug) {
1113 if (menu->prompt->visible.expr) {
1114 debug += "&nbsp;&nbsp;dep: ";
1115 expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1116 debug += "<br><br>";
1117 }
1118 }
1119 }
1120 if (showDebug)
1121 debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
1122 helpText->setText(head + debug + help);
1123}
1124
1125void ConfigMainWindow::loadConfig(void)
1126{
1127 QString s = QFileDialog::getOpenFileName(".config", NULL, this);
1128 if (s.isNull())
1129 return;
1130 if (conf_read(QFile::encodeName(s)))
1131 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1132 ConfigView::updateListAll();
1133}
1134
1135void ConfigMainWindow::saveConfig(void)
1136{
1137 if (conf_write(NULL))
1138 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1139}
1140
1141void ConfigMainWindow::saveConfigAs(void)
1142{
1143 QString s = QFileDialog::getSaveFileName(".config", NULL, this);
1144 if (s.isNull())
1145 return;
1146 if (conf_write(QFile::encodeName(s)))
1147 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1148}
1149
1150void ConfigMainWindow::changeMenu(struct menu *menu)
1151{
1152 configList->setRootMenu(menu);
1153 backAction->setEnabled(TRUE);
1154}
1155
1156void ConfigMainWindow::listFocusChanged(void)
1157{
1158 if (menuList->hasFocus()) {
1159 if (menuList->mode == menuMode)
1160 configList->clearSelection();
1161 setHelp(menuList->selectedItem());
1162 } else if (configList->hasFocus()) {
1163 setHelp(configList->selectedItem());
1164 }
1165}
1166
1167void ConfigMainWindow::goBack(void)
1168{
1169 ConfigItem* item;
1170
1171 configList->setParentMenu();
1172 if (configList->rootEntry == &rootmenu)
1173 backAction->setEnabled(FALSE);
1174 item = (ConfigItem*)menuList->selectedItem();
1175 while (item) {
1176 if (item->menu == configList->rootEntry) {
1177 menuList->setSelected(item, TRUE);
1178 break;
1179 }
1180 item = (ConfigItem*)item->parent();
1181 }
1182}
1183
1184void ConfigMainWindow::showSingleView(void)
1185{
1186 menuView->hide();
1187 menuList->setRootMenu(0);
1188 configList->mode = singleMode;
1189 if (configList->rootEntry == &rootmenu)
1190 configList->updateListAll();
1191 else
1192 configList->setRootMenu(&rootmenu);
1193 configList->setAllOpen(TRUE);
1194 configList->setFocus();
1195}
1196
1197void ConfigMainWindow::showSplitView(void)
1198{
1199 configList->mode = symbolMode;
1200 if (configList->rootEntry == &rootmenu)
1201 configList->updateListAll();
1202 else
1203 configList->setRootMenu(&rootmenu);
1204 configList->setAllOpen(TRUE);
1205 configApp->processEvents();
1206 menuList->mode = menuMode;
1207 menuList->setRootMenu(&rootmenu);
1208 menuList->setAllOpen(TRUE);
1209 menuView->show();
1210 menuList->setFocus();
1211}
1212
1213void ConfigMainWindow::showFullView(void)
1214{
1215 menuView->hide();
1216 menuList->setRootMenu(0);
1217 configList->mode = fullMode;
1218 if (configList->rootEntry == &rootmenu)
1219 configList->updateListAll();
1220 else
1221 configList->setRootMenu(&rootmenu);
1222 configList->setAllOpen(FALSE);
1223 configList->setFocus();
1224}
1225
1226void ConfigMainWindow::setShowAll(bool b)
1227{
1228 if (configList->showAll == b)
1229 return;
1230 configList->showAll = b;
1231 configList->updateListAll();
1232 menuList->showAll = b;
1233 menuList->updateListAll();
1234}
1235
1236void ConfigMainWindow::setShowDebug(bool b)
1237{
1238 if (showDebug == b)
1239 return;
1240 showDebug = b;
1241}
1242
1243void ConfigMainWindow::setShowName(bool b)
1244{
1245 if (configList->showName == b)
1246 return;
1247 configList->showName = b;
1248 configList->reinit();
1249 menuList->showName = b;
1250 menuList->reinit();
1251}
1252
1253void ConfigMainWindow::setShowRange(bool b)
1254{
1255 if (configList->showRange == b)
1256 return;
1257 configList->showRange = b;
1258 configList->reinit();
1259 menuList->showRange = b;
1260 menuList->reinit();
1261}
1262
1263void ConfigMainWindow::setShowData(bool b)
1264{
1265 if (configList->showData == b)
1266 return;
1267 configList->showData = b;
1268 configList->reinit();
1269 menuList->showData = b;
1270 menuList->reinit();
1271}
1272
1273/*
1274 * ask for saving configuration before quitting
1275 * TODO ask only when something changed
1276 */
1277void ConfigMainWindow::closeEvent(QCloseEvent* e)
1278{
1279 if (!sym_change_count) {
1280 e->accept();
1281 return;
1282 }
1283 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1284 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1285 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1286 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1287 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1288 switch (mb.exec()) {
1289 case QMessageBox::Yes:
1290 conf_write(NULL);
1291 case QMessageBox::No:
1292 e->accept();
1293 break;
1294 case QMessageBox::Cancel:
1295 e->ignore();
1296 break;
1297 }
1298}
1299
1300void ConfigMainWindow::showIntro(void)
1301{
1302 static char str[] = "Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
1303 "For each option, a blank box indicates the feature is disabled, a check\n"
1304 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1305 "as a module. Clicking on the box will cycle through the three states.\n\n"
1306 "If you do not see an option (e.g., a device driver) that you believe\n"
1307 "should be present, try turning on Show All Options under the Options menu.\n"
1308 "Although there is no cross reference yet to help you figure out what other\n"
1309 "options must be enabled to support the option you are interested in, you can\n"
1310 "still view the help of a grayed-out option.\n\n"
1311 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1312 "which you can then match by examining other options.\n\n";
1313
1314 QMessageBox::information(this, "qconf", str);
1315}
1316
1317void ConfigMainWindow::showAbout(void)
1318{
1319 static char str[] = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1320 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1321
1322 QMessageBox::information(this, "qconf", str);
1323}
1324
1325void ConfigMainWindow::saveSettings(void)
1326{
1327#if QT_VERSION >= 300
1328 ConfigSettings *configSettings = new ConfigSettings;
1329 configSettings->writeEntry("/kconfig/qconf/window x", pos().x());
1330 configSettings->writeEntry("/kconfig/qconf/window y", pos().y());
1331 configSettings->writeEntry("/kconfig/qconf/window width", size().width());
1332 configSettings->writeEntry("/kconfig/qconf/window height", size().height());
1333 configSettings->writeEntry("/kconfig/qconf/showName", configList->showName);
1334 configSettings->writeEntry("/kconfig/qconf/showRange", configList->showRange);
1335 configSettings->writeEntry("/kconfig/qconf/showData", configList->showData);
1336 configSettings->writeEntry("/kconfig/qconf/showAll", configList->showAll);
1337 configSettings->writeEntry("/kconfig/qconf/showDebug", showDebug);
1338
1339 QString entry;
1340 switch(configList->mode) {
1341 case singleMode :
1342 entry = "single";
1343 break;
1344
1345 case symbolMode :
1346 entry = "split";
1347 break;
1348
1349 case fullMode :
1350 entry = "full";
1351 break;
1352 }
1353 configSettings->writeEntry("/kconfig/qconf/listMode", entry);
1354
1355 configSettings->writeSizes("/kconfig/qconf/split1", split1->sizes());
1356 configSettings->writeSizes("/kconfig/qconf/split2", split2->sizes());
1357
1358 delete configSettings;
1359#endif
1360}
1361
1362void fixup_rootmenu(struct menu *menu)
1363{
1364 struct menu *child;
1365 static int menu_cnt = 0;
1366
1367 menu->flags |= MENU_ROOT;
1368 for (child = menu->list; child; child = child->next) {
1369 if (child->prompt && child->prompt->type == P_MENU) {
1370 menu_cnt++;
1371 fixup_rootmenu(child);
1372 menu_cnt--;
1373 } else if (!menu_cnt)
1374 fixup_rootmenu(child);
1375 }
1376}
1377
1378static const char *progname;
1379
1380static void usage(void)
1381{
1382 printf("%s <config>\n", progname);
1383 exit(0);
1384}
1385
1386int main(int ac, char** av)
1387{
1388 ConfigMainWindow* v;
1389 const char *name;
1390
1391 bindtextdomain(PACKAGE, LOCALEDIR);
1392 textdomain(PACKAGE);
1393
1394#ifndef LKC_DIRECT_LINK
1395 kconfig_load();
1396#endif
1397
1398 progname = av[0];
1399 configApp = new QApplication(ac, av);
1400 if (ac > 1 && av[1][0] == '-') {
1401 switch (av[1][1]) {
1402 case 'h':
1403 case '?':
1404 usage();
1405 }
1406 name = av[2];
1407 } else
1408 name = av[1];
1409 if (!name)
1410 usage();
1411
1412 conf_parse(name);
1413 fixup_rootmenu(&rootmenu);
1414 conf_read(NULL);
1415 //zconfdump(stdout);
1416
1417 v = new ConfigMainWindow();
1418
1419 //zconfdump(stdout);
1420 v->show();
1421 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1422 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1423 configApp->exec();
1424
1425 return 0;
1426}
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
new file mode 100644
index 000000000..e52f3e90b
--- /dev/null
+++ b/scripts/kconfig/qconf.h
@@ -0,0 +1,263 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <qlistview.h>
7#if QT_VERSION >= 300
8#include <qsettings.h>
9#else
10class QSettings { };
11#endif
12
13class ConfigList;
14class ConfigItem;
15class ConfigLineEdit;
16class ConfigMainWindow;
17
18
19class ConfigSettings : public QSettings {
20public:
21 ConfigSettings();
22
23#if QT_VERSION >= 300
24 void readListSettings();
25 QValueList<int> readSizes(const QString& key, bool *ok);
26 bool writeSizes(const QString& key, const QValueList<int>& value);
27#endif
28
29 bool showAll;
30 bool showName;
31 bool showRange;
32 bool showData;
33};
34
35class ConfigView : public QVBox {
36 Q_OBJECT
37 typedef class QVBox Parent;
38public:
39 ConfigView(QWidget* parent, ConfigMainWindow* cview, ConfigSettings* configSettings);
40 ~ConfigView(void);
41 static void updateList(ConfigItem* item);
42 static void updateListAll(void);
43
44public:
45 ConfigList* list;
46 ConfigLineEdit* lineEdit;
47
48 static ConfigView* viewList;
49 ConfigView* nextView;
50};
51
52enum colIdx {
53 promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
54};
55enum listMode {
56 singleMode, menuMode, symbolMode, fullMode
57};
58
59class ConfigList : public QListView {
60 Q_OBJECT
61 typedef class QListView Parent;
62public:
63 ConfigList(ConfigView* p, ConfigMainWindow* cview, ConfigSettings *configSettings);
64 void reinit(void);
65 ConfigView* parent(void) const
66 {
67 return (ConfigView*)Parent::parent();
68 }
69
70protected:
71 ConfigMainWindow* cview;
72
73 void keyPressEvent(QKeyEvent *e);
74 void contentsMousePressEvent(QMouseEvent *e);
75 void contentsMouseReleaseEvent(QMouseEvent *e);
76 void contentsMouseMoveEvent(QMouseEvent *e);
77 void contentsMouseDoubleClickEvent(QMouseEvent *e);
78 void focusInEvent(QFocusEvent *e);
79public slots:
80 void setRootMenu(struct menu *menu);
81
82 void updateList(ConfigItem *item);
83 void setValue(ConfigItem* item, tristate val);
84 void changeValue(ConfigItem* item);
85 void updateSelection(void);
86signals:
87 void menuSelected(struct menu *menu);
88 void parentSelected(void);
89 void gotFocus(void);
90
91public:
92 void updateListAll(void)
93 {
94 updateAll = true;
95 updateList(NULL);
96 updateAll = false;
97 }
98 ConfigList* listView()
99 {
100 return this;
101 }
102 ConfigItem* firstChild() const
103 {
104 return (ConfigItem *)Parent::firstChild();
105 }
106 int mapIdx(colIdx idx)
107 {
108 return colMap[idx];
109 }
110 void addColumn(colIdx idx, const QString& label)
111 {
112 colMap[idx] = Parent::addColumn(label);
113 colRevMap[colMap[idx]] = idx;
114 }
115 void removeColumn(colIdx idx)
116 {
117 int col = colMap[idx];
118 if (col >= 0) {
119 Parent::removeColumn(col);
120 colRevMap[col] = colMap[idx] = -1;
121 }
122 }
123 void setAllOpen(bool open);
124 void setParentMenu(void);
125
126 template <class P>
127 void updateMenuList(P*, struct menu*);
128
129 bool updateAll;
130
131 QPixmap symbolYesPix, symbolModPix, symbolNoPix;
132 QPixmap choiceYesPix, choiceNoPix;
133 QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
134
135 bool showAll, showName, showRange, showData;
136 enum listMode mode;
137 struct menu *rootEntry;
138 QColorGroup disabledColorGroup;
139 QColorGroup inactivedColorGroup;
140
141private:
142 int colMap[colNr];
143 int colRevMap[colNr];
144};
145
146class ConfigItem : public QListViewItem {
147 typedef class QListViewItem Parent;
148public:
149 ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v)
150 : Parent(parent, after), menu(m), visible(v), goParent(false)
151 {
152 init();
153 }
154 ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
155 : Parent(parent, after), menu(m), visible(v), goParent(false)
156 {
157 init();
158 }
159 ConfigItem(QListView *parent, ConfigItem *after, bool v)
160 : Parent(parent, after), menu(0), visible(v), goParent(true)
161 {
162 init();
163 }
164 ~ConfigItem(void);
165 void init(void);
166#if QT_VERSION >= 300
167 void okRename(int col);
168#endif
169 void updateMenu(void);
170 void testUpdateMenu(bool v);
171 ConfigList* listView() const
172 {
173 return (ConfigList*)Parent::listView();
174 }
175 ConfigItem* firstChild() const
176 {
177 return (ConfigItem *)Parent::firstChild();
178 }
179 ConfigItem* nextSibling() const
180 {
181 return (ConfigItem *)Parent::nextSibling();
182 }
183 void setText(colIdx idx, const QString& text)
184 {
185 Parent::setText(listView()->mapIdx(idx), text);
186 }
187 QString text(colIdx idx) const
188 {
189 return Parent::text(listView()->mapIdx(idx));
190 }
191 void setPixmap(colIdx idx, const QPixmap& pm)
192 {
193 Parent::setPixmap(listView()->mapIdx(idx), pm);
194 }
195 const QPixmap* pixmap(colIdx idx) const
196 {
197 return Parent::pixmap(listView()->mapIdx(idx));
198 }
199 void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
200
201 ConfigItem* nextItem;
202 struct menu *menu;
203 bool visible;
204 bool goParent;
205};
206
207class ConfigLineEdit : public QLineEdit {
208 Q_OBJECT
209 typedef class QLineEdit Parent;
210public:
211 ConfigLineEdit(ConfigView* parent)
212 : Parent(parent)
213 { }
214 ConfigView* parent(void) const
215 {
216 return (ConfigView*)Parent::parent();
217 }
218 void show(ConfigItem *i);
219 void keyPressEvent(QKeyEvent *e);
220
221public:
222 ConfigItem *item;
223};
224
225class ConfigMainWindow : public QMainWindow {
226 Q_OBJECT
227public:
228 ConfigMainWindow(void);
229public slots:
230 void setHelp(QListViewItem* item);
231 void changeMenu(struct menu *);
232 void listFocusChanged(void);
233 void goBack(void);
234 void loadConfig(void);
235 void saveConfig(void);
236 void saveConfigAs(void);
237 void showSingleView(void);
238 void showSplitView(void);
239 void showFullView(void);
240 void setShowAll(bool);
241 void setShowDebug(bool);
242 void setShowRange(bool);
243 void setShowName(bool);
244 void setShowData(bool);
245 void showIntro(void);
246 void showAbout(void);
247 void saveSettings(void);
248
249protected:
250 void closeEvent(QCloseEvent *e);
251
252 ConfigView *menuView;
253 ConfigList *menuList;
254 ConfigView *configView;
255 ConfigList *configList;
256 QTextView *helpText;
257 QToolBar *toolBar;
258 QAction *backAction;
259 QSplitter* split1;
260 QSplitter* split2;
261
262 bool showDebug;
263};
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
new file mode 100644
index 000000000..3d7877afc
--- /dev/null
+++ b/scripts/kconfig/symbol.c
@@ -0,0 +1,882 @@
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <ctype.h>
7#include <stdlib.h>
8#include <string.h>
9#include <regex.h>
10#include <sys/utsname.h>
11
12#define LKC_DIRECT_LINK
13#include "lkc.h"
14
15struct symbol symbol_yes = {
16 .name = "y",
17 .curr = { "y", yes },
18 .flags = SYMBOL_YES|SYMBOL_VALID,
19}, symbol_mod = {
20 .name = "m",
21 .curr = { "m", mod },
22 .flags = SYMBOL_MOD|SYMBOL_VALID,
23}, symbol_no = {
24 .name = "n",
25 .curr = { "n", no },
26 .flags = SYMBOL_NO|SYMBOL_VALID,
27}, symbol_empty = {
28 .name = "",
29 .curr = { "", no },
30 .flags = SYMBOL_VALID,
31};
32
33int sym_change_count;
34struct symbol *modules_sym;
35tristate modules_val;
36
37void sym_add_default(struct symbol *sym, const char *def)
38{
39 struct property *prop = prop_alloc(P_DEFAULT, sym);
40
41 prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
42}
43
44void sym_init(void)
45{
46 struct symbol *sym;
47 struct utsname uts;
48 char *p;
49 static bool inited = false;
50
51 if (inited)
52 return;
53 inited = true;
54
55 uname(&uts);
56
57 sym = sym_lookup("ARCH", 0);
58 sym->type = S_STRING;
59 sym->flags |= SYMBOL_AUTO;
60 p = getenv("ARCH");
61 if (p)
62 sym_add_default(sym, p);
63
64 sym = sym_lookup("KERNELVERSION", 0);
65 sym->type = S_STRING;
66 sym->flags |= SYMBOL_AUTO;
67 p = getenv("KERNELVERSION");
68 if (p)
69 sym_add_default(sym, p);
70
71 sym = sym_lookup("UNAME_RELEASE", 0);
72 sym->type = S_STRING;
73 sym->flags |= SYMBOL_AUTO;
74 sym_add_default(sym, uts.release);
75}
76
77enum symbol_type sym_get_type(struct symbol *sym)
78{
79 enum symbol_type type = sym->type;
80
81 if (type == S_TRISTATE) {
82 if (sym_is_choice_value(sym) && sym->visible == yes)
83 type = S_BOOLEAN;
84 else if (modules_val == no)
85 type = S_BOOLEAN;
86 }
87 return type;
88}
89
90const char *sym_type_name(enum symbol_type type)
91{
92 switch (type) {
93 case S_BOOLEAN:
94 return "boolean";
95 case S_TRISTATE:
96 return "tristate";
97 case S_INT:
98 return "integer";
99 case S_HEX:
100 return "hex";
101 case S_STRING:
102 return "string";
103 case S_UNKNOWN:
104 return "unknown";
105 case S_OTHER:
106 break;
107 }
108 return "???";
109}
110
111struct property *sym_get_choice_prop(struct symbol *sym)
112{
113 struct property *prop;
114
115 for_all_choices(sym, prop)
116 return prop;
117 return NULL;
118}
119
120struct property *sym_get_default_prop(struct symbol *sym)
121{
122 struct property *prop;
123
124 for_all_defaults(sym, prop) {
125 prop->visible.tri = expr_calc_value(prop->visible.expr);
126 if (prop->visible.tri != no)
127 return prop;
128 }
129 return NULL;
130}
131
132struct property *sym_get_range_prop(struct symbol *sym)
133{
134 struct property *prop;
135
136 for_all_properties(sym, prop, P_RANGE) {
137 prop->visible.tri = expr_calc_value(prop->visible.expr);
138 if (prop->visible.tri != no)
139 return prop;
140 }
141 return NULL;
142}
143
144static int sym_get_range_val(struct symbol *sym, int base)
145{
146 sym_calc_value(sym);
147 switch (sym->type) {
148 case S_INT:
149 base = 10;
150 break;
151 case S_HEX:
152 base = 16;
153 break;
154 default:
155 break;
156 }
157 return strtol(sym->curr.val, NULL, base);
158}
159
160static void sym_validate_range(struct symbol *sym)
161{
162 struct property *prop;
163 int base, val, val2;
164 char str[64];
165
166 switch (sym->type) {
167 case S_INT:
168 base = 10;
169 break;
170 case S_HEX:
171 base = 16;
172 break;
173 default:
174 return;
175 }
176 prop = sym_get_range_prop(sym);
177 if (!prop)
178 return;
179 val = strtol(sym->curr.val, NULL, base);
180 val2 = sym_get_range_val(prop->expr->left.sym, base);
181 if (val >= val2) {
182 val2 = sym_get_range_val(prop->expr->right.sym, base);
183 if (val <= val2)
184 return;
185 }
186 if (sym->type == S_INT)
187 sprintf(str, "%d", val2);
188 else
189 sprintf(str, "0x%x", val2);
190 sym->curr.val = strdup(str);
191}
192
193static void sym_calc_visibility(struct symbol *sym)
194{
195 struct property *prop;
196 tristate tri;
197
198 /* any prompt visible? */
199 tri = no;
200 for_all_prompts(sym, prop) {
201 prop->visible.tri = expr_calc_value(prop->visible.expr);
202 tri = E_OR(tri, prop->visible.tri);
203 }
204 if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
205 tri = yes;
206 if (sym->visible != tri) {
207 sym->visible = tri;
208 sym_set_changed(sym);
209 }
210 if (sym_is_choice_value(sym))
211 return;
212 tri = no;
213 if (sym->rev_dep.expr)
214 tri = expr_calc_value(sym->rev_dep.expr);
215 if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
216 tri = yes;
217 if (sym->rev_dep.tri != tri) {
218 sym->rev_dep.tri = tri;
219 sym_set_changed(sym);
220 }
221}
222
223static struct symbol *sym_calc_choice(struct symbol *sym)
224{
225 struct symbol *def_sym;
226 struct property *prop;
227 struct expr *e;
228
229 /* is the user choice visible? */
230 def_sym = sym->user.val;
231 if (def_sym) {
232 sym_calc_visibility(def_sym);
233 if (def_sym->visible != no)
234 return def_sym;
235 }
236
237 /* any of the defaults visible? */
238 for_all_defaults(sym, prop) {
239 prop->visible.tri = expr_calc_value(prop->visible.expr);
240 if (prop->visible.tri == no)
241 continue;
242 def_sym = prop_get_symbol(prop);
243 sym_calc_visibility(def_sym);
244 if (def_sym->visible != no)
245 return def_sym;
246 }
247
248 /* just get the first visible value */
249 prop = sym_get_choice_prop(sym);
250 for (e = prop->expr; e; e = e->left.expr) {
251 def_sym = e->right.sym;
252 sym_calc_visibility(def_sym);
253 if (def_sym->visible != no)
254 return def_sym;
255 }
256
257 /* no choice? reset tristate value */
258 sym->curr.tri = no;
259 return NULL;
260}
261
262void sym_calc_value(struct symbol *sym)
263{
264 struct symbol_value newval, oldval;
265 struct property *prop;
266 struct expr *e;
267
268 if (!sym)
269 return;
270
271 if (sym->flags & SYMBOL_VALID)
272 return;
273 sym->flags |= SYMBOL_VALID;
274
275 oldval = sym->curr;
276
277 switch (sym->type) {
278 case S_INT:
279 case S_HEX:
280 case S_STRING:
281 newval = symbol_empty.curr;
282 break;
283 case S_BOOLEAN:
284 case S_TRISTATE:
285 newval = symbol_no.curr;
286 break;
287 default:
288 sym->curr.val = sym->name;
289 sym->curr.tri = no;
290 return;
291 }
292 if (!sym_is_choice_value(sym))
293 sym->flags &= ~SYMBOL_WRITE;
294
295 sym_calc_visibility(sym);
296
297 /* set default if recursively called */
298 sym->curr = newval;
299
300 switch (sym_get_type(sym)) {
301 case S_BOOLEAN:
302 case S_TRISTATE:
303 if (sym_is_choice_value(sym) && sym->visible == yes) {
304 prop = sym_get_choice_prop(sym);
305 newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
306 } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
307 sym->flags |= SYMBOL_WRITE;
308 if (sym_has_value(sym))
309 newval.tri = sym->user.tri;
310 else if (!sym_is_choice(sym)) {
311 prop = sym_get_default_prop(sym);
312 if (prop)
313 newval.tri = expr_calc_value(prop->expr);
314 }
315 newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
316 } else if (!sym_is_choice(sym)) {
317 prop = sym_get_default_prop(sym);
318 if (prop) {
319 sym->flags |= SYMBOL_WRITE;
320 newval.tri = expr_calc_value(prop->expr);
321 }
322 }
323 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
324 newval.tri = yes;
325 break;
326 case S_STRING:
327 case S_HEX:
328 case S_INT:
329 if (sym->visible != no) {
330 sym->flags |= SYMBOL_WRITE;
331 if (sym_has_value(sym)) {
332 newval.val = sym->user.val;
333 break;
334 }
335 }
336 prop = sym_get_default_prop(sym);
337 if (prop) {
338 struct symbol *ds = prop_get_symbol(prop);
339 if (ds) {
340 sym->flags |= SYMBOL_WRITE;
341 sym_calc_value(ds);
342 newval.val = ds->curr.val;
343 }
344 }
345 break;
346 default:
347 ;
348 }
349
350 sym->curr = newval;
351 if (sym_is_choice(sym) && newval.tri == yes)
352 sym->curr.val = sym_calc_choice(sym);
353 sym_validate_range(sym);
354
355 if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
356 sym_set_changed(sym);
357 if (modules_sym == sym)
358 modules_val = modules_sym->curr.tri;
359
360 if (sym_is_choice(sym)) {
361 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
362 prop = sym_get_choice_prop(sym);
363 for (e = prop->expr; e; e = e->left.expr) {
364 e->right.sym->flags |= flags;
365 if (flags & SYMBOL_CHANGED)
366 sym_set_changed(e->right.sym);
367 }
368 }
369}
370
371void sym_clear_all_valid(void)
372{
373 struct symbol *sym;
374 int i;
375
376 for_all_symbols(i, sym)
377 sym->flags &= ~SYMBOL_VALID;
378 sym_change_count++;
379 if (modules_sym)
380 sym_calc_value(modules_sym);
381}
382
383void sym_set_changed(struct symbol *sym)
384{
385 struct property *prop;
386
387 sym->flags |= SYMBOL_CHANGED;
388 for (prop = sym->prop; prop; prop = prop->next) {
389 if (prop->menu)
390 prop->menu->flags |= MENU_CHANGED;
391 }
392}
393
394void sym_set_all_changed(void)
395{
396 struct symbol *sym;
397 int i;
398
399 for_all_symbols(i, sym)
400 sym_set_changed(sym);
401}
402
403bool sym_tristate_within_range(struct symbol *sym, tristate val)
404{
405 int type = sym_get_type(sym);
406
407 if (sym->visible == no)
408 return false;
409
410 if (type != S_BOOLEAN && type != S_TRISTATE)
411 return false;
412
413 if (type == S_BOOLEAN && val == mod)
414 return false;
415 if (sym->visible <= sym->rev_dep.tri)
416 return false;
417 if (sym_is_choice_value(sym) && sym->visible == yes)
418 return val == yes;
419 return val >= sym->rev_dep.tri && val <= sym->visible;
420}
421
422bool sym_set_tristate_value(struct symbol *sym, tristate val)
423{
424 tristate oldval = sym_get_tristate_value(sym);
425
426 if (oldval != val && !sym_tristate_within_range(sym, val))
427 return false;
428
429 if (sym->flags & SYMBOL_NEW) {
430 sym->flags &= ~SYMBOL_NEW;
431 sym_set_changed(sym);
432 }
433 /*
434 * setting a choice value also resets the new flag of the choice
435 * symbol and all other choice values.
436 */
437 if (sym_is_choice_value(sym) && val == yes) {
438 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
439 struct property *prop;
440 struct expr *e;
441
442 cs->user.val = sym;
443 cs->flags &= ~SYMBOL_NEW;
444 prop = sym_get_choice_prop(cs);
445 for (e = prop->expr; e; e = e->left.expr) {
446 if (e->right.sym->visible != no)
447 e->right.sym->flags &= ~SYMBOL_NEW;
448 }
449 }
450
451 sym->user.tri = val;
452 if (oldval != val) {
453 sym_clear_all_valid();
454 if (sym == modules_sym)
455 sym_set_all_changed();
456 }
457
458 return true;
459}
460
461tristate sym_toggle_tristate_value(struct symbol *sym)
462{
463 tristate oldval, newval;
464
465 oldval = newval = sym_get_tristate_value(sym);
466 do {
467 switch (newval) {
468 case no:
469 newval = mod;
470 break;
471 case mod:
472 newval = yes;
473 break;
474 case yes:
475 newval = no;
476 break;
477 }
478 if (sym_set_tristate_value(sym, newval))
479 break;
480 } while (oldval != newval);
481 return newval;
482}
483
484bool sym_string_valid(struct symbol *sym, const char *str)
485{
486 signed char ch;
487
488 switch (sym->type) {
489 case S_STRING:
490 return true;
491 case S_INT:
492 ch = *str++;
493 if (ch == '-')
494 ch = *str++;
495 if (!isdigit(ch))
496 return false;
497 if (ch == '0' && *str != 0)
498 return false;
499 while ((ch = *str++)) {
500 if (!isdigit(ch))
501 return false;
502 }
503 return true;
504 case S_HEX:
505 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
506 str += 2;
507 ch = *str++;
508 do {
509 if (!isxdigit(ch))
510 return false;
511 } while ((ch = *str++));
512 return true;
513 case S_BOOLEAN:
514 case S_TRISTATE:
515 switch (str[0]) {
516 case 'y': case 'Y':
517 case 'm': case 'M':
518 case 'n': case 'N':
519 return true;
520 }
521 return false;
522 default:
523 return false;
524 }
525}
526
527bool sym_string_within_range(struct symbol *sym, const char *str)
528{
529 struct property *prop;
530 int val;
531
532 switch (sym->type) {
533 case S_STRING:
534 return sym_string_valid(sym, str);
535 case S_INT:
536 if (!sym_string_valid(sym, str))
537 return false;
538 prop = sym_get_range_prop(sym);
539 if (!prop)
540 return true;
541 val = strtol(str, NULL, 10);
542 return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
543 val <= sym_get_range_val(prop->expr->right.sym, 10);
544 case S_HEX:
545 if (!sym_string_valid(sym, str))
546 return false;
547 prop = sym_get_range_prop(sym);
548 if (!prop)
549 return true;
550 val = strtol(str, NULL, 16);
551 return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
552 val <= sym_get_range_val(prop->expr->right.sym, 16);
553 case S_BOOLEAN:
554 case S_TRISTATE:
555 switch (str[0]) {
556 case 'y': case 'Y':
557 return sym_tristate_within_range(sym, yes);
558 case 'm': case 'M':
559 return sym_tristate_within_range(sym, mod);
560 case 'n': case 'N':
561 return sym_tristate_within_range(sym, no);
562 }
563 return false;
564 default:
565 return false;
566 }
567}
568
569bool sym_set_string_value(struct symbol *sym, const char *newval)
570{
571 const char *oldval;
572 char *val;
573 int size;
574
575 switch (sym->type) {
576 case S_BOOLEAN:
577 case S_TRISTATE:
578 switch (newval[0]) {
579 case 'y': case 'Y':
580 return sym_set_tristate_value(sym, yes);
581 case 'm': case 'M':
582 return sym_set_tristate_value(sym, mod);
583 case 'n': case 'N':
584 return sym_set_tristate_value(sym, no);
585 }
586 return false;
587 default:
588 ;
589 }
590
591 if (!sym_string_within_range(sym, newval))
592 return false;
593
594 if (sym->flags & SYMBOL_NEW) {
595 sym->flags &= ~SYMBOL_NEW;
596 sym_set_changed(sym);
597 }
598
599 oldval = sym->user.val;
600 size = strlen(newval) + 1;
601 if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
602 size += 2;
603 sym->user.val = val = malloc(size);
604 *val++ = '0';
605 *val++ = 'x';
606 } else if (!oldval || strcmp(oldval, newval))
607 sym->user.val = val = malloc(size);
608 else
609 return true;
610
611 strcpy(val, newval);
612 free((void *)oldval);
613 sym_clear_all_valid();
614
615 return true;
616}
617
618const char *sym_get_string_value(struct symbol *sym)
619{
620 tristate val;
621
622 switch (sym->type) {
623 case S_BOOLEAN:
624 case S_TRISTATE:
625 val = sym_get_tristate_value(sym);
626 switch (val) {
627 case no:
628 return "n";
629 case mod:
630 return "m";
631 case yes:
632 return "y";
633 }
634 break;
635 default:
636 ;
637 }
638 return (const char *)sym->curr.val;
639}
640
641bool sym_is_changable(struct symbol *sym)
642{
643 return sym->visible > sym->rev_dep.tri;
644}
645
646struct symbol *sym_lookup(const char *name, int isconst)
647{
648 struct symbol *symbol;
649 const char *ptr;
650 char *new_name;
651 int hash = 0;
652
653 if (name) {
654 if (name[0] && !name[1]) {
655 switch (name[0]) {
656 case 'y': return &symbol_yes;
657 case 'm': return &symbol_mod;
658 case 'n': return &symbol_no;
659 }
660 }
661 for (ptr = name; *ptr; ptr++)
662 hash += *ptr;
663 hash &= 0xff;
664
665 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
666 if (!strcmp(symbol->name, name)) {
667 if ((isconst && symbol->flags & SYMBOL_CONST) ||
668 (!isconst && !(symbol->flags & SYMBOL_CONST)))
669 return symbol;
670 }
671 }
672 new_name = strdup(name);
673 } else {
674 new_name = NULL;
675 hash = 256;
676 }
677
678 symbol = malloc(sizeof(*symbol));
679 memset(symbol, 0, sizeof(*symbol));
680 symbol->name = new_name;
681 symbol->type = S_UNKNOWN;
682 symbol->flags = SYMBOL_NEW;
683 if (isconst)
684 symbol->flags |= SYMBOL_CONST;
685
686 symbol->next = symbol_hash[hash];
687 symbol_hash[hash] = symbol;
688
689 return symbol;
690}
691
692struct symbol *sym_find(const char *name)
693{
694 struct symbol *symbol = NULL;
695 const char *ptr;
696 int hash = 0;
697
698 if (!name)
699 return NULL;
700
701 if (name[0] && !name[1]) {
702 switch (name[0]) {
703 case 'y': return &symbol_yes;
704 case 'm': return &symbol_mod;
705 case 'n': return &symbol_no;
706 }
707 }
708 for (ptr = name; *ptr; ptr++)
709 hash += *ptr;
710 hash &= 0xff;
711
712 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
713 if (!strcmp(symbol->name, name) &&
714 !(symbol->flags & SYMBOL_CONST))
715 break;
716 }
717
718 return symbol;
719}
720
721struct symbol **sym_re_search(const char *pattern)
722{
723 struct symbol *sym, **sym_arr = NULL;
724 int i, cnt, size;
725 regex_t re;
726
727 cnt = size = 0;
728 /* Skip if empty */
729 if (strlen(pattern) == 0)
730 return NULL;
731 if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
732 return NULL;
733
734 for_all_symbols(i, sym) {
735 if (sym->flags & SYMBOL_CONST || !sym->name)
736 continue;
737 if (regexec(&re, sym->name, 0, NULL, 0))
738 continue;
739 if (cnt + 1 >= size) {
740 void *tmp = sym_arr;
741 size += 16;
742 sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
743 if (!sym_arr) {
744 free(tmp);
745 return NULL;
746 }
747 }
748 sym_arr[cnt++] = sym;
749 }
750 if (sym_arr)
751 sym_arr[cnt] = NULL;
752 regfree(&re);
753
754 return sym_arr;
755}
756
757
758struct symbol *sym_check_deps(struct symbol *sym);
759
760static struct symbol *sym_check_expr_deps(struct expr *e)
761{
762 struct symbol *sym;
763
764 if (!e)
765 return NULL;
766 switch (e->type) {
767 case E_OR:
768 case E_AND:
769 sym = sym_check_expr_deps(e->left.expr);
770 if (sym)
771 return sym;
772 return sym_check_expr_deps(e->right.expr);
773 case E_NOT:
774 return sym_check_expr_deps(e->left.expr);
775 case E_EQUAL:
776 case E_UNEQUAL:
777 sym = sym_check_deps(e->left.sym);
778 if (sym)
779 return sym;
780 return sym_check_deps(e->right.sym);
781 case E_SYMBOL:
782 return sym_check_deps(e->left.sym);
783 default:
784 break;
785 }
786 printf("Oops! How to check %d?\n", e->type);
787 return NULL;
788}
789
790struct symbol *sym_check_deps(struct symbol *sym)
791{
792 struct symbol *sym2;
793 struct property *prop;
794
795 if (sym->flags & SYMBOL_CHECK) {
796 printf("Warning! Found recursive dependency: %s", sym->name);
797 return sym;
798 }
799 if (sym->flags & SYMBOL_CHECKED)
800 return NULL;
801
802 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
803 sym2 = sym_check_expr_deps(sym->rev_dep.expr);
804 if (sym2)
805 goto out;
806
807 for (prop = sym->prop; prop; prop = prop->next) {
808 if (prop->type == P_CHOICE || prop->type == P_SELECT)
809 continue;
810 sym2 = sym_check_expr_deps(prop->visible.expr);
811 if (sym2)
812 goto out;
813 if (prop->type != P_DEFAULT || sym_is_choice(sym))
814 continue;
815 sym2 = sym_check_expr_deps(prop->expr);
816 if (sym2)
817 goto out;
818 }
819out:
820 if (sym2) {
821 printf(" %s", sym->name);
822 if (sym2 == sym) {
823 printf("\n");
824 sym2 = NULL;
825 }
826 }
827 sym->flags &= ~SYMBOL_CHECK;
828 return sym2;
829}
830
831struct property *prop_alloc(enum prop_type type, struct symbol *sym)
832{
833 struct property *prop;
834 struct property **propp;
835
836 prop = malloc(sizeof(*prop));
837 memset(prop, 0, sizeof(*prop));
838 prop->type = type;
839 prop->sym = sym;
840 prop->file = current_file;
841 prop->lineno = zconf_lineno();
842
843 /* append property to the prop list of symbol */
844 if (sym) {
845 for (propp = &sym->prop; *propp; propp = &(*propp)->next)
846 ;
847 *propp = prop;
848 }
849
850 return prop;
851}
852
853struct symbol *prop_get_symbol(struct property *prop)
854{
855 if (prop->expr && (prop->expr->type == E_SYMBOL ||
856 prop->expr->type == E_CHOICE))
857 return prop->expr->left.sym;
858 return NULL;
859}
860
861const char *prop_get_type_name(enum prop_type type)
862{
863 switch (type) {
864 case P_PROMPT:
865 return "prompt";
866 case P_COMMENT:
867 return "comment";
868 case P_MENU:
869 return "menu";
870 case P_DEFAULT:
871 return "default";
872 case P_CHOICE:
873 return "choice";
874 case P_SELECT:
875 return "select";
876 case P_RANGE:
877 return "range";
878 case P_UNKNOWN:
879 break;
880 }
881 return "unknown";
882}
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
new file mode 100644
index 000000000..aea8d56ce
--- /dev/null
+++ b/scripts/kconfig/util.c
@@ -0,0 +1,109 @@
1/*
2 * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
3 * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
4 *
5 * Released under the terms of the GNU GPL v2.0.
6 */
7
8#include <string.h>
9#include "lkc.h"
10
11/* file already present in list? If not add it */
12struct file *file_lookup(const char *name)
13{
14 struct file *file;
15
16 for (file = file_list; file; file = file->next) {
17 if (!strcmp(name, file->name))
18 return file;
19 }
20
21 file = malloc(sizeof(*file));
22 memset(file, 0, sizeof(*file));
23 file->name = strdup(name);
24 file->next = file_list;
25 file_list = file;
26 return file;
27}
28
29/* write a dependency file as used by kbuild to track dependencies */
30int file_write_dep(const char *name)
31{
32 struct file *file;
33 FILE *out;
34
35 if (!name)
36 name = ".kconfig.d";
37 out = fopen("..config.tmp", "w");
38 if (!out)
39 return 1;
40 fprintf(out, "deps_config := \\\n");
41 for (file = file_list; file; file = file->next) {
42 if (file->next)
43 fprintf(out, "\t%s \\\n", file->name);
44 else
45 fprintf(out, "\t%s\n", file->name);
46 }
47 fprintf(out, "\n.config include/autoconf.h: $(deps_config)\n\n$(deps_config):\n");
48 fclose(out);
49 rename("..config.tmp", name);
50 return 0;
51}
52
53
54/* Allocate initial growable sting */
55struct gstr str_new(void)
56{
57 struct gstr gs;
58 gs.s = malloc(sizeof(char) * 64);
59 gs.len = 16;
60 strcpy(gs.s, "\0");
61 return gs;
62}
63
64/* Allocate and assign growable string */
65struct gstr str_assign(const char *s)
66{
67 struct gstr gs;
68 gs.s = strdup(s);
69 gs.len = strlen(s) + 1;
70 return gs;
71}
72
73/* Free storage for growable string */
74void str_free(struct gstr *gs)
75{
76 if (gs->s)
77 free(gs->s);
78 gs->s = NULL;
79 gs->len = 0;
80}
81
82/* Append to growable string */
83void str_append(struct gstr *gs, const char *s)
84{
85 size_t l = strlen(gs->s) + strlen(s) + 1;
86 if (l > gs->len) {
87 gs->s = realloc(gs->s, l);
88 gs->len = l;
89 }
90 strcat(gs->s, s);
91}
92
93/* Append printf formatted string to growable string */
94void str_printf(struct gstr *gs, const char *fmt, ...)
95{
96 va_list ap;
97 char s[10000]; /* big enough... */
98 va_start(ap, fmt);
99 vsnprintf(s, sizeof(s), fmt, ap);
100 str_append(gs, s);
101 va_end(ap);
102}
103
104/* Retrieve value of growable string */
105const char *str_get(struct gstr *gs)
106{
107 return gs->s;
108}
109
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
new file mode 100644
index 000000000..b03220600
--- /dev/null
+++ b/scripts/kconfig/zconf.gperf
@@ -0,0 +1,43 @@
1%language=ANSI-C
2%define hash-function-name kconf_id_hash
3%define lookup-function-name kconf_id_lookup
4%define string-pool-name kconf_id_strings
5%compare-strncmp
6%enum
7%pic
8%struct-type
9
10struct kconf_id;
11
12%%
13mainmenu, T_MAINMENU, TF_COMMAND
14menu, T_MENU, TF_COMMAND
15endmenu, T_ENDMENU, TF_COMMAND
16source, T_SOURCE, TF_COMMAND
17choice, T_CHOICE, TF_COMMAND
18endchoice, T_ENDCHOICE, TF_COMMAND
19comment, T_COMMENT, TF_COMMAND
20config, T_CONFIG, TF_COMMAND
21menuconfig, T_MENUCONFIG, TF_COMMAND
22help, T_HELP, TF_COMMAND
23if, T_IF, TF_COMMAND|TF_PARAM
24endif, T_ENDIF, TF_COMMAND
25depends, T_DEPENDS, TF_COMMAND
26requires, T_REQUIRES, TF_COMMAND
27optional, T_OPTIONAL, TF_COMMAND
28default, T_DEFAULT, TF_COMMAND, S_UNKNOWN
29prompt, T_PROMPT, TF_COMMAND
30tristate, T_TYPE, TF_COMMAND, S_TRISTATE
31def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE
32bool, T_TYPE, TF_COMMAND, S_BOOLEAN
33boolean, T_TYPE, TF_COMMAND, S_BOOLEAN
34def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN
35def_boolean, T_DEFAULT, TF_COMMAND, S_BOOLEAN
36int, T_TYPE, TF_COMMAND, S_INT
37hex, T_TYPE, TF_COMMAND, S_HEX
38string, T_TYPE, TF_COMMAND, S_STRING
39select, T_SELECT, TF_COMMAND
40enable, T_SELECT, TF_COMMAND
41range, T_RANGE, TF_COMMAND
42on, T_ON, TF_PARAM
43%%
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
new file mode 100644
index 000000000..345f0fc07
--- /dev/null
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -0,0 +1,231 @@
1/* ANSI-C code produced by gperf version 3.0.1 */
2/* Command-line: gperf */
3/* Computed positions: -k'1,3' */
4
5#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
6 && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
7 && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
8 && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
9 && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
10 && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
11 && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
12 && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
13 && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
14 && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
15 && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
16 && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
17 && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
18 && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
19 && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
20 && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
21 && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
22 && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
23 && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
24 && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
25 && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
26 && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
27 && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
28/* The character set is not based on ISO-646. */
29#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
30#endif
31
32struct kconf_id;
33/* maximum key range = 45, duplicates = 0 */
34
35#ifdef __GNUC__
36__inline
37#else
38#ifdef __cplusplus
39inline
40#endif
41#endif
42static unsigned int
43kconf_id_hash (register const char *str, register unsigned int len)
44{
45 static unsigned char asso_values[] =
46 {
47 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
48 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
49 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
50 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
51 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
52 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
53 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
54 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
55 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
56 47, 47, 47, 47, 47, 47, 47, 25, 10, 15,
57 0, 0, 5, 47, 0, 0, 47, 47, 0, 10,
58 0, 20, 20, 20, 5, 0, 0, 20, 47, 47,
59 20, 47, 47, 47, 47, 47, 47, 47, 47, 47,
60 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
61 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
62 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
63 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
64 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
65 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
66 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
67 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
68 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
69 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
70 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
71 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
72 47, 47, 47, 47, 47, 47
73 };
74 register int hval = len;
75
76 switch (hval)
77 {
78 default:
79 hval += asso_values[(unsigned char)str[2]];
80 /*FALLTHROUGH*/
81 case 2:
82 case 1:
83 hval += asso_values[(unsigned char)str[0]];
84 break;
85 }
86 return hval;
87}
88
89struct kconf_id_strings_t
90 {
91 char kconf_id_strings_str2[sizeof("if")];
92 char kconf_id_strings_str3[sizeof("int")];
93 char kconf_id_strings_str4[sizeof("help")];
94 char kconf_id_strings_str5[sizeof("endif")];
95 char kconf_id_strings_str6[sizeof("select")];
96 char kconf_id_strings_str7[sizeof("endmenu")];
97 char kconf_id_strings_str8[sizeof("tristate")];
98 char kconf_id_strings_str9[sizeof("endchoice")];
99 char kconf_id_strings_str10[sizeof("range")];
100 char kconf_id_strings_str11[sizeof("string")];
101 char kconf_id_strings_str12[sizeof("default")];
102 char kconf_id_strings_str13[sizeof("def_bool")];
103 char kconf_id_strings_str14[sizeof("menu")];
104 char kconf_id_strings_str16[sizeof("def_boolean")];
105 char kconf_id_strings_str17[sizeof("def_tristate")];
106 char kconf_id_strings_str18[sizeof("mainmenu")];
107 char kconf_id_strings_str20[sizeof("menuconfig")];
108 char kconf_id_strings_str21[sizeof("config")];
109 char kconf_id_strings_str22[sizeof("on")];
110 char kconf_id_strings_str23[sizeof("hex")];
111 char kconf_id_strings_str26[sizeof("source")];
112 char kconf_id_strings_str27[sizeof("depends")];
113 char kconf_id_strings_str28[sizeof("optional")];
114 char kconf_id_strings_str31[sizeof("enable")];
115 char kconf_id_strings_str32[sizeof("comment")];
116 char kconf_id_strings_str33[sizeof("requires")];
117 char kconf_id_strings_str34[sizeof("bool")];
118 char kconf_id_strings_str37[sizeof("boolean")];
119 char kconf_id_strings_str41[sizeof("choice")];
120 char kconf_id_strings_str46[sizeof("prompt")];
121 };
122static struct kconf_id_strings_t kconf_id_strings_contents =
123 {
124 "if",
125 "int",
126 "help",
127 "endif",
128 "select",
129 "endmenu",
130 "tristate",
131 "endchoice",
132 "range",
133 "string",
134 "default",
135 "def_bool",
136 "menu",
137 "def_boolean",
138 "def_tristate",
139 "mainmenu",
140 "menuconfig",
141 "config",
142 "on",
143 "hex",
144 "source",
145 "depends",
146 "optional",
147 "enable",
148 "comment",
149 "requires",
150 "bool",
151 "boolean",
152 "choice",
153 "prompt"
154 };
155#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
156#ifdef __GNUC__
157__inline
158#endif
159struct kconf_id *
160kconf_id_lookup (register const char *str, register unsigned int len)
161{
162 enum
163 {
164 TOTAL_KEYWORDS = 30,
165 MIN_WORD_LENGTH = 2,
166 MAX_WORD_LENGTH = 12,
167 MIN_HASH_VALUE = 2,
168 MAX_HASH_VALUE = 46
169 };
170
171 static struct kconf_id wordlist[] =
172 {
173 {-1}, {-1},
174 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM},
175 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT},
176 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str4, T_HELP, TF_COMMAND},
177 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND},
178 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_SELECT, TF_COMMAND},
179 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND},
180 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE},
181 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND},
182 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND},
183 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_TYPE, TF_COMMAND, S_STRING},
184 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
185 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
186 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_MENU, TF_COMMAND},
187 {-1},
188 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
189 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE},
190 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_MAINMENU, TF_COMMAND},
191 {-1},
192 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20, T_MENUCONFIG, TF_COMMAND},
193 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_CONFIG, TF_COMMAND},
194 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ON, TF_PARAM},
195 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_HEX},
196 {-1}, {-1},
197 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SOURCE, TF_COMMAND},
198 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_DEPENDS, TF_COMMAND},
199 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_OPTIONAL, TF_COMMAND},
200 {-1}, {-1},
201 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND},
202 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND},
203 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_REQUIRES, TF_COMMAND},
204 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34, T_TYPE, TF_COMMAND, S_BOOLEAN},
205 {-1}, {-1},
206 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_TYPE, TF_COMMAND, S_BOOLEAN},
207 {-1}, {-1}, {-1},
208 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_CHOICE, TF_COMMAND},
209 {-1}, {-1}, {-1}, {-1},
210 {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_PROMPT, TF_COMMAND}
211 };
212
213 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
214 {
215 register int key = kconf_id_hash (str, len);
216
217 if (key <= MAX_HASH_VALUE && key >= 0)
218 {
219 register int o = wordlist[key].name;
220 if (o >= 0)
221 {
222 register const char *s = o + kconf_id_strings;
223
224 if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
225 return &wordlist[key];
226 }
227 }
228 }
229 return 0;
230}
231
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
new file mode 100644
index 000000000..cfa46077c
--- /dev/null
+++ b/scripts/kconfig/zconf.l
@@ -0,0 +1,350 @@
1%option backup nostdinit noyywrap never-interactive full ecs
2%option 8bit backup nodefault perf-report perf-report
3%x COMMAND HELP STRING PARAM
4%{
5/*
6 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
7 * Released under the terms of the GNU GPL v2.0.
8 */
9
10#include <limits.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <unistd.h>
15
16#define LKC_DIRECT_LINK
17#include "lkc.h"
18
19#define START_STRSIZE 16
20
21static struct {
22 struct file *file;
23 int lineno;
24} current_pos;
25
26static char *text;
27static int text_size, text_asize;
28
29struct buffer {
30 struct buffer *parent;
31 YY_BUFFER_STATE state;
32};
33
34struct buffer *current_buf;
35
36static int last_ts, first_ts;
37
38static void zconf_endhelp(void);
39static void zconf_endfile(void);
40
41void new_string(void)
42{
43 text = malloc(START_STRSIZE);
44 text_asize = START_STRSIZE;
45 text_size = 0;
46 *text = 0;
47}
48
49void append_string(const char *str, int size)
50{
51 int new_size = text_size + size + 1;
52 if (new_size > text_asize) {
53 new_size += START_STRSIZE - 1;
54 new_size &= -START_STRSIZE;
55 text = realloc(text, new_size);
56 text_asize = new_size;
57 }
58 memcpy(text + text_size, str, size);
59 text_size += size;
60 text[text_size] = 0;
61}
62
63void alloc_string(const char *str, int size)
64{
65 text = malloc(size + 1);
66 memcpy(text, str, size);
67 text[size] = 0;
68}
69%}
70
71ws [ \n\t]
72n [A-Za-z0-9_]
73
74%%
75 int str = 0;
76 int ts, i;
77
78[ \t]*#.*\n |
79[ \t]*\n {
80 current_file->lineno++;
81 return T_EOL;
82}
83[ \t]*#.*
84
85
86[ \t]+ {
87 BEGIN(COMMAND);
88}
89
90. {
91 unput(yytext[0]);
92 BEGIN(COMMAND);
93}
94
95
96<COMMAND>{
97 {n}+ {
98 struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
99 BEGIN(PARAM);
100 current_pos.file = current_file;
101 current_pos.lineno = current_file->lineno;
102 if (id && id->flags & TF_COMMAND) {
103 zconflval.id = id;
104 return id->token;
105 }
106 alloc_string(yytext, yyleng);
107 zconflval.string = text;
108 return T_WORD;
109 }
110 .
111 \n {
112 BEGIN(INITIAL);
113 current_file->lineno++;
114 return T_EOL;
115 }
116}
117
118<PARAM>{
119 "&&" return T_AND;
120 "||" return T_OR;
121 "(" return T_OPEN_PAREN;
122 ")" return T_CLOSE_PAREN;
123 "!" return T_NOT;
124 "=" return T_EQUAL;
125 "!=" return T_UNEQUAL;
126 \"|\' {
127 str = yytext[0];
128 new_string();
129 BEGIN(STRING);
130 }
131 \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
132 --- /* ignore */
133 ({n}|[-/.])+ {
134 struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
135 if (id && id->flags & TF_PARAM) {
136 zconflval.id = id;
137 return id->token;
138 }
139 alloc_string(yytext, yyleng);
140 zconflval.string = text;
141 return T_WORD;
142 }
143 #.* /* comment */
144 \\\n current_file->lineno++;
145 .
146 <<EOF>> {
147 BEGIN(INITIAL);
148 }
149}
150
151<STRING>{
152 [^'"\\\n]+/\n {
153 append_string(yytext, yyleng);
154 zconflval.string = text;
155 return T_WORD_QUOTE;
156 }
157 [^'"\\\n]+ {
158 append_string(yytext, yyleng);
159 }
160 \\.?/\n {
161 append_string(yytext + 1, yyleng - 1);
162 zconflval.string = text;
163 return T_WORD_QUOTE;
164 }
165 \\.? {
166 append_string(yytext + 1, yyleng - 1);
167 }
168 \'|\" {
169 if (str == yytext[0]) {
170 BEGIN(PARAM);
171 zconflval.string = text;
172 return T_WORD_QUOTE;
173 } else
174 append_string(yytext, 1);
175 }
176 \n {
177 printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
178 current_file->lineno++;
179 BEGIN(INITIAL);
180 return T_EOL;
181 }
182 <<EOF>> {
183 BEGIN(INITIAL);
184 }
185}
186
187<HELP>{
188 [ \t]+ {
189 ts = 0;
190 for (i = 0; i < yyleng; i++) {
191 if (yytext[i] == '\t')
192 ts = (ts & ~7) + 8;
193 else
194 ts++;
195 }
196 last_ts = ts;
197 if (first_ts) {
198 if (ts < first_ts) {
199 zconf_endhelp();
200 return T_HELPTEXT;
201 }
202 ts -= first_ts;
203 while (ts > 8) {
204 append_string(" ", 8);
205 ts -= 8;
206 }
207 append_string(" ", ts);
208 }
209 }
210 [ \t]*\n/[^ \t\n] {
211 current_file->lineno++;
212 zconf_endhelp();
213 return T_HELPTEXT;
214 }
215 [ \t]*\n {
216 current_file->lineno++;
217 append_string("\n", 1);
218 }
219 [^ \t\n].* {
220 append_string(yytext, yyleng);
221 if (!first_ts)
222 first_ts = last_ts;
223 }
224 <<EOF>> {
225 zconf_endhelp();
226 return T_HELPTEXT;
227 }
228}
229
230<<EOF>> {
231 if (current_file) {
232 zconf_endfile();
233 return T_EOL;
234 }
235 fclose(yyin);
236 yyterminate();
237}
238
239%%
240void zconf_starthelp(void)
241{
242 new_string();
243 last_ts = first_ts = 0;
244 BEGIN(HELP);
245}
246
247static void zconf_endhelp(void)
248{
249 zconflval.string = text;
250 BEGIN(INITIAL);
251}
252
253
254/*
255 * Try to open specified file with following names:
256 * ./name
257 * $(srctree)/name
258 * The latter is used when srctree is separate from objtree
259 * when compiling the kernel.
260 * Return NULL if file is not found.
261 */
262FILE *zconf_fopen(const char *name)
263{
264 char *env, fullname[PATH_MAX+1];
265 FILE *f;
266
267 f = fopen(name, "r");
268 if (!f && name[0] != '/') {
269 env = getenv(SRCTREE);
270 if (env) {
271 sprintf(fullname, "%s/%s", env, name);
272 f = fopen(fullname, "r");
273 }
274 }
275 return f;
276}
277
278void zconf_initscan(const char *name)
279{
280 yyin = zconf_fopen(name);
281 if (!yyin) {
282 printf("can't find file %s\n", name);
283 exit(1);
284 }
285
286 current_buf = malloc(sizeof(*current_buf));
287 memset(current_buf, 0, sizeof(*current_buf));
288
289 current_file = file_lookup(name);
290 current_file->lineno = 1;
291 current_file->flags = FILE_BUSY;
292}
293
294void zconf_nextfile(const char *name)
295{
296 struct file *file = file_lookup(name);
297 struct buffer *buf = malloc(sizeof(*buf));
298 memset(buf, 0, sizeof(*buf));
299
300 current_buf->state = YY_CURRENT_BUFFER;
301 yyin = zconf_fopen(name);
302 if (!yyin) {
303 printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
304 exit(1);
305 }
306 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
307 buf->parent = current_buf;
308 current_buf = buf;
309
310 if (file->flags & FILE_BUSY) {
311 printf("recursive scan (%s)?\n", name);
312 exit(1);
313 }
314 if (file->flags & FILE_SCANNED) {
315 printf("file %s already scanned?\n", name);
316 exit(1);
317 }
318 file->flags |= FILE_BUSY;
319 file->lineno = 1;
320 file->parent = current_file;
321 current_file = file;
322}
323
324static void zconf_endfile(void)
325{
326 struct buffer *parent;
327
328 current_file->flags |= FILE_SCANNED;
329 current_file->flags &= ~FILE_BUSY;
330 current_file = current_file->parent;
331
332 parent = current_buf->parent;
333 if (parent) {
334 fclose(yyin);
335 yy_delete_buffer(YY_CURRENT_BUFFER);
336 yy_switch_to_buffer(parent->state);
337 }
338 free(current_buf);
339 current_buf = parent;
340}
341
342int zconf_lineno(void)
343{
344 return current_pos.lineno;
345}
346
347char *zconf_curname(void)
348{
349 return current_pos.file ? current_pos.file->name : "<none>";
350}
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
new file mode 100644
index 000000000..ea7755da8
--- /dev/null
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -0,0 +1,2173 @@
1/* A Bison parser, made by GNU Bison 2.0. */
2
3/* Skeleton parser for Yacc-like parsing with Bison,
4 Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21/* As a special exception, when this file is copied by Bison into a
22 Bison output file, you may use that output file without restriction.
23 This special exception was added by the Free Software Foundation
24 in version 1.24 of Bison. */
25
26/* Written by Richard Stallman by simplifying the original so called
27 ``semantic'' parser. */
28
29/* All symbols defined below should begin with yy or YY, to avoid
30 infringing on user name space. This should be done even for local
31 variables, as they might otherwise be expanded by user macros.
32 There are some unavoidable exceptions within include files to
33 define necessary library symbols; they are noted "INFRINGES ON
34 USER NAME SPACE" below. */
35
36/* Identify Bison output. */
37#define YYBISON 1
38
39/* Skeleton name. */
40#define YYSKELETON_NAME "yacc.c"
41
42/* Pure parsers. */
43#define YYPURE 0
44
45/* Using locations. */
46#define YYLSP_NEEDED 0
47
48/* Substitute the variable and function names. */
49#define yyparse zconfparse
50#define yylex zconflex
51#define yyerror zconferror
52#define yylval zconflval
53#define yychar zconfchar
54#define yydebug zconfdebug
55#define yynerrs zconfnerrs
56
57
58/* Tokens. */
59#ifndef YYTOKENTYPE
60# define YYTOKENTYPE
61 /* Put the tokens into the symbol table, so that GDB and other debuggers
62 know about them. */
63 enum yytokentype {
64 T_MAINMENU = 258,
65 T_MENU = 259,
66 T_ENDMENU = 260,
67 T_SOURCE = 261,
68 T_CHOICE = 262,
69 T_ENDCHOICE = 263,
70 T_COMMENT = 264,
71 T_CONFIG = 265,
72 T_MENUCONFIG = 266,
73 T_HELP = 267,
74 T_HELPTEXT = 268,
75 T_IF = 269,
76 T_ENDIF = 270,
77 T_DEPENDS = 271,
78 T_REQUIRES = 272,
79 T_OPTIONAL = 273,
80 T_PROMPT = 274,
81 T_TYPE = 275,
82 T_DEFAULT = 276,
83 T_SELECT = 277,
84 T_RANGE = 278,
85 T_ON = 279,
86 T_WORD = 280,
87 T_WORD_QUOTE = 281,
88 T_UNEQUAL = 282,
89 T_CLOSE_PAREN = 283,
90 T_OPEN_PAREN = 284,
91 T_EOL = 285,
92 T_OR = 286,
93 T_AND = 287,
94 T_EQUAL = 288,
95 T_NOT = 289
96 };
97#endif
98#define T_MAINMENU 258
99#define T_MENU 259
100#define T_ENDMENU 260
101#define T_SOURCE 261
102#define T_CHOICE 262
103#define T_ENDCHOICE 263
104#define T_COMMENT 264
105#define T_CONFIG 265
106#define T_MENUCONFIG 266
107#define T_HELP 267
108#define T_HELPTEXT 268
109#define T_IF 269
110#define T_ENDIF 270
111#define T_DEPENDS 271
112#define T_REQUIRES 272
113#define T_OPTIONAL 273
114#define T_PROMPT 274
115#define T_TYPE 275
116#define T_DEFAULT 276
117#define T_SELECT 277
118#define T_RANGE 278
119#define T_ON 279
120#define T_WORD 280
121#define T_WORD_QUOTE 281
122#define T_UNEQUAL 282
123#define T_CLOSE_PAREN 283
124#define T_OPEN_PAREN 284
125#define T_EOL 285
126#define T_OR 286
127#define T_AND 287
128#define T_EQUAL 288
129#define T_NOT 289
130
131
132
133
134/* Copy the first part of user declarations. */
135
136
137/*
138 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
139 * Released under the terms of the GNU GPL v2.0.
140 */
141
142#include <ctype.h>
143#include <stdarg.h>
144#include <stdio.h>
145#include <stdlib.h>
146#include <string.h>
147#include <stdbool.h>
148
149#define LKC_DIRECT_LINK
150#include "lkc.h"
151
152#include "zconf.hash.c"
153
154#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
155
156#define PRINTD 0x0001
157#define DEBUG_PARSE 0x0002
158
159int cdebug = PRINTD;
160
161extern int zconflex(void);
162static void zconfprint(const char *err, ...);
163static void zconf_error(const char *err, ...);
164static void zconferror(const char *err);
165static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
166
167struct symbol *symbol_hash[257];
168
169static struct menu *current_menu, *current_entry;
170
171#define YYDEBUG 0
172#if YYDEBUG
173#define YYERROR_VERBOSE
174#endif
175
176
177/* Enabling traces. */
178#ifndef YYDEBUG
179# define YYDEBUG 0
180#endif
181
182/* Enabling verbose error messages. */
183#ifdef YYERROR_VERBOSE
184# undef YYERROR_VERBOSE
185# define YYERROR_VERBOSE 1
186#else
187# define YYERROR_VERBOSE 0
188#endif
189
190#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
191
192typedef union YYSTYPE {
193 char *string;
194 struct file *file;
195 struct symbol *symbol;
196 struct expr *expr;
197 struct menu *menu;
198 struct kconf_id *id;
199} YYSTYPE;
200/* Line 190 of yacc.c. */
201
202# define yystype YYSTYPE /* obsolescent; will be withdrawn */
203# define YYSTYPE_IS_DECLARED 1
204# define YYSTYPE_IS_TRIVIAL 1
205#endif
206
207
208
209/* Copy the second part of user declarations. */
210
211
212/* Line 213 of yacc.c. */
213
214
215#if ! defined (yyoverflow) || YYERROR_VERBOSE
216
217# ifndef YYFREE
218# define YYFREE free
219# endif
220# ifndef YYMALLOC
221# define YYMALLOC malloc
222# endif
223
224/* The parser invokes alloca or malloc; define the necessary symbols. */
225
226# ifdef YYSTACK_USE_ALLOCA
227# if YYSTACK_USE_ALLOCA
228# ifdef __GNUC__
229# define YYSTACK_ALLOC __builtin_alloca
230# else
231# define YYSTACK_ALLOC alloca
232# endif
233# endif
234# endif
235
236# ifdef YYSTACK_ALLOC
237 /* Pacify GCC's `empty if-body' warning. */
238# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
239# else
240# if defined (__STDC__) || defined (__cplusplus)
241# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
242# define YYSIZE_T size_t
243# endif
244# define YYSTACK_ALLOC YYMALLOC
245# define YYSTACK_FREE YYFREE
246# endif
247#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
248
249
250#if (! defined (yyoverflow) \
251 && (! defined (__cplusplus) \
252 || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
253
254/* A type that is properly aligned for any stack member. */
255union yyalloc
256{
257 short int yyss;
258 YYSTYPE yyvs;
259 };
260
261/* The size of the maximum gap between one aligned stack and the next. */
262# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
263
264/* The size of an array large to enough to hold all stacks, each with
265 N elements. */
266# define YYSTACK_BYTES(N) \
267 ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
268 + YYSTACK_GAP_MAXIMUM)
269
270/* Copy COUNT objects from FROM to TO. The source and destination do
271 not overlap. */
272# ifndef YYCOPY
273# if defined (__GNUC__) && 1 < __GNUC__
274# define YYCOPY(To, From, Count) \
275 __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
276# else
277# define YYCOPY(To, From, Count) \
278 do \
279 { \
280 register YYSIZE_T yyi; \
281 for (yyi = 0; yyi < (Count); yyi++) \
282 (To)[yyi] = (From)[yyi]; \
283 } \
284 while (0)
285# endif
286# endif
287
288/* Relocate STACK from its old location to the new one. The
289 local variables YYSIZE and YYSTACKSIZE give the old and new number of
290 elements in the stack, and YYPTR gives the new location of the
291 stack. Advance YYPTR to a properly aligned location for the next
292 stack. */
293# define YYSTACK_RELOCATE(Stack) \
294 do \
295 { \
296 YYSIZE_T yynewbytes; \
297 YYCOPY (&yyptr->Stack, Stack, yysize); \
298 Stack = &yyptr->Stack; \
299 yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
300 yyptr += yynewbytes / sizeof (*yyptr); \
301 } \
302 while (0)
303
304#endif
305
306#if defined (__STDC__) || defined (__cplusplus)
307 typedef signed char yysigned_char;
308#else
309 typedef short int yysigned_char;
310#endif
311
312/* YYFINAL -- State number of the termination state. */
313#define YYFINAL 3
314/* YYLAST -- Last index in YYTABLE. */
315#define YYLAST 264
316
317/* YYNTOKENS -- Number of terminals. */
318#define YYNTOKENS 35
319/* YYNNTS -- Number of nonterminals. */
320#define YYNNTS 42
321/* YYNRULES -- Number of rules. */
322#define YYNRULES 104
323/* YYNRULES -- Number of states. */
324#define YYNSTATES 175
325
326/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
327#define YYUNDEFTOK 2
328#define YYMAXUTOK 289
329
330#define YYTRANSLATE(YYX) \
331 ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
332
333/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
334static const unsigned char yytranslate[] =
335{
336 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
337 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
338 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
339 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
340 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
341 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
342 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
343 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
344 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
345 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
346 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
347 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
348 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
349 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
350 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
351 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
352 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
353 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
354 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
355 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
356 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
357 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
358 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
359 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
360 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
361 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
362 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
363 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
364 25, 26, 27, 28, 29, 30, 31, 32, 33, 34
365};
366
367#if YYDEBUG
368/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
369 YYRHS. */
370static const unsigned short int yyprhs[] =
371{
372 0, 0, 3, 5, 6, 9, 12, 15, 20, 23,
373 28, 33, 37, 39, 41, 43, 45, 47, 49, 51,
374 53, 55, 57, 59, 61, 63, 67, 70, 74, 77,
375 81, 84, 85, 88, 91, 94, 97, 100, 104, 109,
376 114, 119, 125, 128, 131, 133, 137, 138, 141, 144,
377 147, 150, 153, 158, 162, 165, 170, 171, 174, 178,
378 180, 184, 185, 188, 191, 194, 198, 201, 203, 207,
379 208, 211, 214, 217, 221, 225, 228, 231, 234, 235,
380 238, 241, 244, 249, 253, 257, 258, 261, 263, 265,
381 268, 271, 274, 276, 279, 280, 283, 285, 289, 293,
382 297, 300, 304, 308, 310
383};
384
385/* YYRHS -- A `-1'-separated list of the rules' RHS. */
386static const yysigned_char yyrhs[] =
387{
388 36, 0, -1, 37, -1, -1, 37, 39, -1, 37,
389 50, -1, 37, 61, -1, 37, 3, 71, 73, -1,
390 37, 72, -1, 37, 25, 1, 30, -1, 37, 38,
391 1, 30, -1, 37, 1, 30, -1, 16, -1, 19,
392 -1, 20, -1, 22, -1, 18, -1, 23, -1, 21,
393 -1, 30, -1, 56, -1, 65, -1, 42, -1, 44,
394 -1, 63, -1, 25, 1, 30, -1, 1, 30, -1,
395 10, 25, 30, -1, 41, 45, -1, 11, 25, 30,
396 -1, 43, 45, -1, -1, 45, 46, -1, 45, 69,
397 -1, 45, 67, -1, 45, 40, -1, 45, 30, -1,
398 20, 70, 30, -1, 19, 71, 74, 30, -1, 21,
399 75, 74, 30, -1, 22, 25, 74, 30, -1, 23,
400 76, 76, 74, 30, -1, 7, 30, -1, 47, 51,
401 -1, 72, -1, 48, 53, 49, -1, -1, 51, 52,
402 -1, 51, 69, -1, 51, 67, -1, 51, 30, -1,
403 51, 40, -1, 19, 71, 74, 30, -1, 20, 70,
404 30, -1, 18, 30, -1, 21, 25, 74, 30, -1,
405 -1, 53, 39, -1, 14, 75, 73, -1, 72, -1,
406 54, 57, 55, -1, -1, 57, 39, -1, 57, 61,
407 -1, 57, 50, -1, 4, 71, 30, -1, 58, 68,
408 -1, 72, -1, 59, 62, 60, -1, -1, 62, 39,
409 -1, 62, 61, -1, 62, 50, -1, 6, 71, 30,
410 -1, 9, 71, 30, -1, 64, 68, -1, 12, 30,
411 -1, 66, 13, -1, -1, 68, 69, -1, 68, 30,
412 -1, 68, 40, -1, 16, 24, 75, 30, -1, 16,
413 75, 30, -1, 17, 75, 30, -1, -1, 71, 74,
414 -1, 25, -1, 26, -1, 5, 30, -1, 8, 30,
415 -1, 15, 30, -1, 30, -1, 73, 30, -1, -1,
416 14, 75, -1, 76, -1, 76, 33, 76, -1, 76,
417 27, 76, -1, 29, 75, 28, -1, 34, 75, -1,
418 75, 31, 75, -1, 75, 32, 75, -1, 25, -1,
419 26, -1
420};
421
422/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
423static const unsigned short int yyrline[] =
424{
425 0, 103, 103, 105, 107, 108, 109, 110, 111, 112,
426 113, 117, 121, 121, 121, 121, 121, 121, 121, 125,
427 126, 127, 128, 129, 130, 134, 135, 141, 149, 155,
428 163, 173, 175, 176, 177, 178, 179, 182, 190, 196,
429 206, 212, 220, 229, 234, 242, 245, 247, 248, 249,
430 250, 251, 254, 260, 271, 277, 287, 289, 294, 302,
431 310, 313, 315, 316, 317, 322, 329, 334, 342, 345,
432 347, 348, 349, 352, 360, 367, 374, 380, 387, 389,
433 390, 391, 394, 399, 404, 412, 414, 419, 420, 423,
434 424, 425, 429, 430, 433, 434, 437, 438, 439, 440,
435 441, 442, 443, 446, 447
436};
437#endif
438
439#if YYDEBUG || YYERROR_VERBOSE
440/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
441 First, the terminals, then, starting at YYNTOKENS, nonterminals. */
442static const char *const yytname[] =
443{
444 "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU",
445 "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
446 "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
447 "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT",
448 "T_SELECT", "T_RANGE", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
449 "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
450 "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt",
451 "option_error", "config_entry_start", "config_stmt",
452 "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
453 "config_option", "choice", "choice_entry", "choice_end", "choice_stmt",
454 "choice_option_list", "choice_option", "choice_block", "if_entry",
455 "if_end", "if_stmt", "if_block", "menu", "menu_entry", "menu_end",
456 "menu_stmt", "menu_block", "source_stmt", "comment", "comment_stmt",
457 "help_start", "help", "depends_list", "depends", "prompt_stmt_opt",
458 "prompt", "end", "nl", "if_expr", "expr", "symbol", 0
459};
460#endif
461
462# ifdef YYPRINT
463/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
464 token YYLEX-NUM. */
465static const unsigned short int yytoknum[] =
466{
467 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
468 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
469 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
470 285, 286, 287, 288, 289
471};
472# endif
473
474/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
475static const unsigned char yyr1[] =
476{
477 0, 35, 36, 37, 37, 37, 37, 37, 37, 37,
478 37, 37, 38, 38, 38, 38, 38, 38, 38, 39,
479 39, 39, 39, 39, 39, 40, 40, 41, 42, 43,
480 44, 45, 45, 45, 45, 45, 45, 46, 46, 46,
481 46, 46, 47, 48, 49, 50, 51, 51, 51, 51,
482 51, 51, 52, 52, 52, 52, 53, 53, 54, 55,
483 56, 57, 57, 57, 57, 58, 59, 60, 61, 62,
484 62, 62, 62, 63, 64, 65, 66, 67, 68, 68,
485 68, 68, 69, 69, 69, 70, 70, 71, 71, 72,
486 72, 72, 73, 73, 74, 74, 75, 75, 75, 75,
487 75, 75, 75, 76, 76
488};
489
490/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
491static const unsigned char yyr2[] =
492{
493 0, 2, 1, 0, 2, 2, 2, 4, 2, 4,
494 4, 3, 1, 1, 1, 1, 1, 1, 1, 1,
495 1, 1, 1, 1, 1, 3, 2, 3, 2, 3,
496 2, 0, 2, 2, 2, 2, 2, 3, 4, 4,
497 4, 5, 2, 2, 1, 3, 0, 2, 2, 2,
498 2, 2, 4, 3, 2, 4, 0, 2, 3, 1,
499 3, 0, 2, 2, 2, 3, 2, 1, 3, 0,
500 2, 2, 2, 3, 3, 2, 2, 2, 0, 2,
501 2, 2, 4, 3, 3, 0, 2, 1, 1, 2,
502 2, 2, 1, 2, 0, 2, 1, 3, 3, 3,
503 2, 3, 3, 1, 1
504};
505
506/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
507 STATE-NUM when YYTABLE doesn't specify something else to do. Zero
508 means the default is an error. */
509static const unsigned char yydefact[] =
510{
511 3, 0, 0, 1, 0, 0, 0, 0, 0, 0,
512 0, 0, 0, 0, 0, 0, 12, 16, 13, 14,
513 18, 15, 17, 0, 19, 0, 4, 31, 22, 31,
514 23, 46, 56, 5, 61, 20, 78, 69, 6, 24,
515 78, 21, 8, 11, 87, 88, 0, 0, 89, 0,
516 42, 90, 0, 0, 0, 103, 104, 0, 0, 0,
517 96, 91, 0, 0, 0, 0, 0, 0, 0, 0,
518 0, 0, 92, 7, 65, 73, 74, 27, 29, 0,
519 100, 0, 0, 58, 0, 0, 9, 10, 0, 0,
520 0, 0, 0, 85, 0, 0, 0, 0, 36, 35,
521 32, 0, 34, 33, 0, 0, 85, 0, 50, 51,
522 47, 49, 48, 57, 45, 44, 62, 64, 60, 63,
523 59, 80, 81, 79, 70, 72, 68, 71, 67, 93,
524 99, 101, 102, 98, 97, 26, 76, 0, 0, 0,
525 94, 0, 94, 94, 94, 0, 0, 77, 54, 94,
526 0, 94, 0, 83, 84, 0, 0, 37, 86, 0,
527 0, 94, 25, 0, 53, 0, 82, 95, 38, 39,
528 40, 0, 52, 55, 41
529};
530
531/* YYDEFGOTO[NTERM-NUM]. */
532static const short int yydefgoto[] =
533{
534 -1, 1, 2, 25, 26, 99, 27, 28, 29, 30,
535 64, 100, 31, 32, 114, 33, 66, 110, 67, 34,
536 118, 35, 68, 36, 37, 126, 38, 70, 39, 40,
537 41, 101, 102, 69, 103, 141, 142, 42, 73, 156,
538 59, 60
539};
540
541/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
542 STATE-NUM. */
543#define YYPACT_NINF -78
544static const short int yypact[] =
545{
546 -78, 2, 159, -78, -21, 0, 0, -12, 0, 1,
547 4, 0, 27, 38, 60, 58, -78, -78, -78, -78,
548 -78, -78, -78, 100, -78, 104, -78, -78, -78, -78,
549 -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
550 -78, -78, -78, -78, -78, -78, 86, 113, -78, 114,
551 -78, -78, 125, 127, 128, -78, -78, 60, 60, 210,
552 65, -78, 141, 142, 39, 103, 182, 200, 6, 66,
553 6, 131, -78, 146, -78, -78, -78, -78, -78, 196,
554 -78, 60, 60, 146, 40, 40, -78, -78, 155, 156,
555 -2, 60, 0, 0, 60, 105, 40, 194, -78, -78,
556 -78, 206, -78, -78, 183, 0, 0, 195, -78, -78,
557 -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
558 -78, -78, -78, -78, -78, -78, -78, -78, -78, -78,
559 -78, 197, -78, -78, -78, -78, -78, 60, 213, 216,
560 212, 203, 212, 190, 212, 40, 208, -78, -78, 212,
561 222, 212, 219, -78, -78, 60, 223, -78, -78, 224,
562 225, 212, -78, 226, -78, 227, -78, 47, -78, -78,
563 -78, 228, -78, -78, -78
564};
565
566/* YYPGOTO[NTERM-NUM]. */
567static const short int yypgoto[] =
568{
569 -78, -78, -78, -78, 164, -36, -78, -78, -78, -78,
570 230, -78, -78, -78, -78, 29, -78, -78, -78, -78,
571 -78, -78, -78, -78, -78, -78, 59, -78, -78, -78,
572 -78, -78, 198, 220, 24, 157, -5, 169, 202, 74,
573 -53, -77
574};
575
576/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
577 positive, shift that token. If negative, reduce the rule which
578 number is the opposite. If zero, do what YYDEFACT says.
579 If YYTABLE_NINF, syntax error. */
580#define YYTABLE_NINF -76
581static const short int yytable[] =
582{
583 46, 47, 3, 49, 79, 80, 52, 133, 134, 43,
584 6, 7, 8, 9, 10, 11, 12, 13, 48, 145,
585 14, 15, 137, 55, 56, 44, 45, 57, 131, 132,
586 109, 50, 58, 122, 51, 122, 24, 138, 139, -28,
587 88, 143, -28, -28, -28, -28, -28, -28, -28, -28,
588 -28, 89, 53, -28, -28, 90, 91, -28, 92, 93,
589 94, 95, 96, 54, 97, 55, 56, 88, 161, 98,
590 -66, -66, -66, -66, -66, -66, -66, -66, 81, 82,
591 -66, -66, 90, 91, 152, 55, 56, 140, 61, 57,
592 112, 97, 84, 123, 58, 123, 121, 117, 85, 125,
593 149, 62, 167, -30, 88, 63, -30, -30, -30, -30,
594 -30, -30, -30, -30, -30, 89, 72, -30, -30, 90,
595 91, -30, 92, 93, 94, 95, 96, 119, 97, 127,
596 144, -75, 88, 98, -75, -75, -75, -75, -75, -75,
597 -75, -75, -75, 74, 75, -75, -75, 90, 91, -75,
598 -75, -75, -75, -75, -75, 76, 97, 77, 78, -2,
599 4, 121, 5, 6, 7, 8, 9, 10, 11, 12,
600 13, 86, 87, 14, 15, 16, 129, 17, 18, 19,
601 20, 21, 22, 88, 23, 135, 136, -43, -43, 24,
602 -43, -43, -43, -43, 89, 146, -43, -43, 90, 91,
603 104, 105, 106, 107, 155, 7, 8, 97, 10, 11,
604 12, 13, 108, 148, 14, 15, 158, 159, 160, 147,
605 151, 81, 82, 163, 130, 165, 155, 81, 82, 82,
606 24, 113, 116, 157, 124, 171, 115, 120, 162, 128,
607 72, 81, 82, 153, 81, 82, 154, 81, 82, 166,
608 81, 82, 164, 168, 169, 170, 172, 173, 174, 65,
609 71, 83, 0, 150, 111
610};
611
612static const short int yycheck[] =
613{
614 5, 6, 0, 8, 57, 58, 11, 84, 85, 30,
615 4, 5, 6, 7, 8, 9, 10, 11, 30, 96,
616 14, 15, 24, 25, 26, 25, 26, 29, 81, 82,
617 66, 30, 34, 69, 30, 71, 30, 90, 91, 0,
618 1, 94, 3, 4, 5, 6, 7, 8, 9, 10,
619 11, 12, 25, 14, 15, 16, 17, 18, 19, 20,
620 21, 22, 23, 25, 25, 25, 26, 1, 145, 30,
621 4, 5, 6, 7, 8, 9, 10, 11, 31, 32,
622 14, 15, 16, 17, 137, 25, 26, 92, 30, 29,
623 66, 25, 27, 69, 34, 71, 30, 68, 33, 70,
624 105, 1, 155, 0, 1, 1, 3, 4, 5, 6,
625 7, 8, 9, 10, 11, 12, 30, 14, 15, 16,
626 17, 18, 19, 20, 21, 22, 23, 68, 25, 70,
627 25, 0, 1, 30, 3, 4, 5, 6, 7, 8,
628 9, 10, 11, 30, 30, 14, 15, 16, 17, 18,
629 19, 20, 21, 22, 23, 30, 25, 30, 30, 0,
630 1, 30, 3, 4, 5, 6, 7, 8, 9, 10,
631 11, 30, 30, 14, 15, 16, 30, 18, 19, 20,
632 21, 22, 23, 1, 25, 30, 30, 5, 6, 30,
633 8, 9, 10, 11, 12, 1, 14, 15, 16, 17,
634 18, 19, 20, 21, 14, 5, 6, 25, 8, 9,
635 10, 11, 30, 30, 14, 15, 142, 143, 144, 13,
636 25, 31, 32, 149, 28, 151, 14, 31, 32, 32,
637 30, 67, 68, 30, 70, 161, 67, 68, 30, 70,
638 30, 31, 32, 30, 31, 32, 30, 31, 32, 30,
639 31, 32, 30, 30, 30, 30, 30, 30, 30, 29,
640 40, 59, -1, 106, 66
641};
642
643/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
644 symbol of state STATE-NUM. */
645static const unsigned char yystos[] =
646{
647 0, 36, 37, 0, 1, 3, 4, 5, 6, 7,
648 8, 9, 10, 11, 14, 15, 16, 18, 19, 20,
649 21, 22, 23, 25, 30, 38, 39, 41, 42, 43,
650 44, 47, 48, 50, 54, 56, 58, 59, 61, 63,
651 64, 65, 72, 30, 25, 26, 71, 71, 30, 71,
652 30, 30, 71, 25, 25, 25, 26, 29, 34, 75,
653 76, 30, 1, 1, 45, 45, 51, 53, 57, 68,
654 62, 68, 30, 73, 30, 30, 30, 30, 30, 75,
655 75, 31, 32, 73, 27, 33, 30, 30, 1, 12,
656 16, 17, 19, 20, 21, 22, 23, 25, 30, 40,
657 46, 66, 67, 69, 18, 19, 20, 21, 30, 40,
658 52, 67, 69, 39, 49, 72, 39, 50, 55, 61,
659 72, 30, 40, 69, 39, 50, 60, 61, 72, 30,
660 28, 75, 75, 76, 76, 30, 30, 24, 75, 75,
661 71, 70, 71, 75, 25, 76, 1, 13, 30, 71,
662 70, 25, 75, 30, 30, 14, 74, 30, 74, 74,
663 74, 76, 30, 74, 30, 74, 30, 75, 30, 30,
664 30, 74, 30, 30, 30
665};
666
667#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
668# define YYSIZE_T __SIZE_TYPE__
669#endif
670#if ! defined (YYSIZE_T) && defined (size_t)
671# define YYSIZE_T size_t
672#endif
673#if ! defined (YYSIZE_T)
674# if defined (__STDC__) || defined (__cplusplus)
675# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
676# define YYSIZE_T size_t
677# endif
678#endif
679#if ! defined (YYSIZE_T)
680# define YYSIZE_T unsigned int
681#endif
682
683#define yyerrok (yyerrstatus = 0)
684#define yyclearin (yychar = YYEMPTY)
685#define YYEMPTY (-2)
686#define YYEOF 0
687
688#define YYACCEPT goto yyacceptlab
689#define YYABORT goto yyabortlab
690#define YYERROR goto yyerrorlab
691
692
693/* Like YYERROR except do call yyerror. This remains here temporarily
694 to ease the transition to the new meaning of YYERROR, for GCC.
695 Once GCC version 2 has supplanted version 1, this can go. */
696
697#define YYFAIL goto yyerrlab
698
699#define YYRECOVERING() (!!yyerrstatus)
700
701#define YYBACKUP(Token, Value) \
702do \
703 if (yychar == YYEMPTY && yylen == 1) \
704 { \
705 yychar = (Token); \
706 yylval = (Value); \
707 yytoken = YYTRANSLATE (yychar); \
708 YYPOPSTACK; \
709 goto yybackup; \
710 } \
711 else \
712 { \
713 yyerror ("syntax error: cannot back up");\
714 YYERROR; \
715 } \
716while (0)
717
718
719#define YYTERROR 1
720#define YYERRCODE 256
721
722
723/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
724 If N is 0, then set CURRENT to the empty location which ends
725 the previous symbol: RHS[0] (always defined). */
726
727#define YYRHSLOC(Rhs, K) ((Rhs)[K])
728#ifndef YYLLOC_DEFAULT
729# define YYLLOC_DEFAULT(Current, Rhs, N) \
730 do \
731 if (N) \
732 { \
733 (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
734 (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
735 (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
736 (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
737 } \
738 else \
739 { \
740 (Current).first_line = (Current).last_line = \
741 YYRHSLOC (Rhs, 0).last_line; \
742 (Current).first_column = (Current).last_column = \
743 YYRHSLOC (Rhs, 0).last_column; \
744 } \
745 while (0)
746#endif
747
748
749/* YY_LOCATION_PRINT -- Print the location on the stream.
750 This macro was not mandated originally: define only if we know
751 we won't break user code: when these are the locations we know. */
752
753#ifndef YY_LOCATION_PRINT
754# if YYLTYPE_IS_TRIVIAL
755# define YY_LOCATION_PRINT(File, Loc) \
756 fprintf (File, "%d.%d-%d.%d", \
757 (Loc).first_line, (Loc).first_column, \
758 (Loc).last_line, (Loc).last_column)
759# else
760# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
761# endif
762#endif
763
764
765/* YYLEX -- calling `yylex' with the right arguments. */
766
767#ifdef YYLEX_PARAM
768# define YYLEX yylex (YYLEX_PARAM)
769#else
770# define YYLEX yylex ()
771#endif
772
773/* Enable debugging if requested. */
774#if YYDEBUG
775
776# ifndef YYFPRINTF
777# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
778# define YYFPRINTF fprintf
779# endif
780
781# define YYDPRINTF(Args) \
782do { \
783 if (yydebug) \
784 YYFPRINTF Args; \
785} while (0)
786
787# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
788do { \
789 if (yydebug) \
790 { \
791 YYFPRINTF (stderr, "%s ", Title); \
792 yysymprint (stderr, \
793 Type, Value); \
794 YYFPRINTF (stderr, "\n"); \
795 } \
796} while (0)
797
798/*------------------------------------------------------------------.
799| yy_stack_print -- Print the state stack from its BOTTOM up to its |
800| TOP (included). |
801`------------------------------------------------------------------*/
802
803#if defined (__STDC__) || defined (__cplusplus)
804static void
805yy_stack_print (short int *bottom, short int *top)
806#else
807static void
808yy_stack_print (bottom, top)
809 short int *bottom;
810 short int *top;
811#endif
812{
813 YYFPRINTF (stderr, "Stack now");
814 for (/* Nothing. */; bottom <= top; ++bottom)
815 YYFPRINTF (stderr, " %d", *bottom);
816 YYFPRINTF (stderr, "\n");
817}
818
819# define YY_STACK_PRINT(Bottom, Top) \
820do { \
821 if (yydebug) \
822 yy_stack_print ((Bottom), (Top)); \
823} while (0)
824
825
826/*------------------------------------------------.
827| Report that the YYRULE is going to be reduced. |
828`------------------------------------------------*/
829
830#if defined (__STDC__) || defined (__cplusplus)
831static void
832yy_reduce_print (int yyrule)
833#else
834static void
835yy_reduce_print (yyrule)
836 int yyrule;
837#endif
838{
839 int yyi;
840 unsigned int yylno = yyrline[yyrule];
841 YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
842 yyrule - 1, yylno);
843 /* Print the symbols being reduced, and their result. */
844 for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
845 YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
846 YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
847}
848
849# define YY_REDUCE_PRINT(Rule) \
850do { \
851 if (yydebug) \
852 yy_reduce_print (Rule); \
853} while (0)
854
855/* Nonzero means print parse trace. It is left uninitialized so that
856 multiple parsers can coexist. */
857int yydebug;
858#else /* !YYDEBUG */
859# define YYDPRINTF(Args)
860# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
861# define YY_STACK_PRINT(Bottom, Top)
862# define YY_REDUCE_PRINT(Rule)
863#endif /* !YYDEBUG */
864
865
866/* YYINITDEPTH -- initial size of the parser's stacks. */
867#ifndef YYINITDEPTH
868# define YYINITDEPTH 200
869#endif
870
871/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
872 if the built-in stack extension method is used).
873
874 Do not make this value too large; the results are undefined if
875 SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
876 evaluated with infinite-precision integer arithmetic. */
877
878#ifndef YYMAXDEPTH
879# define YYMAXDEPTH 10000
880#endif
881
882
883
884#if YYERROR_VERBOSE
885
886# ifndef yystrlen
887# if defined (__GLIBC__) && defined (_STRING_H)
888# define yystrlen strlen
889# else
890/* Return the length of YYSTR. */
891static YYSIZE_T
892# if defined (__STDC__) || defined (__cplusplus)
893yystrlen (const char *yystr)
894# else
895yystrlen (yystr)
896 const char *yystr;
897# endif
898{
899 register const char *yys = yystr;
900
901 while (*yys++ != '\0')
902 continue;
903
904 return yys - yystr - 1;
905}
906# endif
907# endif
908
909# ifndef yystpcpy
910# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
911# define yystpcpy stpcpy
912# else
913/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
914 YYDEST. */
915static char *
916# if defined (__STDC__) || defined (__cplusplus)
917yystpcpy (char *yydest, const char *yysrc)
918# else
919yystpcpy (yydest, yysrc)
920 char *yydest;
921 const char *yysrc;
922# endif
923{
924 register char *yyd = yydest;
925 register const char *yys = yysrc;
926
927 while ((*yyd++ = *yys++) != '\0')
928 continue;
929
930 return yyd - 1;
931}
932# endif
933# endif
934
935#endif /* !YYERROR_VERBOSE */
936
937
938
939#if YYDEBUG
940/*--------------------------------.
941| Print this symbol on YYOUTPUT. |
942`--------------------------------*/
943
944#if defined (__STDC__) || defined (__cplusplus)
945static void
946yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
947#else
948static void
949yysymprint (yyoutput, yytype, yyvaluep)
950 FILE *yyoutput;
951 int yytype;
952 YYSTYPE *yyvaluep;
953#endif
954{
955 /* Pacify ``unused variable'' warnings. */
956 (void) yyvaluep;
957
958 if (yytype < YYNTOKENS)
959 YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
960 else
961 YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
962
963
964# ifdef YYPRINT
965 if (yytype < YYNTOKENS)
966 YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
967# endif
968 switch (yytype)
969 {
970 default:
971 break;
972 }
973 YYFPRINTF (yyoutput, ")");
974}
975
976#endif /* ! YYDEBUG */
977/*-----------------------------------------------.
978| Release the memory associated to this symbol. |
979`-----------------------------------------------*/
980
981#if defined (__STDC__) || defined (__cplusplus)
982static void
983yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
984#else
985static void
986yydestruct (yymsg, yytype, yyvaluep)
987 const char *yymsg;
988 int yytype;
989 YYSTYPE *yyvaluep;
990#endif
991{
992 /* Pacify ``unused variable'' warnings. */
993 (void) yyvaluep;
994
995 if (!yymsg)
996 yymsg = "Deleting";
997 YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
998
999 switch (yytype)
1000 {
1001 case 48: /* choice_entry */
1002
1003 {
1004 fprintf(stderr, "%s:%d: missing end statement for this entry\n",
1005 (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
1006 if (current_menu == (yyvaluep->menu))
1007 menu_end_menu();
1008};
1009
1010 break;
1011 case 54: /* if_entry */
1012
1013 {
1014 fprintf(stderr, "%s:%d: missing end statement for this entry\n",
1015 (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
1016 if (current_menu == (yyvaluep->menu))
1017 menu_end_menu();
1018};
1019
1020 break;
1021 case 59: /* menu_entry */
1022
1023 {
1024 fprintf(stderr, "%s:%d: missing end statement for this entry\n",
1025 (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
1026 if (current_menu == (yyvaluep->menu))
1027 menu_end_menu();
1028};
1029
1030 break;
1031
1032 default:
1033 break;
1034 }
1035}
1036
1037
1038/* Prevent warnings from -Wmissing-prototypes. */
1039
1040#ifdef YYPARSE_PARAM
1041# if defined (__STDC__) || defined (__cplusplus)
1042int yyparse (void *YYPARSE_PARAM);
1043# else
1044int yyparse ();
1045# endif
1046#else /* ! YYPARSE_PARAM */
1047#if defined (__STDC__) || defined (__cplusplus)
1048int yyparse (void);
1049#else
1050int yyparse ();
1051#endif
1052#endif /* ! YYPARSE_PARAM */
1053
1054
1055
1056/* The look-ahead symbol. */
1057int yychar;
1058
1059/* The semantic value of the look-ahead symbol. */
1060YYSTYPE yylval;
1061
1062/* Number of syntax errors so far. */
1063int yynerrs;
1064
1065
1066
1067/*----------.
1068| yyparse. |
1069`----------*/
1070
1071#ifdef YYPARSE_PARAM
1072# if defined (__STDC__) || defined (__cplusplus)
1073int yyparse (void *YYPARSE_PARAM)
1074# else
1075int yyparse (YYPARSE_PARAM)
1076 void *YYPARSE_PARAM;
1077# endif
1078#else /* ! YYPARSE_PARAM */
1079#if defined (__STDC__) || defined (__cplusplus)
1080int
1081yyparse (void)
1082#else
1083int
1084yyparse ()
1085
1086#endif
1087#endif
1088{
1089
1090 register int yystate;
1091 register int yyn;
1092 int yyresult;
1093 /* Number of tokens to shift before error messages enabled. */
1094 int yyerrstatus;
1095 /* Look-ahead token as an internal (translated) token number. */
1096 int yytoken = 0;
1097
1098 /* Three stacks and their tools:
1099 `yyss': related to states,
1100 `yyvs': related to semantic values,
1101 `yyls': related to locations.
1102
1103 Refer to the stacks thru separate pointers, to allow yyoverflow
1104 to reallocate them elsewhere. */
1105
1106 /* The state stack. */
1107 short int yyssa[YYINITDEPTH];
1108 short int *yyss = yyssa;
1109 register short int *yyssp;
1110
1111 /* The semantic value stack. */
1112 YYSTYPE yyvsa[YYINITDEPTH];
1113 YYSTYPE *yyvs = yyvsa;
1114 register YYSTYPE *yyvsp;
1115
1116
1117
1118#define YYPOPSTACK (yyvsp--, yyssp--)
1119
1120 YYSIZE_T yystacksize = YYINITDEPTH;
1121
1122 /* The variables used to return semantic value and location from the
1123 action routines. */
1124 YYSTYPE yyval;
1125
1126
1127 /* When reducing, the number of symbols on the RHS of the reduced
1128 rule. */
1129 int yylen;
1130
1131 YYDPRINTF ((stderr, "Starting parse\n"));
1132
1133 yystate = 0;
1134 yyerrstatus = 0;
1135 yynerrs = 0;
1136 yychar = YYEMPTY; /* Cause a token to be read. */
1137
1138 /* Initialize stack pointers.
1139 Waste one element of value and location stack
1140 so that they stay on the same level as the state stack.
1141 The wasted elements are never initialized. */
1142
1143 yyssp = yyss;
1144 yyvsp = yyvs;
1145
1146
1147 yyvsp[0] = yylval;
1148
1149 goto yysetstate;
1150
1151/*------------------------------------------------------------.
1152| yynewstate -- Push a new state, which is found in yystate. |
1153`------------------------------------------------------------*/
1154 yynewstate:
1155 /* In all cases, when you get here, the value and location stacks
1156 have just been pushed. so pushing a state here evens the stacks.
1157 */
1158 yyssp++;
1159
1160 yysetstate:
1161 *yyssp = yystate;
1162
1163 if (yyss + yystacksize - 1 <= yyssp)
1164 {
1165 /* Get the current used size of the three stacks, in elements. */
1166 YYSIZE_T yysize = yyssp - yyss + 1;
1167
1168#ifdef yyoverflow
1169 {
1170 /* Give user a chance to reallocate the stack. Use copies of
1171 these so that the &'s don't force the real ones into
1172 memory. */
1173 YYSTYPE *yyvs1 = yyvs;
1174 short int *yyss1 = yyss;
1175
1176
1177 /* Each stack pointer address is followed by the size of the
1178 data in use in that stack, in bytes. This used to be a
1179 conditional around just the two extra args, but that might
1180 be undefined if yyoverflow is a macro. */
1181 yyoverflow ("parser stack overflow",
1182 &yyss1, yysize * sizeof (*yyssp),
1183 &yyvs1, yysize * sizeof (*yyvsp),
1184
1185 &yystacksize);
1186
1187 yyss = yyss1;
1188 yyvs = yyvs1;
1189 }
1190#else /* no yyoverflow */
1191# ifndef YYSTACK_RELOCATE
1192 goto yyoverflowlab;
1193# else
1194 /* Extend the stack our own way. */
1195 if (YYMAXDEPTH <= yystacksize)
1196 goto yyoverflowlab;
1197 yystacksize *= 2;
1198 if (YYMAXDEPTH < yystacksize)
1199 yystacksize = YYMAXDEPTH;
1200
1201 {
1202 short int *yyss1 = yyss;
1203 union yyalloc *yyptr =
1204 (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
1205 if (! yyptr)
1206 goto yyoverflowlab;
1207 YYSTACK_RELOCATE (yyss);
1208 YYSTACK_RELOCATE (yyvs);
1209
1210# undef YYSTACK_RELOCATE
1211 if (yyss1 != yyssa)
1212 YYSTACK_FREE (yyss1);
1213 }
1214# endif
1215#endif /* no yyoverflow */
1216
1217 yyssp = yyss + yysize - 1;
1218 yyvsp = yyvs + yysize - 1;
1219
1220
1221 YYDPRINTF ((stderr, "Stack size increased to %lu\n",
1222 (unsigned long int) yystacksize));
1223
1224 if (yyss + yystacksize - 1 <= yyssp)
1225 YYABORT;
1226 }
1227
1228 YYDPRINTF ((stderr, "Entering state %d\n", yystate));
1229
1230 goto yybackup;
1231
1232/*-----------.
1233| yybackup. |
1234`-----------*/
1235yybackup:
1236
1237/* Do appropriate processing given the current state. */
1238/* Read a look-ahead token if we need one and don't already have one. */
1239/* yyresume: */
1240
1241 /* First try to decide what to do without reference to look-ahead token. */
1242
1243 yyn = yypact[yystate];
1244 if (yyn == YYPACT_NINF)
1245 goto yydefault;
1246
1247 /* Not known => get a look-ahead token if don't already have one. */
1248
1249 /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
1250 if (yychar == YYEMPTY)
1251 {
1252 YYDPRINTF ((stderr, "Reading a token: "));
1253 yychar = YYLEX;
1254 }
1255
1256 if (yychar <= YYEOF)
1257 {
1258 yychar = yytoken = YYEOF;
1259 YYDPRINTF ((stderr, "Now at end of input.\n"));
1260 }
1261 else
1262 {
1263 yytoken = YYTRANSLATE (yychar);
1264 YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
1265 }
1266
1267 /* If the proper action on seeing token YYTOKEN is to reduce or to
1268 detect an error, take that action. */
1269 yyn += yytoken;
1270 if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
1271 goto yydefault;
1272 yyn = yytable[yyn];
1273 if (yyn <= 0)
1274 {
1275 if (yyn == 0 || yyn == YYTABLE_NINF)
1276 goto yyerrlab;
1277 yyn = -yyn;
1278 goto yyreduce;
1279 }
1280
1281 if (yyn == YYFINAL)
1282 YYACCEPT;
1283
1284 /* Shift the look-ahead token. */
1285 YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
1286
1287 /* Discard the token being shifted unless it is eof. */
1288 if (yychar != YYEOF)
1289 yychar = YYEMPTY;
1290
1291 *++yyvsp = yylval;
1292
1293
1294 /* Count tokens shifted since error; after three, turn off error
1295 status. */
1296 if (yyerrstatus)
1297 yyerrstatus--;
1298
1299 yystate = yyn;
1300 goto yynewstate;
1301
1302
1303/*-----------------------------------------------------------.
1304| yydefault -- do the default action for the current state. |
1305`-----------------------------------------------------------*/
1306yydefault:
1307 yyn = yydefact[yystate];
1308 if (yyn == 0)
1309 goto yyerrlab;
1310 goto yyreduce;
1311
1312
1313/*-----------------------------.
1314| yyreduce -- Do a reduction. |
1315`-----------------------------*/
1316yyreduce:
1317 /* yyn is the number of a rule to reduce with. */
1318 yylen = yyr2[yyn];
1319
1320 /* If YYLEN is nonzero, implement the default value of the action:
1321 `$$ = $1'.
1322
1323 Otherwise, the following line sets YYVAL to garbage.
1324 This behavior is undocumented and Bison
1325 users should not rely upon it. Assigning to YYVAL
1326 unconditionally makes the parser a bit smaller, and it avoids a
1327 GCC warning that YYVAL may be used uninitialized. */
1328 yyval = yyvsp[1-yylen];
1329
1330
1331 YY_REDUCE_PRINT (yyn);
1332 switch (yyn)
1333 {
1334 case 8:
1335
1336 { zconf_error("unexpected end statement"); ;}
1337 break;
1338
1339 case 9:
1340
1341 { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); ;}
1342 break;
1343
1344 case 10:
1345
1346 {
1347 zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name);
1348;}
1349 break;
1350
1351 case 11:
1352
1353 { zconf_error("invalid statement"); ;}
1354 break;
1355
1356 case 25:
1357
1358 { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); ;}
1359 break;
1360
1361 case 26:
1362
1363 { zconf_error("invalid option"); ;}
1364 break;
1365
1366 case 27:
1367
1368 {
1369 struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
1370 sym->flags |= SYMBOL_OPTIONAL;
1371 menu_add_entry(sym);
1372 printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
1373;}
1374 break;
1375
1376 case 28:
1377
1378 {
1379 menu_end_entry();
1380 printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
1381;}
1382 break;
1383
1384 case 29:
1385
1386 {
1387 struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
1388 sym->flags |= SYMBOL_OPTIONAL;
1389 menu_add_entry(sym);
1390 printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
1391;}
1392 break;
1393
1394 case 30:
1395
1396 {
1397 if (current_entry->prompt)
1398 current_entry->prompt->type = P_MENU;
1399 else
1400 zconfprint("warning: menuconfig statement without prompt");
1401 menu_end_entry();
1402 printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
1403;}
1404 break;
1405
1406 case 37:
1407
1408 {
1409 menu_set_type((yyvsp[-2].id)->stype);
1410 printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
1411 zconf_curname(), zconf_lineno(),
1412 (yyvsp[-2].id)->stype);
1413;}
1414 break;
1415
1416 case 38:
1417
1418 {
1419 menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
1420 printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
1421;}
1422 break;
1423
1424 case 39:
1425
1426 {
1427 menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr));
1428 if ((yyvsp[-3].id)->stype != S_UNKNOWN)
1429 menu_set_type((yyvsp[-3].id)->stype);
1430 printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
1431 zconf_curname(), zconf_lineno(),
1432 (yyvsp[-3].id)->stype);
1433;}
1434 break;
1435
1436 case 40:
1437
1438 {
1439 menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
1440 printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
1441;}
1442 break;
1443
1444 case 41:
1445
1446 {
1447 menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr));
1448 printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
1449;}
1450 break;
1451
1452 case 42:
1453
1454 {
1455 struct symbol *sym = sym_lookup(NULL, 0);
1456 sym->flags |= SYMBOL_CHOICE;
1457 menu_add_entry(sym);
1458 menu_add_expr(P_CHOICE, NULL, NULL);
1459 printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
1460;}
1461 break;
1462
1463 case 43:
1464
1465 {
1466 (yyval.menu) = menu_add_menu();
1467;}
1468 break;
1469
1470 case 44:
1471
1472 {
1473 if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) {
1474 menu_end_menu();
1475 printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
1476 }
1477;}
1478 break;
1479
1480 case 52:
1481
1482 {
1483 menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
1484 printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
1485;}
1486 break;
1487
1488 case 53:
1489
1490 {
1491 if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) {
1492 menu_set_type((yyvsp[-2].id)->stype);
1493 printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
1494 zconf_curname(), zconf_lineno(),
1495 (yyvsp[-2].id)->stype);
1496 } else
1497 YYERROR;
1498;}
1499 break;
1500
1501 case 54:
1502
1503 {
1504 current_entry->sym->flags |= SYMBOL_OPTIONAL;
1505 printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
1506;}
1507 break;
1508
1509 case 55:
1510
1511 {
1512 if ((yyvsp[-3].id)->stype == S_UNKNOWN) {
1513 menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
1514 printd(DEBUG_PARSE, "%s:%d:default\n",
1515 zconf_curname(), zconf_lineno());
1516 } else
1517 YYERROR;
1518;}
1519 break;
1520
1521 case 58:
1522
1523 {
1524 printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
1525 menu_add_entry(NULL);
1526 menu_add_dep((yyvsp[-1].expr));
1527 (yyval.menu) = menu_add_menu();
1528;}
1529 break;
1530
1531 case 59:
1532
1533 {
1534 if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) {
1535 menu_end_menu();
1536 printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
1537 }
1538;}
1539 break;
1540
1541 case 65:
1542
1543 {
1544 menu_add_entry(NULL);
1545 menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
1546 printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
1547;}
1548 break;
1549
1550 case 66:
1551
1552 {
1553 (yyval.menu) = menu_add_menu();
1554;}
1555 break;
1556
1557 case 67:
1558
1559 {
1560 if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) {
1561 menu_end_menu();
1562 printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
1563 }
1564;}
1565 break;
1566
1567 case 73:
1568
1569 {
1570 printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
1571 zconf_nextfile((yyvsp[-1].string));
1572;}
1573 break;
1574
1575 case 74:
1576
1577 {
1578 menu_add_entry(NULL);
1579 menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL);
1580 printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
1581;}
1582 break;
1583
1584 case 75:
1585
1586 {
1587 menu_end_entry();
1588;}
1589 break;
1590
1591 case 76:
1592
1593 {
1594 printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
1595 zconf_starthelp();
1596;}
1597 break;
1598
1599 case 77:
1600
1601 {
1602 current_entry->sym->help = (yyvsp[0].string);
1603;}
1604 break;
1605
1606 case 82:
1607
1608 {
1609 menu_add_dep((yyvsp[-1].expr));
1610 printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
1611;}
1612 break;
1613
1614 case 83:
1615
1616 {
1617 menu_add_dep((yyvsp[-1].expr));
1618 printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
1619;}
1620 break;
1621
1622 case 84:
1623
1624 {
1625 menu_add_dep((yyvsp[-1].expr));
1626 printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
1627;}
1628 break;
1629
1630 case 86:
1631
1632 {
1633 menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr));
1634;}
1635 break;
1636
1637 case 89:
1638
1639 { (yyval.id) = (yyvsp[-1].id); ;}
1640 break;
1641
1642 case 90:
1643
1644 { (yyval.id) = (yyvsp[-1].id); ;}
1645 break;
1646
1647 case 91:
1648
1649 { (yyval.id) = (yyvsp[-1].id); ;}
1650 break;
1651
1652 case 94:
1653
1654 { (yyval.expr) = NULL; ;}
1655 break;
1656
1657 case 95:
1658
1659 { (yyval.expr) = (yyvsp[0].expr); ;}
1660 break;
1661
1662 case 96:
1663
1664 { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;}
1665 break;
1666
1667 case 97:
1668
1669 { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
1670 break;
1671
1672 case 98:
1673
1674 { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
1675 break;
1676
1677 case 99:
1678
1679 { (yyval.expr) = (yyvsp[-1].expr); ;}
1680 break;
1681
1682 case 100:
1683
1684 { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;}
1685 break;
1686
1687 case 101:
1688
1689 { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
1690 break;
1691
1692 case 102:
1693
1694 { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
1695 break;
1696
1697 case 103:
1698
1699 { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;}
1700 break;
1701
1702 case 104:
1703
1704 { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;}
1705 break;
1706
1707
1708 }
1709
1710/* Line 1037 of yacc.c. */
1711
1712
1713 yyvsp -= yylen;
1714 yyssp -= yylen;
1715
1716
1717 YY_STACK_PRINT (yyss, yyssp);
1718
1719 *++yyvsp = yyval;
1720
1721
1722 /* Now `shift' the result of the reduction. Determine what state
1723 that goes to, based on the state we popped back to and the rule
1724 number reduced by. */
1725
1726 yyn = yyr1[yyn];
1727
1728 yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
1729 if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1730 yystate = yytable[yystate];
1731 else
1732 yystate = yydefgoto[yyn - YYNTOKENS];
1733
1734 goto yynewstate;
1735
1736
1737/*------------------------------------.
1738| yyerrlab -- here on detecting error |
1739`------------------------------------*/
1740yyerrlab:
1741 /* If not already recovering from an error, report this error. */
1742 if (!yyerrstatus)
1743 {
1744 ++yynerrs;
1745#if YYERROR_VERBOSE
1746 yyn = yypact[yystate];
1747
1748 if (YYPACT_NINF < yyn && yyn < YYLAST)
1749 {
1750 YYSIZE_T yysize = 0;
1751 int yytype = YYTRANSLATE (yychar);
1752 const char* yyprefix;
1753 char *yymsg;
1754 int yyx;
1755
1756 /* Start YYX at -YYN if negative to avoid negative indexes in
1757 YYCHECK. */
1758 int yyxbegin = yyn < 0 ? -yyn : 0;
1759
1760 /* Stay within bounds of both yycheck and yytname. */
1761 int yychecklim = YYLAST - yyn;
1762 int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
1763 int yycount = 0;
1764
1765 yyprefix = ", expecting ";
1766 for (yyx = yyxbegin; yyx < yyxend; ++yyx)
1767 if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1768 {
1769 yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
1770 yycount += 1;
1771 if (yycount == 5)
1772 {
1773 yysize = 0;
1774 break;
1775 }
1776 }
1777 yysize += (sizeof ("syntax error, unexpected ")
1778 + yystrlen (yytname[yytype]));
1779 yymsg = (char *) YYSTACK_ALLOC (yysize);
1780 if (yymsg != 0)
1781 {
1782 char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
1783 yyp = yystpcpy (yyp, yytname[yytype]);
1784
1785 if (yycount < 5)
1786 {
1787 yyprefix = ", expecting ";
1788 for (yyx = yyxbegin; yyx < yyxend; ++yyx)
1789 if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1790 {
1791 yyp = yystpcpy (yyp, yyprefix);
1792 yyp = yystpcpy (yyp, yytname[yyx]);
1793 yyprefix = " or ";
1794 }
1795 }
1796 yyerror (yymsg);
1797 YYSTACK_FREE (yymsg);
1798 }
1799 else
1800 yyerror ("syntax error; also virtual memory exhausted");
1801 }
1802 else
1803#endif /* YYERROR_VERBOSE */
1804 yyerror ("syntax error");
1805 }
1806
1807
1808
1809 if (yyerrstatus == 3)
1810 {
1811 /* If just tried and failed to reuse look-ahead token after an
1812 error, discard it. */
1813
1814 if (yychar <= YYEOF)
1815 {
1816 /* If at end of input, pop the error token,
1817 then the rest of the stack, then return failure. */
1818 if (yychar == YYEOF)
1819 for (;;)
1820 {
1821
1822 YYPOPSTACK;
1823 if (yyssp == yyss)
1824 YYABORT;
1825 yydestruct ("Error: popping",
1826 yystos[*yyssp], yyvsp);
1827 }
1828 }
1829 else
1830 {
1831 yydestruct ("Error: discarding", yytoken, &yylval);
1832 yychar = YYEMPTY;
1833 }
1834 }
1835
1836 /* Else will try to reuse look-ahead token after shifting the error
1837 token. */
1838 goto yyerrlab1;
1839
1840
1841/*---------------------------------------------------.
1842| yyerrorlab -- error raised explicitly by YYERROR. |
1843`---------------------------------------------------*/
1844yyerrorlab:
1845
1846#ifdef __GNUC__
1847 /* Pacify GCC when the user code never invokes YYERROR and the label
1848 yyerrorlab therefore never appears in user code. */
1849 if (0)
1850 goto yyerrorlab;
1851#endif
1852
1853yyvsp -= yylen;
1854 yyssp -= yylen;
1855 yystate = *yyssp;
1856 goto yyerrlab1;
1857
1858
1859/*-------------------------------------------------------------.
1860| yyerrlab1 -- common code for both syntax error and YYERROR. |
1861`-------------------------------------------------------------*/
1862yyerrlab1:
1863 yyerrstatus = 3; /* Each real token shifted decrements this. */
1864
1865 for (;;)
1866 {
1867 yyn = yypact[yystate];
1868 if (yyn != YYPACT_NINF)
1869 {
1870 yyn += YYTERROR;
1871 if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
1872 {
1873 yyn = yytable[yyn];
1874 if (0 < yyn)
1875 break;
1876 }
1877 }
1878
1879 /* Pop the current state because it cannot handle the error token. */
1880 if (yyssp == yyss)
1881 YYABORT;
1882
1883
1884 yydestruct ("Error: popping", yystos[yystate], yyvsp);
1885 YYPOPSTACK;
1886 yystate = *yyssp;
1887 YY_STACK_PRINT (yyss, yyssp);
1888 }
1889
1890 if (yyn == YYFINAL)
1891 YYACCEPT;
1892
1893 *++yyvsp = yylval;
1894
1895
1896 /* Shift the error token. */
1897 YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
1898
1899 yystate = yyn;
1900 goto yynewstate;
1901
1902
1903/*-------------------------------------.
1904| yyacceptlab -- YYACCEPT comes here. |
1905`-------------------------------------*/
1906yyacceptlab:
1907 yyresult = 0;
1908 goto yyreturn;
1909
1910/*-----------------------------------.
1911| yyabortlab -- YYABORT comes here. |
1912`-----------------------------------*/
1913yyabortlab:
1914 yydestruct ("Error: discarding lookahead",
1915 yytoken, &yylval);
1916 yychar = YYEMPTY;
1917 yyresult = 1;
1918 goto yyreturn;
1919
1920#ifndef yyoverflow
1921/*----------------------------------------------.
1922| yyoverflowlab -- parser overflow comes here. |
1923`----------------------------------------------*/
1924yyoverflowlab:
1925 yyerror ("parser stack overflow");
1926 yyresult = 2;
1927 /* Fall through. */
1928#endif
1929
1930yyreturn:
1931#ifndef yyoverflow
1932 if (yyss != yyssa)
1933 YYSTACK_FREE (yyss);
1934#endif
1935 return yyresult;
1936}
1937
1938
1939
1940
1941
1942void conf_parse(const char *name)
1943{
1944 struct symbol *sym;
1945 int i;
1946
1947 zconf_initscan(name);
1948
1949 sym_init();
1950 menu_init();
1951 modules_sym = sym_lookup("MODULES", 0);
1952 rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
1953
1954#if YYDEBUG
1955 if (getenv("ZCONF_DEBUG"))
1956 zconfdebug = 1;
1957#endif
1958 zconfparse();
1959 if (zconfnerrs)
1960 exit(1);
1961 menu_finalize(&rootmenu);
1962 for_all_symbols(i, sym) {
1963 sym_check_deps(sym);
1964 }
1965
1966 sym_change_count = 1;
1967}
1968
1969const char *zconf_tokenname(int token)
1970{
1971 switch (token) {
1972 case T_MENU: return "menu";
1973 case T_ENDMENU: return "endmenu";
1974 case T_CHOICE: return "choice";
1975 case T_ENDCHOICE: return "endchoice";
1976 case T_IF: return "if";
1977 case T_ENDIF: return "endif";
1978 case T_DEPENDS: return "depends";
1979 }
1980 return "<token>";
1981}
1982
1983static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
1984{
1985 if (id->token != endtoken) {
1986 zconf_error("unexpected '%s' within %s block",
1987 kconf_id_strings + id->name, zconf_tokenname(starttoken));
1988 zconfnerrs++;
1989 return false;
1990 }
1991 if (current_menu->file != current_file) {
1992 zconf_error("'%s' in different file than '%s'",
1993 kconf_id_strings + id->name, zconf_tokenname(starttoken));
1994 fprintf(stderr, "%s:%d: location of the '%s'\n",
1995 current_menu->file->name, current_menu->lineno,
1996 zconf_tokenname(starttoken));
1997 zconfnerrs++;
1998 return false;
1999 }
2000 return true;
2001}
2002
2003static void zconfprint(const char *err, ...)
2004{
2005 va_list ap;
2006
2007 fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
2008 va_start(ap, err);
2009 vfprintf(stderr, err, ap);
2010 va_end(ap);
2011 fprintf(stderr, "\n");
2012}
2013
2014static void zconf_error(const char *err, ...)
2015{
2016 va_list ap;
2017
2018 zconfnerrs++;
2019 fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
2020 va_start(ap, err);
2021 vfprintf(stderr, err, ap);
2022 va_end(ap);
2023 fprintf(stderr, "\n");
2024}
2025
2026static void zconferror(const char *err)
2027{
2028#if YYDEBUG
2029 fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
2030#endif
2031}
2032
2033void print_quoted_string(FILE *out, const char *str)
2034{
2035 const char *p;
2036 int len;
2037
2038 putc('"', out);
2039 while ((p = strchr(str, '"'))) {
2040 len = p - str;
2041 if (len)
2042 fprintf(out, "%.*s", len, str);
2043 fputs("\\\"", out);
2044 str = p + 1;
2045 }
2046 fputs(str, out);
2047 putc('"', out);
2048}
2049
2050void print_symbol(FILE *out, struct menu *menu)
2051{
2052 struct symbol *sym = menu->sym;
2053 struct property *prop;
2054
2055 if (sym_is_choice(sym))
2056 fprintf(out, "choice\n");
2057 else
2058 fprintf(out, "config %s\n", sym->name);
2059 switch (sym->type) {
2060 case S_BOOLEAN:
2061 fputs(" boolean\n", out);
2062 break;
2063 case S_TRISTATE:
2064 fputs(" tristate\n", out);
2065 break;
2066 case S_STRING:
2067 fputs(" string\n", out);
2068 break;
2069 case S_INT:
2070 fputs(" integer\n", out);
2071 break;
2072 case S_HEX:
2073 fputs(" hex\n", out);
2074 break;
2075 default:
2076 fputs(" ???\n", out);
2077 break;
2078 }
2079 for (prop = sym->prop; prop; prop = prop->next) {
2080 if (prop->menu != menu)
2081 continue;
2082 switch (prop->type) {
2083 case P_PROMPT:
2084 fputs(" prompt ", out);
2085 print_quoted_string(out, prop->text);
2086 if (!expr_is_yes(prop->visible.expr)) {
2087 fputs(" if ", out);
2088 expr_fprint(prop->visible.expr, out);
2089 }
2090 fputc('\n', out);
2091 break;
2092 case P_DEFAULT:
2093 fputs( " default ", out);
2094 expr_fprint(prop->expr, out);
2095 if (!expr_is_yes(prop->visible.expr)) {
2096 fputs(" if ", out);
2097 expr_fprint(prop->visible.expr, out);
2098 }
2099 fputc('\n', out);
2100 break;
2101 case P_CHOICE:
2102 fputs(" #choice value\n", out);
2103 break;
2104 default:
2105 fprintf(out, " unknown prop %d!\n", prop->type);
2106 break;
2107 }
2108 }
2109 if (sym->help) {
2110 int len = strlen(sym->help);
2111 while (sym->help[--len] == '\n')
2112 sym->help[len] = 0;
2113 fprintf(out, " help\n%s\n", sym->help);
2114 }
2115 fputc('\n', out);
2116}
2117
2118void zconfdump(FILE *out)
2119{
2120 struct property *prop;
2121 struct symbol *sym;
2122 struct menu *menu;
2123
2124 menu = rootmenu.list;
2125 while (menu) {
2126 if ((sym = menu->sym))
2127 print_symbol(out, menu);
2128 else if ((prop = menu->prompt)) {
2129 switch (prop->type) {
2130 case P_COMMENT:
2131 fputs("\ncomment ", out);
2132 print_quoted_string(out, prop->text);
2133 fputs("\n", out);
2134 break;
2135 case P_MENU:
2136 fputs("\nmenu ", out);
2137 print_quoted_string(out, prop->text);
2138 fputs("\n", out);
2139 break;
2140 default:
2141 ;
2142 }
2143 if (!expr_is_yes(prop->visible.expr)) {
2144 fputs(" depends ", out);
2145 expr_fprint(prop->visible.expr, out);
2146 fputc('\n', out);
2147 }
2148 fputs("\n", out);
2149 }
2150
2151 if (menu->list)
2152 menu = menu->list;
2153 else if (menu->next)
2154 menu = menu->next;
2155 else while ((menu = menu->parent)) {
2156 if (menu->prompt && menu->prompt->type == P_MENU)
2157 fputs("\nendmenu\n", out);
2158 if (menu->next) {
2159 menu = menu->next;
2160 break;
2161 }
2162 }
2163 }
2164}
2165
2166#include "lex.zconf.c"
2167#include "util.c"
2168#include "confdata.c"
2169#include "expr.c"
2170#include "symbol.c"
2171#include "menu.c"
2172
2173
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
new file mode 100644
index 000000000..1f61fba6a
--- /dev/null
+++ b/scripts/kconfig/zconf.y
@@ -0,0 +1,681 @@
1%{
2/*
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
4 * Released under the terms of the GNU GPL v2.0.
5 */
6
7#include <ctype.h>
8#include <stdarg.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <stdbool.h>
13
14#define LKC_DIRECT_LINK
15#include "lkc.h"
16
17#include "zconf.hash.c"
18
19#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
20
21#define PRINTD 0x0001
22#define DEBUG_PARSE 0x0002
23
24int cdebug = PRINTD;
25
26extern int zconflex(void);
27static void zconfprint(const char *err, ...);
28static void zconf_error(const char *err, ...);
29static void zconferror(const char *err);
30static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
31
32struct symbol *symbol_hash[257];
33
34static struct menu *current_menu, *current_entry;
35
36#define YYDEBUG 0
37#if YYDEBUG
38#define YYERROR_VERBOSE
39#endif
40%}
41%expect 26
42
43%union
44{
45 char *string;
46 struct file *file;
47 struct symbol *symbol;
48 struct expr *expr;
49 struct menu *menu;
50 struct kconf_id *id;
51}
52
53%token <id>T_MAINMENU
54%token <id>T_MENU
55%token <id>T_ENDMENU
56%token <id>T_SOURCE
57%token <id>T_CHOICE
58%token <id>T_ENDCHOICE
59%token <id>T_COMMENT
60%token <id>T_CONFIG
61%token <id>T_MENUCONFIG
62%token <id>T_HELP
63%token <string> T_HELPTEXT
64%token <id>T_IF
65%token <id>T_ENDIF
66%token <id>T_DEPENDS
67%token <id>T_REQUIRES
68%token <id>T_OPTIONAL
69%token <id>T_PROMPT
70%token <id>T_TYPE
71%token <id>T_DEFAULT
72%token <id>T_SELECT
73%token <id>T_RANGE
74%token <id>T_ON
75%token <string> T_WORD
76%token <string> T_WORD_QUOTE
77%token T_UNEQUAL
78%token T_CLOSE_PAREN
79%token T_OPEN_PAREN
80%token T_EOL
81
82%left T_OR
83%left T_AND
84%left T_EQUAL T_UNEQUAL
85%nonassoc T_NOT
86
87%type <string> prompt
88%type <symbol> symbol
89%type <expr> expr
90%type <expr> if_expr
91%type <id> end
92%type <id> option_name
93%type <menu> if_entry menu_entry choice_entry
94
95%destructor {
96 fprintf(stderr, "%s:%d: missing end statement for this entry\n",
97 $$->file->name, $$->lineno);
98 if (current_menu == $$)
99 menu_end_menu();
100} if_entry menu_entry choice_entry
101
102%%
103input: stmt_list;
104
105stmt_list:
106 /* empty */
107 | stmt_list common_stmt
108 | stmt_list choice_stmt
109 | stmt_list menu_stmt
110 | stmt_list T_MAINMENU prompt nl
111 | stmt_list end { zconf_error("unexpected end statement"); }
112 | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
113 | stmt_list option_name error T_EOL
114{
115 zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
116}
117 | stmt_list error T_EOL { zconf_error("invalid statement"); }
118;
119
120option_name:
121 T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
122;
123
124common_stmt:
125 T_EOL
126 | if_stmt
127 | comment_stmt
128 | config_stmt
129 | menuconfig_stmt
130 | source_stmt
131;
132
133option_error:
134 T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
135 | error T_EOL { zconf_error("invalid option"); }
136;
137
138
139/* config/menuconfig entry */
140
141config_entry_start: T_CONFIG T_WORD T_EOL
142{
143 struct symbol *sym = sym_lookup($2, 0);
144 sym->flags |= SYMBOL_OPTIONAL;
145 menu_add_entry(sym);
146 printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
147};
148
149config_stmt: config_entry_start config_option_list
150{
151 menu_end_entry();
152 printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
153};
154
155menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
156{
157 struct symbol *sym = sym_lookup($2, 0);
158 sym->flags |= SYMBOL_OPTIONAL;
159 menu_add_entry(sym);
160 printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
161};
162
163menuconfig_stmt: menuconfig_entry_start config_option_list
164{
165 if (current_entry->prompt)
166 current_entry->prompt->type = P_MENU;
167 else
168 zconfprint("warning: menuconfig statement without prompt");
169 menu_end_entry();
170 printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
171};
172
173config_option_list:
174 /* empty */
175 | config_option_list config_option
176 | config_option_list depends
177 | config_option_list help
178 | config_option_list option_error
179 | config_option_list T_EOL
180;
181
182config_option: T_TYPE prompt_stmt_opt T_EOL
183{
184 menu_set_type($1->stype);
185 printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
186 zconf_curname(), zconf_lineno(),
187 $1->stype);
188};
189
190config_option: T_PROMPT prompt if_expr T_EOL
191{
192 menu_add_prompt(P_PROMPT, $2, $3);
193 printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
194};
195
196config_option: T_DEFAULT expr if_expr T_EOL
197{
198 menu_add_expr(P_DEFAULT, $2, $3);
199 if ($1->stype != S_UNKNOWN)
200 menu_set_type($1->stype);
201 printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
202 zconf_curname(), zconf_lineno(),
203 $1->stype);
204};
205
206config_option: T_SELECT T_WORD if_expr T_EOL
207{
208 menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
209 printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
210};
211
212config_option: T_RANGE symbol symbol if_expr T_EOL
213{
214 menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
215 printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
216};
217
218/* choice entry */
219
220choice: T_CHOICE T_EOL
221{
222 struct symbol *sym = sym_lookup(NULL, 0);
223 sym->flags |= SYMBOL_CHOICE;
224 menu_add_entry(sym);
225 menu_add_expr(P_CHOICE, NULL, NULL);
226 printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
227};
228
229choice_entry: choice choice_option_list
230{
231 $$ = menu_add_menu();
232};
233
234choice_end: end
235{
236 if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
237 menu_end_menu();
238 printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
239 }
240};
241
242choice_stmt: choice_entry choice_block choice_end
243;
244
245choice_option_list:
246 /* empty */
247 | choice_option_list choice_option
248 | choice_option_list depends
249 | choice_option_list help
250 | choice_option_list T_EOL
251 | choice_option_list option_error
252;
253
254choice_option: T_PROMPT prompt if_expr T_EOL
255{
256 menu_add_prompt(P_PROMPT, $2, $3);
257 printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
258};
259
260choice_option: T_TYPE prompt_stmt_opt T_EOL
261{
262 if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
263 menu_set_type($1->stype);
264 printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
265 zconf_curname(), zconf_lineno(),
266 $1->stype);
267 } else
268 YYERROR;
269};
270
271choice_option: T_OPTIONAL T_EOL
272{
273 current_entry->sym->flags |= SYMBOL_OPTIONAL;
274 printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
275};
276
277choice_option: T_DEFAULT T_WORD if_expr T_EOL
278{
279 if ($1->stype == S_UNKNOWN) {
280 menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
281 printd(DEBUG_PARSE, "%s:%d:default\n",
282 zconf_curname(), zconf_lineno());
283 } else
284 YYERROR;
285};
286
287choice_block:
288 /* empty */
289 | choice_block common_stmt
290;
291
292/* if entry */
293
294if_entry: T_IF expr nl
295{
296 printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
297 menu_add_entry(NULL);
298 menu_add_dep($2);
299 $$ = menu_add_menu();
300};
301
302if_end: end
303{
304 if (zconf_endtoken($1, T_IF, T_ENDIF)) {
305 menu_end_menu();
306 printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
307 }
308};
309
310if_stmt: if_entry if_block if_end
311;
312
313if_block:
314 /* empty */
315 | if_block common_stmt
316 | if_block menu_stmt
317 | if_block choice_stmt
318;
319
320/* menu entry */
321
322menu: T_MENU prompt T_EOL
323{
324 menu_add_entry(NULL);
325 menu_add_prompt(P_MENU, $2, NULL);
326 printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
327};
328
329menu_entry: menu depends_list
330{
331 $$ = menu_add_menu();
332};
333
334menu_end: end
335{
336 if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
337 menu_end_menu();
338 printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
339 }
340};
341
342menu_stmt: menu_entry menu_block menu_end
343;
344
345menu_block:
346 /* empty */
347 | menu_block common_stmt
348 | menu_block menu_stmt
349 | menu_block choice_stmt
350;
351
352source_stmt: T_SOURCE prompt T_EOL
353{
354 printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
355 zconf_nextfile($2);
356};
357
358/* comment entry */
359
360comment: T_COMMENT prompt T_EOL
361{
362 menu_add_entry(NULL);
363 menu_add_prompt(P_COMMENT, $2, NULL);
364 printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
365};
366
367comment_stmt: comment depends_list
368{
369 menu_end_entry();
370};
371
372/* help option */
373
374help_start: T_HELP T_EOL
375{
376 printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
377 zconf_starthelp();
378};
379
380help: help_start T_HELPTEXT
381{
382 current_entry->sym->help = $2;
383};
384
385/* depends option */
386
387depends_list:
388 /* empty */
389 | depends_list depends
390 | depends_list T_EOL
391 | depends_list option_error
392;
393
394depends: T_DEPENDS T_ON expr T_EOL
395{
396 menu_add_dep($3);
397 printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
398}
399 | T_DEPENDS expr T_EOL
400{
401 menu_add_dep($2);
402 printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
403}
404 | T_REQUIRES expr T_EOL
405{
406 menu_add_dep($2);
407 printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
408};
409
410/* prompt statement */
411
412prompt_stmt_opt:
413 /* empty */
414 | prompt if_expr
415{
416 menu_add_prompt(P_PROMPT, $1, $2);
417};
418
419prompt: T_WORD
420 | T_WORD_QUOTE
421;
422
423end: T_ENDMENU T_EOL { $$ = $1; }
424 | T_ENDCHOICE T_EOL { $$ = $1; }
425 | T_ENDIF T_EOL { $$ = $1; }
426;
427
428nl:
429 T_EOL
430 | nl T_EOL
431;
432
433if_expr: /* empty */ { $$ = NULL; }
434 | T_IF expr { $$ = $2; }
435;
436
437expr: symbol { $$ = expr_alloc_symbol($1); }
438 | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
439 | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
440 | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
441 | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
442 | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
443 | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
444;
445
446symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
447 | T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); }
448;
449
450%%
451
452void conf_parse(const char *name)
453{
454 struct symbol *sym;
455 int i;
456
457 zconf_initscan(name);
458
459 sym_init();
460 menu_init();
461 modules_sym = sym_lookup("MODULES", 0);
462 rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
463
464#if YYDEBUG
465 if (getenv("ZCONF_DEBUG"))
466 zconfdebug = 1;
467#endif
468 zconfparse();
469 if (zconfnerrs)
470 exit(1);
471 menu_finalize(&rootmenu);
472 for_all_symbols(i, sym) {
473 sym_check_deps(sym);
474 }
475
476 sym_change_count = 1;
477}
478
479const char *zconf_tokenname(int token)
480{
481 switch (token) {
482 case T_MENU: return "menu";
483 case T_ENDMENU: return "endmenu";
484 case T_CHOICE: return "choice";
485 case T_ENDCHOICE: return "endchoice";
486 case T_IF: return "if";
487 case T_ENDIF: return "endif";
488 case T_DEPENDS: return "depends";
489 }
490 return "<token>";
491}
492
493static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
494{
495 if (id->token != endtoken) {
496 zconf_error("unexpected '%s' within %s block",
497 kconf_id_strings + id->name, zconf_tokenname(starttoken));
498 zconfnerrs++;
499 return false;
500 }
501 if (current_menu->file != current_file) {
502 zconf_error("'%s' in different file than '%s'",
503 kconf_id_strings + id->name, zconf_tokenname(starttoken));
504 fprintf(stderr, "%s:%d: location of the '%s'\n",
505 current_menu->file->name, current_menu->lineno,
506 zconf_tokenname(starttoken));
507 zconfnerrs++;
508 return false;
509 }
510 return true;
511}
512
513static void zconfprint(const char *err, ...)
514{
515 va_list ap;
516
517 fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
518 va_start(ap, err);
519 vfprintf(stderr, err, ap);
520 va_end(ap);
521 fprintf(stderr, "\n");
522}
523
524static void zconf_error(const char *err, ...)
525{
526 va_list ap;
527
528 zconfnerrs++;
529 fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
530 va_start(ap, err);
531 vfprintf(stderr, err, ap);
532 va_end(ap);
533 fprintf(stderr, "\n");
534}
535
536static void zconferror(const char *err)
537{
538#if YYDEBUG
539 fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
540#endif
541}
542
543void print_quoted_string(FILE *out, const char *str)
544{
545 const char *p;
546 int len;
547
548 putc('"', out);
549 while ((p = strchr(str, '"'))) {
550 len = p - str;
551 if (len)
552 fprintf(out, "%.*s", len, str);
553 fputs("\\\"", out);
554 str = p + 1;
555 }
556 fputs(str, out);
557 putc('"', out);
558}
559
560void print_symbol(FILE *out, struct menu *menu)
561{
562 struct symbol *sym = menu->sym;
563 struct property *prop;
564
565 if (sym_is_choice(sym))
566 fprintf(out, "choice\n");
567 else
568 fprintf(out, "config %s\n", sym->name);
569 switch (sym->type) {
570 case S_BOOLEAN:
571 fputs(" boolean\n", out);
572 break;
573 case S_TRISTATE:
574 fputs(" tristate\n", out);
575 break;
576 case S_STRING:
577 fputs(" string\n", out);
578 break;
579 case S_INT:
580 fputs(" integer\n", out);
581 break;
582 case S_HEX:
583 fputs(" hex\n", out);
584 break;
585 default:
586 fputs(" ???\n", out);
587 break;
588 }
589 for (prop = sym->prop; prop; prop = prop->next) {
590 if (prop->menu != menu)
591 continue;
592 switch (prop->type) {
593 case P_PROMPT:
594 fputs(" prompt ", out);
595 print_quoted_string(out, prop->text);
596 if (!expr_is_yes(prop->visible.expr)) {
597 fputs(" if ", out);
598 expr_fprint(prop->visible.expr, out);
599 }
600 fputc('\n', out);
601 break;
602 case P_DEFAULT:
603 fputs( " default ", out);
604 expr_fprint(prop->expr, out);
605 if (!expr_is_yes(prop->visible.expr)) {
606 fputs(" if ", out);
607 expr_fprint(prop->visible.expr, out);
608 }
609 fputc('\n', out);
610 break;
611 case P_CHOICE:
612 fputs(" #choice value\n", out);
613 break;
614 default:
615 fprintf(out, " unknown prop %d!\n", prop->type);
616 break;
617 }
618 }
619 if (sym->help) {
620 int len = strlen(sym->help);
621 while (sym->help[--len] == '\n')
622 sym->help[len] = 0;
623 fprintf(out, " help\n%s\n", sym->help);
624 }
625 fputc('\n', out);
626}
627
628void zconfdump(FILE *out)
629{
630 struct property *prop;
631 struct symbol *sym;
632 struct menu *menu;
633
634 menu = rootmenu.list;
635 while (menu) {
636 if ((sym = menu->sym))
637 print_symbol(out, menu);
638 else if ((prop = menu->prompt)) {
639 switch (prop->type) {
640 case P_COMMENT:
641 fputs("\ncomment ", out);
642 print_quoted_string(out, prop->text);
643 fputs("\n", out);
644 break;
645 case P_MENU:
646 fputs("\nmenu ", out);
647 print_quoted_string(out, prop->text);
648 fputs("\n", out);
649 break;
650 default:
651 ;
652 }
653 if (!expr_is_yes(prop->visible.expr)) {
654 fputs(" depends ", out);
655 expr_fprint(prop->visible.expr, out);
656 fputc('\n', out);
657 }
658 fputs("\n", out);
659 }
660
661 if (menu->list)
662 menu = menu->list;
663 else if (menu->next)
664 menu = menu->next;
665 else while ((menu = menu->parent)) {
666 if (menu->prompt && menu->prompt->type == P_MENU)
667 fputs("\nendmenu\n", out);
668 if (menu->next) {
669 menu = menu->next;
670 break;
671 }
672 }
673 }
674}
675
676#include "lex.zconf.c"
677#include "util.c"
678#include "confdata.c"
679#include "expr.c"
680#include "symbol.c"
681#include "menu.c"
diff --git a/scripts/mkconfigs b/scripts/mkconfigs
new file mode 100755
index 000000000..fda9de72f
--- /dev/null
+++ b/scripts/mkconfigs
@@ -0,0 +1,51 @@
1#!/bin/sh
2#
3# Copyright (C) 2002 Khalid Aziz <khalid_aziz at hp.com>
4# Copyright (C) 2002 Randy Dunlap <rddunlap at osdl.org>
5# Copyright (C) 2002 Al Stone <ahs3 at fc.hp.com>
6# Copyright (C) 2002 Hewlett-Packard Company
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21#
22# Busybox version by Matteo Croce <3297627799 at wind.it>
23#
24# Rules to generate bbconfig.h from .config:
25# - Retain lines that begin with "CONFIG_"
26# - Retain lines that begin with "# CONFIG_"
27# - lines that use double-quotes must \\-escape-quote them
28
29if [ $# -lt 1 ]
30then
31 config=.config
32else config=$1
33fi
34
35echo "#ifndef _BBCONFIGOPTS_H"
36echo "#define _BBCONFIGOPTS_H"
37echo \
38"/*
39 * busybox configuration settings.
40 *
41 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
42 *
43 * This file is generated automatically by scripts/config/mkconfigs.
44 * Do not edit.
45 *
46 */"
47
48echo "static const char * const bbconfig_config ="
49echo "`sed 's/\"/\\\\\"/g' $config | grep "^#\? \?CONFIG_" | awk '{print "\\"" $0 "\\\\n\\"";}'`"
50echo ";"
51echo "#endif /* _BBCONFIGOPTS_H */"
diff --git a/scripts/trylink b/scripts/trylink
new file mode 100755
index 000000000..dfe282db5
--- /dev/null
+++ b/scripts/trylink
@@ -0,0 +1,18 @@
1#!/bin/sh
2
3debug=false
4
5function try {
6 added="$1"
7 shift
8 $debug && echo "Trying: $* $added"
9 "$@" $added >/dev/null 2>&1 \
10 && exit 0
11}
12
13try "" "$@"
14try "-lm" "$@"
15try "-lcrypt" "$@"
16try "-Wl,--start-group -lcrypt -lm -Wl,--end-group" "$@"
17# It failed. Rerun & let people see the error messages
18"$@" $added
diff --git a/scripts/usage.c b/scripts/usage.c
index 373642cd6..adb290e4d 100644
--- a/scripts/usage.c
+++ b/scripts/usage.c
@@ -1,11 +1,13 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2#include <unistd.h> 2#include <unistd.h>
3#include "busybox.h" 3
4#include "../include/autoconf.h"
5#include "../include/busybox.h"
4 6
5static const char usage_messages[] = 7static const char usage_messages[] =
6#define MAKE_USAGE 8#define MAKE_USAGE
7#include "usage.h" 9#include "../include/usage.h"
8#include "applets.h" 10#include "../include/applets.h"
9; 11;
10 12
11int main(void) 13int main(void)
diff --git a/scripts/usage_compressed b/scripts/usage_compressed
index 8e2228af2..ab164aa12 100644..100755
--- a/scripts/usage_compressed
+++ b/scripts/usage_compressed
@@ -1,13 +1,19 @@
1#!/bin/sh 1#!/bin/sh
2 2
3loc="$1" 3target="$1"
4loc="$2"
4 5
6test "$target" || exit 1
5test "$loc" || loc=. 7test "$loc" || loc=.
6test -x "$loc/usage" || exit 1 8test -x "$loc/usage" || exit 1
9test "$SED" || SED=sed
10
11sz=`"$loc/usage" | wc -c` || exit 1
12
13exec >"$target"
7 14
8echo 'static const char packed_usage[] = ' 15echo 'static const char packed_usage[] = '
9"$loc"/usage | bzip2 -1 | od -v -t x1 \ 16"$loc/usage" | bzip2 -1 | od -v -t x1 \
10| $SED -e 's/^[^ ]*//' -e 's/ \(..\)/\\x\1/g' -e 's/^\(.*\)$/"\1"/' || exit 1 17| $SED -e 's/^[^ ]*//' -e 's/ \(..\)/\\x\1/g' -e 's/^\(.*\)$/"\1"/'
11echo ';' 18echo ';'
12sz=`"$loc"/usage | wc -c` || exit 1
13echo '#define SIZEOF_usage_messages' `expr 0 + $sz` 19echo '#define SIZEOF_usage_messages' `expr 0 + $sz`