diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 | 
| commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
| tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /scripts | |
| download | linux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.bz2 | |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'scripts')
94 files changed, 34478 insertions, 0 deletions
diff --git a/scripts/Lindent b/scripts/Lindent new file mode 100755 index 000000000000..34ed785116b6 --- /dev/null +++ b/scripts/Lindent @@ -0,0 +1,2 @@ +#!/bin/sh +indent -kr -i8 -ts8 -sob -l80 -ss -ncs "$@" diff --git a/scripts/Makefile b/scripts/Makefile new file mode 100644 index 000000000000..67763eeb8a3e --- /dev/null +++ b/scripts/Makefile @@ -0,0 +1,22 @@ +### +# scripts contains sources for various helper programs used throughout +# the kernel for the build process. +# --------------------------------------------------------------------------- +# kallsyms:      Find all symbols in vmlinux +# pnmttologo:    Convert pnm files to logo files +# conmakehash:   Create chartable +# conmakehash:	 Create arrays for initializing the kernel console tables + +hostprogs-$(CONFIG_KALLSYMS)     += kallsyms +hostprogs-$(CONFIG_LOGO)         += pnmtologo +hostprogs-$(CONFIG_VT)           += conmakehash +hostprogs-$(CONFIG_PROM_CONSOLE) += conmakehash +hostprogs-$(CONFIG_IKCONFIG)     += bin2c + +always		:= $(hostprogs-y) + +subdir-$(CONFIG_MODVERSIONS) += genksyms +subdir-$(CONFIG_MODULES)     += mod + +# Let clean descend into subdirs +subdir-	+= basic lxdialog kconfig package diff --git a/scripts/Makefile.build b/scripts/Makefile.build new file mode 100644 index 000000000000..352d531ee3c1 --- /dev/null +++ b/scripts/Makefile.build @@ -0,0 +1,330 @@ +# ========================================================================== +# Building +# ========================================================================== + +src := $(obj) + +.PHONY: __build +__build: + +# Read .config if it exist, otherwise ignore +-include .config + +include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile) + +include scripts/Makefile.lib + +ifdef host-progs +ifneq ($(hostprogs-y),$(host-progs)) +$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!) +hostprogs-y += $(host-progs) +endif +endif + +# Do not include host rules unles needed +ifneq ($(hostprogs-y)$(hostprogs-m),) +include scripts/Makefile.host +endif + +ifneq ($(KBUILD_SRC),) +# Create output directory if not already present +_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) + +# Create directories for object files if directory does not exist +# Needed when obj-y := dir/file.o syntax is used +_dummy := $(foreach d,$(obj-dirs), $(shell [ -d $(d) ] || mkdir -p $(d))) +endif + + +ifdef EXTRA_TARGETS +$(warning kbuild: $(obj)/Makefile - Usage of EXTRA_TARGETS is obsolete in 2.6. Please fix!) +endif + +ifdef build-targets +$(warning kbuild: $(obj)/Makefile - Usage of build-targets is obsolete in 2.6. Please fix!) +endif + +ifdef export-objs +$(warning kbuild: $(obj)/Makefile - Usage of export-objs is obsolete in 2.6. Please fix!) +endif + +ifdef O_TARGET +$(warning kbuild: $(obj)/Makefile - Usage of O_TARGET := $(O_TARGET) is obsolete in 2.6. Please fix!) +endif + +ifdef L_TARGET +$(error kbuild: $(obj)/Makefile - Use of L_TARGET is replaced by lib-y in 2.6. Please fix!) +endif + +ifdef list-multi +$(warning kbuild: $(obj)/Makefile - list-multi := $(list-multi) is obsolete in 2.6. Please fix!) +endif + +ifndef obj +$(warning kbuild: Makefile.build is included improperly) +endif + +# =========================================================================== + +ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),) +lib-target := $(obj)/lib.a +endif + +ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),) +builtin-target := $(obj)/built-in.o +endif + +# We keep a list of all modules in $(MODVERDIR) + +__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ +	 $(if $(KBUILD_MODULES),$(obj-m)) \ +	 $(subdir-ym) $(always) +	@: + +# Linus' kernel sanity checking tool +ifneq ($(KBUILD_CHECKSRC),0) +  ifeq ($(KBUILD_CHECKSRC),2) +    quiet_cmd_force_checksrc = CHECK   $< +          cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ; +  else +      quiet_cmd_checksrc     = CHECK   $< +            cmd_checksrc     = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ; +  endif +endif + + +# Compile C sources (.c) +# --------------------------------------------------------------------------- + +# Default is built-in, unless we know otherwise +modkern_cflags := $(CFLAGS_KERNEL) +quiet_modtag := $(empty)   $(empty) + +$(real-objs-m)        : modkern_cflags := $(CFLAGS_MODULE) +$(real-objs-m:.o=.i)  : modkern_cflags := $(CFLAGS_MODULE) +$(real-objs-m:.o=.s)  : modkern_cflags := $(CFLAGS_MODULE) +$(real-objs-m:.o=.lst): modkern_cflags := $(CFLAGS_MODULE) + +$(real-objs-m)        : quiet_modtag := [M] +$(real-objs-m:.o=.i)  : quiet_modtag := [M] +$(real-objs-m:.o=.s)  : quiet_modtag := [M] +$(real-objs-m:.o=.lst): quiet_modtag := [M] + +$(obj-m)              : quiet_modtag := [M] + +# Default for not multi-part modules +modname = $(*F) + +$(multi-objs-m)         : modname = $(modname-multi) +$(multi-objs-m:.o=.i)   : modname = $(modname-multi) +$(multi-objs-m:.o=.s)   : modname = $(modname-multi) +$(multi-objs-m:.o=.lst) : modname = $(modname-multi) +$(multi-objs-y)         : modname = $(modname-multi) +$(multi-objs-y:.o=.i)   : modname = $(modname-multi) +$(multi-objs-y:.o=.s)   : modname = $(modname-multi) +$(multi-objs-y:.o=.lst) : modname = $(modname-multi) + +quiet_cmd_cc_s_c = CC $(quiet_modtag)  $@ +cmd_cc_s_c       = $(CC) $(c_flags) -S -o $@ $<  + +%.s: %.c FORCE +	$(call if_changed_dep,cc_s_c) + +quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@ +cmd_cc_i_c       = $(CPP) $(c_flags)   -o $@ $< + +%.i: %.c FORCE +	$(call if_changed_dep,cc_i_c) + +# C (.c) files +# The C file is compiled and updated dependency information is generated. +# (See cmd_cc_o_c + relevant part of rule_cc_o_c) + +quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@ + +ifndef CONFIG_MODVERSIONS +cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< + +else +# When module versioning is enabled the following steps are executed: +# o compile a .tmp_<file>.o from <file>.c +# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does +#   not export symbols, we just rename .tmp_<file>.o to <file>.o and +#   are done. +# o otherwise, we calculate symbol versions using the good old +#   genksyms on the preprocessed source and postprocess them in a way +#   that they are usable as a linker script +# o generate <file>.o from .tmp_<file>.o using the linker to +#   replace the unresolved symbols __crc_exported_symbol with +#   the actual value of the checksum generated by genksyms + +cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< +cmd_modversions =							\ +	if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then	\ +		$(CPP) -D__GENKSYMS__ $(c_flags) $<			\ +		| $(GENKSYMS)						\ +		> $(@D)/.tmp_$(@F:.o=.ver);				\ +									\ +		$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) 		\ +			-T $(@D)/.tmp_$(@F:.o=.ver);			\ +		rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver);	\ +	else								\ +		mv $(@D)/.tmp_$(@F) $@;					\ +	fi; +endif + +define rule_cc_o_c +	$(if $($(quiet)cmd_checksrc),echo '  $($(quiet)cmd_checksrc)';)   \ +	$(cmd_checksrc)							  \ +	$(if $($(quiet)cmd_cc_o_c),echo '  $($(quiet)cmd_cc_o_c)';)	  \ +	$(cmd_cc_o_c);							  \ +	$(cmd_modversions)						  \ +	scripts/basic/fixdep $(depfile) $@ '$(cmd_cc_o_c)' > $(@D)/.$(@F).tmp;  \ +	rm -f $(depfile);						  \ +	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd +endef + +# Built-in and composite module parts + +%.o: %.c FORCE +	$(call cmd,force_checksrc) +	$(call if_changed_rule,cc_o_c) + +# Single-part modules are special since we need to mark them in $(MODVERDIR) + +$(single-used-m): %.o: %.c FORCE +	$(call cmd,force_checksrc) +	$(call if_changed_rule,cc_o_c) +	@{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod) + +quiet_cmd_cc_lst_c = MKLST   $@ +      cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ +		     $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \ +				     System.map $(OBJDUMP) > $@ + +%.lst: %.c FORCE +	$(call if_changed_dep,cc_lst_c) + +# Compile assembler sources (.S) +# --------------------------------------------------------------------------- + +modkern_aflags := $(AFLAGS_KERNEL) + +$(real-objs-m)      : modkern_aflags := $(AFLAGS_MODULE) +$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE) + +quiet_cmd_as_s_S = CPP $(quiet_modtag) $@ +cmd_as_s_S       = $(CPP) $(a_flags)   -o $@ $<  + +%.s: %.S FORCE +	$(call if_changed_dep,as_s_S) + +quiet_cmd_as_o_S = AS $(quiet_modtag)  $@ +cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $< + +%.o: %.S FORCE +	$(call if_changed_dep,as_o_S) + +targets += $(real-objs-y) $(real-objs-m) $(lib-y) +targets += $(extra-y) $(MAKECMDGOALS) $(always) + +# Linker scripts preprocessor (.lds.S -> .lds) +# --------------------------------------------------------------------------- +quiet_cmd_cpp_lds_S = LDS     $@ +      cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $< + +%.lds: %.lds.S FORCE +	$(call if_changed_dep,cpp_lds_S) + +# Build the compiled-in targets +# --------------------------------------------------------------------------- + +# To build objects in subdirs, we need to descend into the directories +$(sort $(subdir-obj-y)): $(subdir-ym) ; + +# +# Rule to compile a set of .o files into one .o file +# +ifdef builtin-target +quiet_cmd_link_o_target = LD      $@ +# If the list of objects to link is empty, just create an empty built-in.o +cmd_link_o_target = $(if $(strip $(obj-y)),\ +		      $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\ +		      rm -f $@; $(AR) rcs $@) + +$(builtin-target): $(obj-y) FORCE +	$(call if_changed,link_o_target) + +targets += $(builtin-target) +endif # builtin-target + +# +# Rule to compile a set of .o files into one .a file +# +ifdef lib-target +quiet_cmd_link_l_target = AR      $@ +cmd_link_l_target = rm -f $@; $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-y) + +$(lib-target): $(lib-y) FORCE +	$(call if_changed,link_l_target) + +targets += $(lib-target) +endif + +# +# Rule to link composite objects +# +#  Composite objects are specified in kbuild makefile as follows: +#    <composite-object>-objs := <list of .o files> +#  or +#    <composite-object>-y    := <list of .o files> +link_multi_deps =                     \ +$(filter $(addprefix $(obj)/,         \ +$($(subst $(obj)/,,$(@:.o=-objs)))    \ +$($(subst $(obj)/,,$(@:.o=-y)))), $^) +  +quiet_cmd_link_multi-y = LD      $@ +cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) + +quiet_cmd_link_multi-m = LD [M]  $@ +cmd_link_multi-m = $(LD) $(ld_flags) $(LDFLAGS_MODULE) -o $@ $(link_multi_deps) + +# We would rather have a list of rules like +# 	foo.o: $(foo-objs) +# but that's not so easy, so we rather make all composite objects depend +# on the set of all their parts +$(multi-used-y) : %.o: $(multi-objs-y) FORCE +	$(call if_changed,link_multi-y) + +$(multi-used-m) : %.o: $(multi-objs-m) FORCE +	$(call if_changed,link_multi-m) +	@{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod) + +targets += $(multi-used-y) $(multi-used-m) + + +# Descending +# --------------------------------------------------------------------------- + +.PHONY: $(subdir-ym) +$(subdir-ym): +	$(Q)$(MAKE) $(build)=$@ + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +.PHONY: FORCE + +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) +  include $(cmd_files) +endif diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean new file mode 100644 index 000000000000..ff3e87dbf387 --- /dev/null +++ b/scripts/Makefile.clean @@ -0,0 +1,94 @@ +# ========================================================================== +# Cleaning up +# ========================================================================== + +src := $(obj) + +.PHONY: __clean +__clean: + +include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile) + +# Figure out what we need to build from the various variables +# ========================================================================== + +__subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y))) +subdir-y	+= $(__subdir-y) +__subdir-m	:= $(patsubst %/,%,$(filter %/, $(obj-m))) +subdir-m	+= $(__subdir-m) +__subdir-n	:= $(patsubst %/,%,$(filter %/, $(obj-n))) +subdir-n	+= $(__subdir-n) +__subdir-	:= $(patsubst %/,%,$(filter %/, $(obj-))) +subdir-		+= $(__subdir-) + +# Subdirectories we need to descend into + +subdir-ym	:= $(sort $(subdir-y) $(subdir-m)) +subdir-ymn      := $(sort $(subdir-ym) $(subdir-n) $(subdir-)) + +# Add subdir path + +subdir-ymn	:= $(addprefix $(obj)/,$(subdir-ymn)) + +# build a list of files to remove, usually releative to the current +# directory + +__clean-files	:= $(extra-y) $(EXTRA_TARGETS) $(always) \ +		   $(targets) $(clean-files)             \ +		   $(host-progs)                         \ +		   $(hostprogs-y) $(hostprogs-m) $(hostprogs-) + +# as clean-files is given relative to the current directory, this adds +# a $(obj) prefix, except for absolute paths + +__clean-files   := $(wildcard                                               \ +                   $(addprefix $(obj)/, $(filter-out /%, $(__clean-files))) \ +		   $(filter /%, $(__clean-files))) + +# as clean-dirs is given relative to the current directory, this adds +# a $(obj) prefix, except for absolute paths + +__clean-dirs    := $(wildcard                                               \ +                   $(addprefix $(obj)/, $(filter-out /%, $(clean-dirs)))    \ +		   $(filter /%, $(clean-dirs))) + +# ========================================================================== + +quiet_cmd_clean    = CLEAN   $(obj) +      cmd_clean    = rm -f $(__clean-files) +quiet_cmd_cleandir = CLEAN   $(__clean-dirs) +      cmd_cleandir = rm -rf $(__clean-dirs) + + +__clean: $(subdir-ymn) +ifneq ($(strip $(__clean-files)),) +	+$(call cmd,clean) +endif +ifneq ($(strip $(__clean-dirs)),) +	+$(call cmd,cleandir) +endif +ifneq ($(strip $(clean-rule)),) +	+$(clean-rule) +endif +	@: + + +# =========================================================================== +# Generic stuff +# =========================================================================== + +# Descending +# --------------------------------------------------------------------------- + +.PHONY: $(subdir-ymn) +$(subdir-ymn): +	$(Q)$(MAKE) $(clean)=$@ + +# If quiet is set, only print short version of command + +cmd = @$(if $($(quiet)cmd_$(1)),echo '  $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) + +# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir +# Usage: +# $(Q)$(MAKE) $(clean)=dir +clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj diff --git a/scripts/Makefile.host b/scripts/Makefile.host new file mode 100644 index 000000000000..2821a2b83bbb --- /dev/null +++ b/scripts/Makefile.host @@ -0,0 +1,155 @@ +# ========================================================================== +# Building binaries on the host system +# Binaries are used during the compilation of the kernel, for example +# to preprocess a data file. +# +# Both C and C++ is supported, but preferred language is C for such utilities. +# +# Samle syntax (see Documentation/kbuild/makefile.txt for reference) +# hostprogs-y := bin2hex +# Will compile bin2hex.c and create an executable named bin2hex +# +# hostprogs-y    := lxdialog +# lxdialog-objs := checklist.o lxdialog.o +# Will compile lxdialog.c and checklist.c, and then link the executable +# lxdialog, based on checklist.o and lxdialog.o +# +# hostprogs-y      := qconf +# qconf-cxxobjs   := qconf.o +# qconf-objs      := menu.o +# Will compile qconf as a C++ program, and menu as a C program. +# They are linked as C++ code to the executable qconf + +# hostprogs-y := conf +# conf-objs  := conf.o libkconfig.so +# libkconfig-objs := expr.o type.o +# Will create a shared library named libkconfig.so that consist of +# expr.o and type.o (they are both compiled as C code and the object file +# are made as position independent code). +# conf.c is compiled as a c program, and conf.o is linked together with +# libkconfig.so as the executable conf. +# Note: Shared libraries consisting of C++ files are not supported + +__hostprogs := $(sort $(hostprogs-y)$(hostprogs-m)) + +# hostprogs-y := tools/build may have been specified. Retreive directory +obj-dirs += $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) +obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs)))) + + +# C code +# Executables compiled from a single .c file +host-csingle	:= $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m))) + +# C executables linked based on several .o files +host-cmulti	:= $(foreach m,$(__hostprogs),\ +		   $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m)))) + +# Object (.o) files compiled from .c files +host-cobjs	:= $(sort $(foreach m,$(__hostprogs),$($(m)-objs))) + +# C++ code +# C++ executables compiled from at least on .cc file +# and zero or more .c files +host-cxxmulti	:= $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) + +# C++ Object (.o) files compiled from .cc files +host-cxxobjs	:= $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) + +# Shared libaries (only .c supported) +# Shared libraries (.so) - all .so files referenced in "xxx-objs" +host-cshlib	:= $(sort $(filter %.so, $(host-cobjs))) +# Remove .so files from "xxx-objs" +host-cobjs	:= $(filter-out %.so,$(host-cobjs)) + +#Object (.o) files used by the shared libaries +host-cshobjs	:= $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs)))) + +__hostprogs     := $(addprefix $(obj)/,$(__hostprogs)) +host-csingle	:= $(addprefix $(obj)/,$(host-csingle)) +host-cmulti	:= $(addprefix $(obj)/,$(host-cmulti)) +host-cobjs	:= $(addprefix $(obj)/,$(host-cobjs)) +host-cxxmulti	:= $(addprefix $(obj)/,$(host-cxxmulti)) +host-cxxobjs	:= $(addprefix $(obj)/,$(host-cxxobjs)) +host-cshlib	:= $(addprefix $(obj)/,$(host-cshlib)) +host-cshobjs	:= $(addprefix $(obj)/,$(host-cshobjs)) +obj-dirs        := $(addprefix $(obj)/,$(obj-dirs)) + +##### +# Handle options to gcc. Support building with separate output directory + +_hostc_flags   = $(HOSTCFLAGS)   $(HOST_EXTRACFLAGS)   $(HOSTCFLAGS_$(*F).o) +_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o) + +ifeq ($(KBUILD_SRC),) +__hostc_flags	= $(_hostc_flags) +__hostcxx_flags	= $(_hostcxx_flags) +else +__hostc_flags	= -I$(obj) $(call flags,_hostc_flags) +__hostcxx_flags	= -I$(obj) $(call flags,_hostcxx_flags) +endif + +hostc_flags    = -Wp,-MD,$(depfile) $(__hostc_flags) +hostcxx_flags  = -Wp,-MD,$(depfile) $(__hostcxx_flags) + +##### +# Compile programs on the host + +# Create executable from a single .c file +# host-csingle -> Executable +quiet_cmd_host-csingle 	= HOSTCC  $@ +      cmd_host-csingle	= $(HOSTCC) $(hostc_flags) $(HOST_LOADLIBES) -o $@ $< +$(host-csingle): %: %.c FORCE +	$(call if_changed_dep,host-csingle) + +# Link an executable based on list of .o files, all plain c +# host-cmulti -> executable +quiet_cmd_host-cmulti	= HOSTLD  $@ +      cmd_host-cmulti	= $(HOSTCC) $(HOSTLDFLAGS) -o $@ \ +			  $(addprefix $(obj)/,$($(@F)-objs)) \ +			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-cmulti): %: $(host-cobjs) $(host-cshlib) FORCE +	$(call if_changed,host-cmulti) + +# Create .o file from a single .c file +# host-cobjs -> .o +quiet_cmd_host-cobjs	= HOSTCC  $@ +      cmd_host-cobjs	= $(HOSTCC) $(hostc_flags) -c -o $@ $< +$(host-cobjs): %.o: %.c FORCE +	$(call if_changed_dep,host-cobjs) + +# Link an executable based on list of .o files, a mixture of .c and .cc +# host-cxxmulti -> executable +quiet_cmd_host-cxxmulti	= HOSTLD  $@ +      cmd_host-cxxmulti	= $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \ +			  $(foreach o,objs cxxobjs,\ +			  $(addprefix $(obj)/,$($(@F)-$(o)))) \ +			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-cxxmulti): %: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE +	$(call if_changed,host-cxxmulti) + +# Create .o file from a single .cc (C++) file +quiet_cmd_host-cxxobjs	= HOSTCXX $@ +      cmd_host-cxxobjs	= $(HOSTCXX) $(hostcxx_flags) -c -o $@ $< +$(host-cxxobjs): %.o: %.cc FORCE +	$(call if_changed_dep,host-cxxobjs) + +# Compile .c file, create position independent .o file +# host-cshobjs -> .o +quiet_cmd_host-cshobjs	= HOSTCC  -fPIC $@ +      cmd_host-cshobjs	= $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $< +$(host-cshobjs): %.o: %.c FORCE +	$(call if_changed_dep,host-cshobjs) + +# Link a shared library, based on position independent .o files +# *.o -> .so shared library (host-cshlib) +quiet_cmd_host-cshlib	= HOSTLLD -shared $@ +      cmd_host-cshlib	= $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \ +			  $(addprefix $(obj)/,$($(@F:.so=-objs))) \ +			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-cshlib): %: $(host-cshobjs) FORCE +	$(call if_changed,host-cshlib) + +targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\ +	   $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs)  + diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib new file mode 100644 index 000000000000..7cf75cc4f849 --- /dev/null +++ b/scripts/Makefile.lib @@ -0,0 +1,267 @@ +# =========================================================================== +# kbuild: Generic definitions +# =========================================================================== + +# Standard vars + +comma   := , +empty   := +space   := $(empty) $(empty) + +# Backward compatibility - to be removed... +extra-y	+= $(EXTRA_TARGETS) +# Figure out what we need to build from the various variables +# =========================================================================== + +# When an object is listed to be built compiled-in and modular, +# only build the compiled-in version + +obj-m := $(filter-out $(obj-y),$(obj-m)) + +# Libraries are always collected in one lib file. +# Filter out objects already built-in + +lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m))) + + +# Handle objects in subdirs +# --------------------------------------------------------------------------- +# o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o +#   and add the directory to the list of dirs to descend into: $(subdir-y) +# o if we encounter foo/ in $(obj-m), remove it from $(obj-m)  +#   and add the directory to the list of dirs to descend into: $(subdir-m) + +__subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y))) +subdir-y	+= $(__subdir-y) +__subdir-m	:= $(patsubst %/,%,$(filter %/, $(obj-m))) +subdir-m	+= $(__subdir-m) +obj-y		:= $(patsubst %/, %/built-in.o, $(obj-y)) +obj-m		:= $(filter-out %/, $(obj-m)) + +# Subdirectories we need to descend into + +subdir-ym	:= $(sort $(subdir-y) $(subdir-m)) + +# if $(foo-objs) exists, foo.o is a composite object  +multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) +multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) +multi-used   := $(multi-used-y) $(multi-used-m) +single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m))) + +# Build list of the parts of our composite objects, our composite +# objects depend on those (obviously) +multi-objs-y := $(foreach m, $(multi-used-y), $($(m:.o=-objs)) $($(m:.o=-y))) +multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y))) +multi-objs   := $(multi-objs-y) $(multi-objs-m) + +# $(subdir-obj-y) is the list of objects in $(obj-y) which do not live +# in the local directory +subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o))) + +# $(obj-dirs) is a list of directories that contain object files +obj-dirs := $(dir $(multi-objs) $(subdir-obj-y)) + +# Replace multi-part objects by their individual parts, look at local dir only +real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y) +real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) + +# Add subdir path + +extra-y		:= $(addprefix $(obj)/,$(extra-y)) +always		:= $(addprefix $(obj)/,$(always)) +targets		:= $(addprefix $(obj)/,$(targets)) +obj-y		:= $(addprefix $(obj)/,$(obj-y)) +obj-m		:= $(addprefix $(obj)/,$(obj-m)) +lib-y		:= $(addprefix $(obj)/,$(lib-y)) +subdir-obj-y	:= $(addprefix $(obj)/,$(subdir-obj-y)) +real-objs-y	:= $(addprefix $(obj)/,$(real-objs-y)) +real-objs-m	:= $(addprefix $(obj)/,$(real-objs-m)) +single-used-m	:= $(addprefix $(obj)/,$(single-used-m)) +multi-used-y	:= $(addprefix $(obj)/,$(multi-used-y)) +multi-used-m	:= $(addprefix $(obj)/,$(multi-used-m)) +multi-objs-y	:= $(addprefix $(obj)/,$(multi-objs-y)) +multi-objs-m	:= $(addprefix $(obj)/,$(multi-objs-m)) +subdir-ym	:= $(addprefix $(obj)/,$(subdir-ym)) +obj-dirs	:= $(addprefix $(obj)/,$(obj-dirs)) + +# The temporary file to save gcc -MD generated dependencies must not +# contain a comma +depfile = $(subst $(comma),_,$(@D)/.$(@F).d) + +# These flags are needed for modversions and compiling, so we define them here +# already +# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will  +# end up in (or would, if it gets compiled in) +# Note: It's possible that one object gets potentially linked into more +#       than one module. In that case KBUILD_MODNAME will be set to foo_bar, +#       where foo and bar are the name of the modules. +basename_flags = -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) +modname_flags  = $(if $(filter 1,$(words $(modname))),-DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname)))) + +_c_flags       = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) +_a_flags       = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o) +_cpp_flags     = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F)) + +# If building the kernel in a separate objtree expand all occurrences +# of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/'). + +ifeq ($(KBUILD_SRC),) +__c_flags	= $(_c_flags) +__a_flags	= $(_a_flags) +__cpp_flags     = $(_cpp_flags) +else + +# Prefix -I with $(srctree) if it is not an absolute path +addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1) +# Find all -I options and call addtree +flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o))) + +# -I$(obj) locates generated .h files +# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files +#   and locates generated .h files +# FIXME: Replace both with specific CFLAGS* statements in the makefiles +__c_flags	= $(call addtree,-I$(obj)) $(call flags,_c_flags) +__a_flags	=                          $(call flags,_a_flags) +__cpp_flags     =                          $(call flags,_cpp_flags) +endif + +c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \ +		 $(__c_flags) $(modkern_cflags) \ +		 $(basename_flags) $(modname_flags) + +a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \ +		 $(__a_flags) $(modkern_aflags) + +cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags) + +ld_flags       = $(LDFLAGS) $(EXTRA_LDFLAGS) + +# Finds the multi-part object the current object will be linked into +modname-multi = $(sort $(foreach m,$(multi-used),\ +		$(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=)))) + +# Shipped files +# =========================================================================== + +quiet_cmd_shipped = SHIPPED $@ +cmd_shipped = cat $< > $@ + +$(obj)/%:: $(src)/%_shipped +	$(call cmd,shipped) + +# Commands useful for building a boot image +# =========================================================================== +#  +#	Use as following: +# +#	target: source(s) FORCE +#		$(if_changed,ld/objcopy/gzip) +# +#	and add target to EXTRA_TARGETS so that we know we have to +#	read in the saved command line + +# Linking +# --------------------------------------------------------------------------- + +quiet_cmd_ld = LD      $@ +cmd_ld = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) \ +	       $(filter-out FORCE,$^) -o $@  + +# Objcopy +# --------------------------------------------------------------------------- + +quiet_cmd_objcopy = OBJCOPY $@ +cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@ + +# Gzip +# --------------------------------------------------------------------------- + +quiet_cmd_gzip = GZIP    $@ +cmd_gzip = gzip -f -9 < $< > $@ + +# =========================================================================== +# Generic stuff +# =========================================================================== + +ifneq ($(KBUILD_NOCMDDEP),1) +# Check if both arguments has same arguments. Result in empty string if equal +# User may override this check using make KBUILD_NOCMDDEP=1 +arg-check = $(strip $(filter-out $(1), $(2)) $(filter-out $(2), $(1)) ) + +endif + +# echo command. Short version is $(quiet) equals quiet, otherwise full command +echo-cmd = $(if $($(quiet)cmd_$(1)), \ +	echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) + +# function to only execute the passed command if necessary +# >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file +# note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars +#  +if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \ +	@set -e; \ +	$(echo-cmd) \ +	$(cmd_$(1)); \ +	echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd) + + +# execute the command and also postprocess generated .d dependencies +# file + +if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\ +	$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),                  \ +	@set -e; \ +	$(echo-cmd) \ +	$(cmd_$(1)); \ +	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \ +	rm -f $(depfile); \ +	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd) + +# Usage: $(call if_changed_rule,foo) +# will check if $(cmd_foo) changed, or any of the prequisites changed, +# and if so will execute $(rule_foo) + +if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\ +			@set -e; \ +			$(rule_$(1))) + +# If quiet is set, only print short version of command + +cmd = @$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))' &&) $(cmd_$(1)) + +#	$(call descend,<dir>,<target>) +#	Recursively call a sub-make in <dir> with target <target>  +# Usage is deprecated, because make do not see this as an invocation of make. +descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2) + +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= +# Usage: +# $(Q)$(MAKE) $(build)=dir +build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj + +# filechk is used to check if the content of a generated file is updated. +# Sample usage: +# define filechk_sample +#	echo $KERNELRELEASE +# endef +# version.h : Makefile +#	$(call filechk,sample) +# The rule defined shall write to stdout the content of the new file. +# The existing file will be compared with the new one. +# - If no file exist it is created +# - If the content differ the new file is used +# - If they are equal no change, and no timestamp update + +define filechk +	$(Q)set -e;				\ +	echo '  CHK     $@';			\ +	mkdir -p $(dir $@);			\ +	$(filechk_$(1)) $(2) > $@.tmp;		\ +	if [ -r $@ ] && cmp -s $@ $@.tmp; then	\ +		rm -f $@.tmp;			\ +	else					\ +		echo '  UPD     $@';		\ +		mv -f $@.tmp $@;		\ +	fi +endef + diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst new file mode 100644 index 000000000000..85d6494e3c24 --- /dev/null +++ b/scripts/Makefile.modinst @@ -0,0 +1,29 @@ +# ========================================================================== +# Installing modules +# ========================================================================== + +.PHONY: __modinst +__modinst: + +include scripts/Makefile.lib + +# + +__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) +modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) + +.PHONY: $(modules) +__modinst: $(modules) +	@: + +quiet_cmd_modules_install = INSTALL $@ +      cmd_modules_install = mkdir -p $(2); cp $@ $(2) + +# Modules built outside the kernel source tree go into extra by default +INSTALL_MOD_DIR ?= extra +ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(KBUILD_EXTMOD),,$(@D)) + +modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) + +$(modules): +	$(call cmd,modules_install,$(MODLIB)/$(modinst_dir)) diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost new file mode 100644 index 000000000000..94b550e21be8 --- /dev/null +++ b/scripts/Makefile.modpost @@ -0,0 +1,110 @@ +# =========================================================================== +# Module versions +# =========================================================================== +# +# Stage one of module building created the following: +# a) The individual .o files used for the module +# b) A <module>.o file wich is the .o files above linked together +# c) A <module>.mod file in $(MODVERDIR)/, listing the name of the +#    the preliminary <module>.o file, plus all .o files + +# Stage 2 is handled by this file and does the following +# 1) Find all modules from the files listed in $(MODVERDIR)/ +# 2) modpost is then used to +# 3)  create one <module>.mod.c file pr. module +# 4)  create one Module.symvers file with CRC for all exported symbols +# 5) compile all <module>.mod.c files +# 6) final link of the module to a <module.ko> file + +# Step 3 is used to place certain information in the module's ELF +# section, including information such as: +#   Version magic (see include/vermagic.h for full details) +#     - Kernel release +#     - SMP is CONFIG_SMP +#     - PREEMPT is CONFIG_PREEMPT +#     - GCC Version +#   Module info +#     - Module version (MODULE_VERSION) +#     - Module alias'es (MODULE_ALIAS) +#     - Module license (MODULE_LICENSE) +#     - See include/linux/module.h for more details + +# Step 4 is solely used to allow module versioning in external modules, +# where the CRC of each module is retreived from the Module.symers file. + +.PHONY: _modpost +_modpost: __modpost + +include .config +include scripts/Makefile.lib + +symverfile := $(objtree)/Module.symvers + +# Step 1), find all modules listed in $(MODVERDIR)/ +__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) +modules   := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o))) + +_modpost: $(modules) + + +# Step 2), invoke modpost +#  Includes step 3,4 +quiet_cmd_modpost = MODPOST +      cmd_modpost = scripts/mod/modpost            \ +        $(if $(CONFIG_MODVERSIONS),-m)             \ +	$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,)  \ +	$(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \ +	$(filter-out FORCE,$^) + +.PHONY: __modpost +__modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE +	$(call cmd,modpost) + +# Declare generated files as targets for modpost +$(symverfile):         __modpost ; +$(modules:.ko=.mod.c): __modpost ; + + +# Step 5), compile all *.mod.c files + +# modname is set to make c_flags define KBUILD_MODNAME +modname = $(*F) + +quiet_cmd_cc_o_c = CC      $@ +      cmd_cc_o_c = $(CC) $(c_flags) $(CFLAGS_MODULE)	\ +		   -c -o $@ $< + +$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE +	$(call if_changed_dep,cc_o_c) + +targets += $(modules:.ko=.mod.o) + +# Step 6), final link of the modules +quiet_cmd_ld_ko_o = LD [M]  $@ +      cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ 		\ +			  $(filter-out FORCE,$^) + +$(modules): %.ko :%.o %.mod.o FORCE +	$(call if_changed,ld_ko_o) + +targets += $(modules) + + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +.PHONY: FORCE + +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) +  include $(cmd_files) +endif diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile new file mode 100644 index 000000000000..f22e94c3a2d1 --- /dev/null +++ b/scripts/basic/Makefile @@ -0,0 +1,18 @@ +### +# Makefile.basic list the most basic programs used during the build process. +# The programs listed herein is what is needed to do the basic stuff, +# such as splitting .config and fix dependency file. +# This initial step is needed to avoid files to be recompiled +# when kernel configuration changes (which is what happens when +# .config is included by main Makefile. +# --------------------------------------------------------------------------- +# fixdep: 	 Used to generate dependency information during build process +# split-include: Divide all config symbols up in a number of files in +#                include/config/... +# docproc:	 Used in Documentation/docbook + +hostprogs-y	:= fixdep split-include docproc +always		:= $(hostprogs-y) + +# fixdep is needed to compile other host programs +$(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 000000000000..8ca7ecdb68fb --- /dev/null +++ b/scripts/basic/docproc.c @@ -0,0 +1,398 @@ +/* + *	docproc is a simple preprocessor for the template files + *      used as placeholders for the kernel internal documentation. + *	docproc is used for documentation-frontend and + *      dependency-generator. + *	The two usages have in common that they require + *	some knowledge of the .tmpl syntax, therefore they + *	are kept together. + * + *	documentation-frontend + *		Scans the template file and call kernel-doc for + *		all occurrences of ![EIF]file + *		Beforehand each referenced file are scanned for + *		any exported sympols "EXPORT_SYMBOL()" statements. + *		This is used to create proper -function and + *		-nofunction arguments in calls to kernel-doc. + *		Usage: docproc doc file.tmpl + * + *	dependency-generator: + *		Scans the template file and list all files + *		referenced in a format recognized by make. + *		Usage:	docproc depend file.tmpl + *		Writes dependency information to stdout + *		in the following format: + *		file.tmpl src.c	src2.c + *		The filenames are obtained from the following constructs: + *		!Efilename + *		!Ifilename + *		!Dfilename + *		!Ffilename + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <limits.h> +#include <sys/types.h> +#include <sys/wait.h> + +/* exitstatus is used to keep track of any failing calls to kernel-doc, + * but execution continues. */ +int exitstatus = 0; + +typedef void DFL(char *); +DFL *defaultline; + +typedef void FILEONLY(char * file); +FILEONLY *internalfunctions; +FILEONLY *externalfunctions; +FILEONLY *symbolsonly; + +typedef void FILELINE(char * file, signed char * line); +FILELINE * singlefunctions; +FILELINE * entity_system; + +#define MAXLINESZ     2048 +#define MAXFILES      250 +#define KERNELDOCPATH "scripts/" +#define KERNELDOC     "kernel-doc" +#define DOCBOOK       "-docbook" +#define FUNCTION      "-function" +#define NOFUNCTION    "-nofunction" + +void usage (void) +{ +	fprintf(stderr, "Usage: docproc {doc|depend} file\n"); +	fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n"); +	fprintf(stderr, "doc: frontend when generating kernel documentation\n"); +	fprintf(stderr, "depend: generate list of files referenced within file\n"); +} + +/* + * Execute kernel-doc with parameters givin in svec + */ +void exec_kernel_doc(char **svec) +{ +	pid_t pid; +	int ret; +	char real_filename[PATH_MAX + 1]; +	/* Make sure output generated so far are flushed */ +	fflush(stdout); +	switch(pid=fork()) { +		case -1: +			perror("fork"); +			exit(1); +		case  0: +			memset(real_filename, 0, sizeof(real_filename)); +			strncat(real_filename, getenv("SRCTREE"), PATH_MAX); +			strncat(real_filename, KERNELDOCPATH KERNELDOC, +					PATH_MAX - strlen(real_filename)); +			execvp(real_filename, svec); +			fprintf(stderr, "exec "); +			perror(real_filename); +			exit(1); +		default: +			waitpid(pid, &ret ,0); +	} +	if (WIFEXITED(ret)) +		exitstatus |= WEXITSTATUS(ret); +	else +		exitstatus = 0xff; +} + +/* Types used to create list of all exported symbols in a number of files */ +struct symbols +{ +	char *name; +}; + +struct symfile +{ +	char *filename; +	struct symbols *symbollist; +	int symbolcnt; +}; + +struct symfile symfilelist[MAXFILES]; +int symfilecnt = 0; + +void add_new_symbol(struct symfile *sym, char * symname) +{ +	sym->symbollist = +          realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *)); +	sym->symbollist[sym->symbolcnt++].name = strdup(symname); +} + +/* Add a filename to the list */ +struct symfile * add_new_file(char * filename) +{ +	symfilelist[symfilecnt++].filename = strdup(filename); +	return &symfilelist[symfilecnt - 1]; +} +/* Check if file already are present in the list */ +struct symfile * filename_exist(char * filename) +{ +	int i; +	for (i=0; i < symfilecnt; i++) +		if (strcmp(symfilelist[i].filename, filename) == 0) +			return &symfilelist[i]; +	return NULL; +} + +/* + * List all files referenced within the template file. + * Files are separated by tabs. + */ +void adddep(char * file)		   { printf("\t%s", file); } +void adddep2(char * file, signed char * line)     { line = line; adddep(file); } +void noaction(char * line)		   { line = line; } +void noaction2(char * file, signed char * line)   { file = file; line = line; } + +/* Echo the line without further action */ +void printline(char * line)               { printf("%s", line); } + +/* + * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL + * in filename. + * All symbols located are stored in symfilelist. + */ +void find_export_symbols(char * filename) +{ +	FILE * fp; +	struct symfile *sym; +	char line[MAXLINESZ]; +	if (filename_exist(filename) == NULL) { +		char real_filename[PATH_MAX + 1]; +		memset(real_filename, 0, sizeof(real_filename)); +		strncat(real_filename, getenv("SRCTREE"), PATH_MAX); +		strncat(real_filename, filename, +				PATH_MAX - strlen(real_filename)); +		sym = add_new_file(filename); +		fp = fopen(real_filename, "r"); +		if (fp == NULL) +		{ +			fprintf(stderr, "docproc: "); +			perror(real_filename); +		} +		while(fgets(line, MAXLINESZ, fp)) { +			signed char *p; +			signed char *e; +			if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) || +                            ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) { +				/* Skip EXPORT_SYMBOL{_GPL} */ +				while (isalnum(*p) || *p == '_') +					p++; +				/* Remove paranteses and additional ws */ +				while (isspace(*p)) +					p++; +				if (*p != '(') +					continue; /* Syntax error? */ +				else +					p++; +				while (isspace(*p)) +					p++; +				e = p; +				while (isalnum(*e) || *e == '_') +					e++; +				*e = '\0'; +				add_new_symbol(sym, p); +			} +		} +		fclose(fp); +	} +} + +/* + * Document all external or internal functions in a file. + * Call kernel-doc with following parameters: + * kernel-doc -docbook -nofunction function_name1 filename + * function names are obtained from all the the src files + * by find_export_symbols. + * intfunc uses -nofunction + * extfunc uses -function + */ +void docfunctions(char * filename, char * type) +{ +	int i,j; +	int symcnt = 0; +	int idx = 0; +	char **vec; + +	for (i=0; i <= symfilecnt; i++) +		symcnt += symfilelist[i].symbolcnt; +	vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*)); +	if (vec == NULL) { +		perror("docproc: "); +		exit(1); +	} +	vec[idx++] = KERNELDOC; +	vec[idx++] = DOCBOOK; +	for (i=0; i < symfilecnt; i++) { +		struct symfile * sym = &symfilelist[i]; +		for (j=0; j < sym->symbolcnt; j++) { +			vec[idx++]     = type; +			vec[idx++] = sym->symbollist[j].name; +		} +	} +	vec[idx++]     = filename; +	vec[idx] = NULL; +	printf("<!-- %s -->\n", filename); +	exec_kernel_doc(vec); +	fflush(stdout); +	free(vec); +} +void intfunc(char * filename) {	docfunctions(filename, NOFUNCTION); } +void extfunc(char * filename) { docfunctions(filename, FUNCTION);   } + +/* + * Document spåecific function(s) in a file. + * Call kernel-doc with the following parameters: + * kernel-doc -docbook -function function1 [-function function2] + */ +void singfunc(char * filename, signed char * line) +{ +	char *vec[200]; /* Enough for specific functions */ +        int i, idx = 0; +        int startofsym = 1; +	vec[idx++] = KERNELDOC; +	vec[idx++] = DOCBOOK; + +        /* Split line up in individual parameters preceeded by FUNCTION */ +        for (i=0; line[i]; i++) { +                if (isspace(line[i])) { +                        line[i] = '\0'; +                        startofsym = 1; +                        continue; +                } +                if (startofsym) { +                        startofsym = 0; +                        vec[idx++] = FUNCTION; +                        vec[idx++] = &line[i]; +                } +        } +	vec[idx++] = filename; +	vec[idx] = NULL; +	exec_kernel_doc(vec); +} + +/* + * Parse file, calling action specific functions for: + * 1) Lines containing !E + * 2) Lines containing !I + * 3) Lines containing !D + * 4) Lines containing !F + * 5) Default lines - lines not matching the above + */ +void parse_file(FILE *infile) +{ +	char line[MAXLINESZ]; +	signed char * s; +	while(fgets(line, MAXLINESZ, infile)) { +		if (line[0] == '!') { +			s = line + 2; +			switch (line[1]) { +				case 'E': +					while (*s && !isspace(*s)) s++; +					*s = '\0'; +					externalfunctions(line+2); +					break; +				case 'I': +					while (*s && !isspace(*s)) s++; +					*s = '\0'; +					internalfunctions(line+2); +					break; +				case 'D': +					while (*s && !isspace(*s)) s++; +                                        *s = '\0'; +                                        symbolsonly(line+2); +                                        break; +				case 'F': +					/* filename */ +					while (*s && !isspace(*s)) s++; +					*s++ = '\0'; +                                        /* function names */ +					while (isspace(*s)) +						s++; +					singlefunctions(line +2, s); +					break; +				default: +					defaultline(line); +			} +		} +		else { +			defaultline(line); +		} +	} +	fflush(stdout); +} + + +int main(int argc, char *argv[]) +{ +	FILE * infile; +	if (argc != 3) { +		usage(); +		exit(1); +	} +	/* Open file, exit on error */ +	infile = fopen(argv[2], "r"); +        if (infile == NULL) { +                fprintf(stderr, "docproc: "); +                perror(argv[2]); +                exit(2); +        } + +	if (strcmp("doc", argv[1]) == 0) +	{ +		/* Need to do this in two passes. +		 * First pass is used to collect all symbols exported +		 * in the various files. +		 * Second pass generate the documentation. +		 * This is required because function are declared +		 * and exported in different files :-(( +		 */ +		/* Collect symbols */ +		defaultline       = noaction; +		internalfunctions = find_export_symbols; +		externalfunctions = find_export_symbols; +		symbolsonly       = find_export_symbols; +		singlefunctions   = noaction2; +		parse_file(infile); + +		/* Rewind to start from beginning of file again */ +		fseek(infile, 0, SEEK_SET); +		defaultline       = printline; +		internalfunctions = intfunc; +		externalfunctions = extfunc; +		symbolsonly       = printline; +		singlefunctions   = singfunc; + +		parse_file(infile); +	} +	else if (strcmp("depend", argv[1]) == 0) +	{ +		/* Create first part of dependency chain +		 * file.tmpl */ +		printf("%s\t", argv[2]); +		defaultline       = noaction; +		internalfunctions = adddep; +		externalfunctions = adddep; +		symbolsonly       = adddep; +		singlefunctions   = adddep2; +		parse_file(infile); +		printf("\n"); +	} +	else +	{ +		fprintf(stderr, "Unknown option: %s\n", argv[1]); +		exit(1); +	} +	fclose(infile); +	fflush(stdout); +	return exitstatus; +} + diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c new file mode 100644 index 000000000000..7f42c5d8a5a2 --- /dev/null +++ b/scripts/basic/fixdep.c @@ -0,0 +1,390 @@ +/* + * "Optimize" a list of dependencies as spit out by gcc -MD + * for the kernel build + * =========================================================================== + * + * Author       Kai Germaschewski + * Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de> + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * + * Introduction: + * + * gcc produces a very nice and correct list of dependencies which + * tells make when to remake a file. + * + * To use this list as-is however has the drawback that virtually + * every file in the kernel includes <linux/config.h> which then again + * includes <linux/autoconf.h> + * + * If the user re-runs make *config, linux/autoconf.h will be + * regenerated.  make notices that and will rebuild every file which + * includes autoconf.h, i.e. basically all files. This is extremely + * annoying if the user just changed CONFIG_HIS_DRIVER from n to m. + * + * So we play the same trick that "mkdep" played before. We replace + * the dependency on linux/autoconf.h by a dependency on every config + * option which is mentioned in any of the listed prequisites. + * + * To be exact, split-include populates a tree in include/config/, + * e.g. include/config/his/driver.h, which contains the #define/#undef + * for the CONFIG_HIS_DRIVER option. + * + * So if the user changes his CONFIG_HIS_DRIVER option, only the objects + * which depend on "include/linux/config/his/driver.h" will be rebuilt, + * so most likely only his driver ;-) + * + * The idea above dates, by the way, back to Michael E Chastain, AFAIK. + * + * So to get dependencies right, there are two issues: + * o if any of the files the compiler read changed, we need to rebuild + * o if the command line given to the compile the file changed, we + *   better rebuild as well. + * + * The former is handled by using the -MD output, the later by saving + * the command line used to compile the old object and comparing it + * to the one we would now use. + * + * Again, also this idea is pretty old and has been discussed on + * kbuild-devel a long time ago. I don't have a sensibly working + * internet connection right now, so I rather don't mention names + * without double checking. + * + * This code here has been based partially based on mkdep.c, which + * says the following about its history: + * + *   Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>. + *   This is a C version of syncdep.pl by Werner Almesberger. + * + * + * It is invoked as + * + *   fixdep <depfile> <target> <cmdline> + * + * and will read the dependency file <depfile> + * + * The transformed dependency snipped is written to stdout. + * + * It first generates a line + * + *   cmd_<target> = <cmdline> + * + * and then basically copies the .<target>.d file to stdout, in the + * process filtering out the dependency on linux/autoconf.h and adding + * dependencies on include/config/my/option.h for every + * CONFIG_MY_OPTION encountered in any of the prequisites. + * + * It will also filter out all the dependencies on *.ver. We need + * to make sure that the generated version checksum are globally up + * to date before even starting the recursive build, so it's too late + * at this point anyway. + * + * The algorithm to grep for "CONFIG_..." is bit unusual, but should + * be fast ;-) We don't even try to really parse the header files, but + * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will + * be picked up as well. It's not a problem with respect to + * correctness, since that can only give too many dependencies, thus + * we cannot miss a rebuild. Since people tend to not mention totally + * unrelated CONFIG_ options all over the place, it's not an + * efficiency problem either. + * + * (Note: it'd be easy to port over the complete mkdep state machine, + *  but I don't think the added complexity is worth it) + */ +/* + * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto + * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not + * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as + * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h, + * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that + * those files will have correct dependencies. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <limits.h> +#include <ctype.h> +#include <arpa/inet.h> + +#define INT_CONF ntohl(0x434f4e46) +#define INT_ONFI ntohl(0x4f4e4649) +#define INT_NFIG ntohl(0x4e464947) +#define INT_FIG_ ntohl(0x4649475f) + +char *target; +char *depfile; +char *cmdline; + +void usage(void) + +{ +	fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n"); +	exit(1); +} + +void print_cmdline(void) +{ +	printf("cmd_%s := %s\n\n", target, cmdline); +} + +char * str_config  = NULL; +int    size_config = 0; +int    len_config  = 0; + +/* + * Grow the configuration string to a desired length. + * Usually the first growth is plenty. + */ +void grow_config(int len) +{ +	while (len_config + len > size_config) { +		if (size_config == 0) +			size_config = 2048; +		str_config = realloc(str_config, size_config *= 2); +		if (str_config == NULL) +			{ perror("fixdep:malloc"); exit(1); } +	} +} + + + +/* + * Lookup a value in the configuration string. + */ +int is_defined_config(const char * name, int len) +{ +	const char * pconfig; +	const char * plast = str_config + len_config - len; +	for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) { +		if (pconfig[ -1] == '\n' +		&&  pconfig[len] == '\n' +		&&  !memcmp(pconfig, name, len)) +			return 1; +	} +	return 0; +} + +/* + * Add a new value to the configuration string. + */ +void define_config(const char * name, int len) +{ +	grow_config(len + 1); + +	memcpy(str_config+len_config, name, len); +	len_config += len; +	str_config[len_config++] = '\n'; +} + +/* + * Clear the set of configuration strings. + */ +void clear_config(void) +{ +	len_config = 0; +	define_config("", 0); +} + +/* + * Record the use of a CONFIG_* word. + */ +void use_config(char *m, int slen) +{ +	char s[PATH_MAX]; +	char *p; + +	if (is_defined_config(m, slen)) +	    return; + +	define_config(m, slen); + +	memcpy(s, m, slen); s[slen] = 0; + +	for (p = s; p < s + slen; p++) { +		if (*p == '_') +			*p = '/'; +		else +			*p = tolower((unsigned char)*p); +	} +	printf("    $(wildcard include/config/%s.h) \\\n", s); +} + +void parse_config_file(signed char *map, size_t len) +{ +	int *end = (int *) (map + len); +	/* start at +1, so that p can never be < map */ +	int *m   = (int *) map + 1; +	signed char *p, *q; + +	for (; m < end; m++) { +		if (*m == INT_CONF) { p = (signed char *) m  ; goto conf; } +		if (*m == INT_ONFI) { p = (signed char *) m-1; goto conf; } +		if (*m == INT_NFIG) { p = (signed char *) m-2; goto conf; } +		if (*m == INT_FIG_) { p = (signed char *) m-3; goto conf; } +		continue; +	conf: +		if (p > map + len - 7) +			continue; +		if (memcmp(p, "CONFIG_", 7)) +			continue; +		for (q = p + 7; q < map + len; q++) { +			if (!(isalnum(*q) || *q == '_')) +				goto found; +		} +		continue; + +	found: +		use_config(p+7, q-p-7); +	} +} + +/* test is s ends in sub */ +int strrcmp(char *s, char *sub) +{ +	int slen = strlen(s); +	int sublen = strlen(sub); + +	if (sublen > slen) +		return 1; + +	return memcmp(s + slen - sublen, sub, sublen); +} + +void do_config_file(char *filename) +{ +	struct stat st; +	int fd; +	void *map; + +	fd = open(filename, O_RDONLY); +	if (fd < 0) { +		fprintf(stderr, "fixdep: "); +		perror(filename); +		exit(2); +	} +	fstat(fd, &st); +	if (st.st_size == 0) { +		close(fd); +		return; +	} +	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); +	if ((long) map == -1) { +		perror("fixdep: mmap"); +		close(fd); +		return; +	} + +	parse_config_file(map, st.st_size); + +	munmap(map, st.st_size); + +	close(fd); +} + +void parse_dep_file(void *map, size_t len) +{ +	signed char *m = map; +	signed char *end = m + len; +	signed char *p; +	char s[PATH_MAX]; + +	p = strchr(m, ':'); +	if (!p) { +		fprintf(stderr, "fixdep: parse error\n"); +		exit(1); +	} +	memcpy(s, m, p-m); s[p-m] = 0; +	printf("deps_%s := \\\n", target); +	m = p+1; + +	clear_config(); + +	while (m < end) { +		while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) +			m++; +		p = m; +		while (p < end && *p != ' ') p++; +		if (p == end) { +			do p--; while (!isalnum(*p)); +			p++; +		} +		memcpy(s, m, p-m); s[p-m] = 0; +		if (strrcmp(s, "include/linux/autoconf.h") && +		    strrcmp(s, "arch/um/include/uml-config.h") && +		    strrcmp(s, ".ver")) { +			printf("  %s \\\n", s); +			do_config_file(s); +		} +		m = p + 1; +	} +	printf("\n%s: $(deps_%s)\n\n", target, target); +	printf("$(deps_%s):\n", target); +} + +void print_deps(void) +{ +	struct stat st; +	int fd; +	void *map; + +	fd = open(depfile, O_RDONLY); +	if (fd < 0) { +		fprintf(stderr, "fixdep: "); +		perror(depfile); +		exit(2); +	} +	fstat(fd, &st); +	if (st.st_size == 0) { +		fprintf(stderr,"fixdep: %s is empty\n",depfile); +		close(fd); +		return; +	} +	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); +	if ((long) map == -1) { +		perror("fixdep: mmap"); +		close(fd); +		return; +	} + +	parse_dep_file(map, st.st_size); + +	munmap(map, st.st_size); + +	close(fd); +} + +void traps(void) +{ +	static char test[] __attribute__((aligned(sizeof(int)))) = "CONF"; + +	if (*(int *)test != INT_CONF) { +		fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n", +			*(int *)test); +		exit(2); +	} +} + +int main(int argc, char *argv[]) +{ +	traps(); + +	if (argc != 4) +		usage(); + +	depfile = argv[1]; +	target = argv[2]; +	cmdline = argv[3]; + +	print_cmdline(); +	print_deps(); + +	return 0; +} diff --git a/scripts/basic/split-include.c b/scripts/basic/split-include.c new file mode 100644 index 000000000000..60fc4d8ebaa9 --- /dev/null +++ b/scripts/basic/split-include.c @@ -0,0 +1,226 @@ +/* + * split-include.c + * + * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>. + * This is a C version of syncdep.pl by Werner Almesberger. + * + * This program takes autoconf.h as input and outputs a directory full + * of one-line include files, merging onto the old values. + * + * Think of the configuration options as key-value pairs.  Then there + * are five cases: + * + *    key      old value   new value   action + * + *    KEY-1    VALUE-1     VALUE-1     leave file alone + *    KEY-2    VALUE-2A    VALUE-2B    write VALUE-2B into file + *    KEY-3    -           VALUE-3     write VALUE-3  into file + *    KEY-4    VALUE-4     -           write an empty file + *    KEY-5    (empty)     -           leave old empty file alone + */ + +#include <sys/stat.h> +#include <sys/types.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define ERROR_EXIT(strExit)						\ +    {									\ +	const int errnoSave = errno;					\ +	fprintf(stderr, "%s: ", str_my_name);				\ +	errno = errnoSave;						\ +	perror((strExit));						\ +	exit(1);							\ +    } + + + +int main(int argc, const char * argv []) +{ +    const char * str_my_name; +    const char * str_file_autoconf; +    const char * str_dir_config; + +    FILE * fp_config; +    FILE * fp_target; +    FILE * fp_find; + +    int buffer_size; + +    char * line; +    char * old_line; +    char * list_target; +    char * ptarget; + +    struct stat stat_buf; + +    /* Check arg count. */ +    if (argc != 3) +    { +	fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]); +	exit(1); +    } + +    str_my_name       = argv[0]; +    str_file_autoconf = argv[1]; +    str_dir_config    = argv[2]; + +    /* Find a buffer size. */ +    if (stat(str_file_autoconf, &stat_buf) != 0) +	ERROR_EXIT(str_file_autoconf); +    buffer_size = 2 * stat_buf.st_size + 4096; + +    /* Allocate buffers. */ +    if ( (line        = malloc(buffer_size)) == NULL +    ||   (old_line    = malloc(buffer_size)) == NULL +    ||   (list_target = malloc(buffer_size)) == NULL ) +	ERROR_EXIT(str_file_autoconf); + +    /* Open autoconfig file. */ +    if ((fp_config = fopen(str_file_autoconf, "r")) == NULL) +	ERROR_EXIT(str_file_autoconf); + +    /* Make output directory if needed. */ +    if (stat(str_dir_config, &stat_buf) != 0) +    { +	if (mkdir(str_dir_config, 0755) != 0) +	    ERROR_EXIT(str_dir_config); +    } + +    /* Change to output directory. */ +    if (chdir(str_dir_config) != 0) +	ERROR_EXIT(str_dir_config); + +    /* Put initial separator into target list. */ +    ptarget = list_target; +    *ptarget++ = '\n'; + +    /* Read config lines. */ +    while (fgets(line, buffer_size, fp_config)) +    { +	const signed char * str_config; +	int is_same; +	int itarget; + +	if (line[0] != '#') +	    continue; +	if ((str_config = strstr(line, "CONFIG_")) == NULL) +	    continue; + +	/* Make the output file name. */ +	str_config += sizeof("CONFIG_") - 1; +	for (itarget = 0; !isspace(str_config[itarget]); itarget++) +	{ +	    int c = (unsigned char) str_config[itarget]; +	    if (isupper(c)) c = tolower(c); +	    if (c == '_')   c = '/'; +	    ptarget[itarget] = c; +	} +	ptarget[itarget++] = '.'; +	ptarget[itarget++] = 'h'; +	ptarget[itarget++] = '\0'; + +	/* Check for existing file. */ +	is_same = 0; +	if ((fp_target = fopen(ptarget, "r")) != NULL) +	{ +	    fgets(old_line, buffer_size, fp_target); +	    if (fclose(fp_target) != 0) +		ERROR_EXIT(ptarget); +	    if (!strcmp(line, old_line)) +		is_same = 1; +	} + +	if (!is_same) +	{ +	    /* Auto-create directories. */ +	    int islash; +	    for (islash = 0; islash < itarget; islash++) +	    { +		if (ptarget[islash] == '/') +		{ +		    ptarget[islash] = '\0'; +		    if (stat(ptarget, &stat_buf) != 0 +		    &&  mkdir(ptarget, 0755)     != 0) +			ERROR_EXIT( ptarget ); +		    ptarget[islash] = '/'; +		} +	    } + +	    /* Write the file. */ +	    if ((fp_target = fopen(ptarget, "w" )) == NULL) +		ERROR_EXIT(ptarget); +	    fputs(line, fp_target); +	    if (ferror(fp_target) || fclose(fp_target) != 0) +		ERROR_EXIT(ptarget); +	} + +	/* Update target list */ +	ptarget += itarget; +	*(ptarget-1) = '\n'; +    } + +    /* +     * Close autoconfig file. +     * Terminate the target list. +     */ +    if (fclose(fp_config) != 0) +	ERROR_EXIT(str_file_autoconf); +    *ptarget = '\0'; + +    /* +     * Fix up existing files which have no new value. +     * This is Case 4 and Case 5. +     * +     * I re-read the tree and filter it against list_target. +     * This is crude.  But it avoids data copies.  Also, list_target +     * is compact and contiguous, so it easily fits into cache. +     * +     * Notice that list_target contains strings separated by \n, +     * with a \n before the first string and after the last. +     * fgets gives the incoming names a terminating \n. +     * So by having an initial \n, strstr will find exact matches. +     */ + +    fp_find = popen("find * -type f -name \"*.h\" -print", "r"); +    if (fp_find == 0) +	ERROR_EXIT( "find" ); + +    line[0] = '\n'; +    while (fgets(line+1, buffer_size, fp_find)) +    { +	if (strstr(list_target, line) == NULL) +	{ +	    /* +	     * This is an old file with no CONFIG_* flag in autoconf.h. +	     */ + +	    /* First strip the \n. */ +	    line[strlen(line)-1] = '\0'; + +	    /* Grab size. */ +	    if (stat(line+1, &stat_buf) != 0) +		ERROR_EXIT(line); + +	    /* If file is not empty, make it empty and give it a fresh date. */ +	    if (stat_buf.st_size != 0) +	    { +		if ((fp_target = fopen(line+1, "w")) == NULL) +		    ERROR_EXIT(line); +		if (fclose(fp_target) != 0) +		    ERROR_EXIT(line); +	    } +	} +    } + +    if (pclose(fp_find) != 0) +	ERROR_EXIT("find"); + +    return 0; +} diff --git a/scripts/bin2c.c b/scripts/bin2c.c new file mode 100644 index 000000000000..96dd2bcbb407 --- /dev/null +++ b/scripts/bin2c.c @@ -0,0 +1,36 @@ +/* + * Unloved program to convert a binary on stdin to a C include on stdout + * + * Jan 1999 Matt Mackall <mpm@selenic.com> + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#include <stdio.h> + +int main(int argc, char *argv[]) +{ +	int ch, total=0; + +	if (argc > 1) +		printf("const char %s[] %s=\n", +			argv[1], argc > 2 ? argv[2] : ""); + +	do { +		printf("\t\""); +		while ((ch = getchar()) != EOF) +		{ +			total++; +			printf("\\x%02x",ch); +			if (total % 16 == 0) +				break; +		} +		printf("\"\n"); +	} while (ch != EOF); + +	if (argc > 1) +		printf("\t;\n\nconst int %s_size = %d;\n", argv[1], total); + +	return 0; +} diff --git a/scripts/binoffset.c b/scripts/binoffset.c new file mode 100644 index 000000000000..591309d85518 --- /dev/null +++ b/scripts/binoffset.c @@ -0,0 +1,163 @@ +/*************************************************************************** + * binoffset.c + * (C) 2002 Randy Dunlap <rddunlap@osdl.org> + +#   This program is free software; you can redistribute it and/or modify +#   it under the terms of the GNU General Public License as published by +#   the Free Software Foundation; either version 2 of the License, or +#   (at your option) any later version. +# +#   This program is distributed in the hope that it will be useful, +#   but WITHOUT ANY WARRANTY; without even the implied warranty of +#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#   GNU General Public License for more details. +# +#   You should have received a copy of the GNU General Public License +#   along with this program; if not, write to the Free Software +#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# binoffset.c: +# - searches a (binary) file for a specified (binary) pattern +# - returns the offset of the located pattern or ~0 if not found +# - exits with exit status 0 normally or non-0 if pattern is not found +#   or any other error occurs. + +****************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#define VERSION		"0.1" +#define BUF_SIZE	(16 * 1024) +#define PAT_SIZE	100 + +char		*progname; +char		*inputname; +int		inputfd; +unsigned int	bix;			/* buf index */ +unsigned char	patterns [PAT_SIZE] = {0}; /* byte-sized pattern array */ +int		pat_len;		/* actual number of pattern bytes */ +unsigned char	*madr;			/* mmap address */ +size_t		filesize; +int		num_matches = 0; +off_t		firstloc = 0; + +void usage (void) +{ +	fprintf (stderr, "%s ver. %s\n", progname, VERSION); +	fprintf (stderr, "usage:  %s filename pattern_bytes\n", +			progname); +	fprintf (stderr, "        [prints location of pattern_bytes in file]\n"); +	exit (1); +} + +void get_pattern (int pat_count, char *pats []) +{ +	int ix, err, tmp; + +#ifdef DEBUG +	fprintf (stderr,"get_pattern: count = %d\n", pat_count); +	for (ix = 0; ix < pat_count; ix++) +		fprintf (stderr, "  pat # %d:  [%s]\n", ix, pats[ix]); +#endif + +	for (ix = 0; ix < pat_count; ix++) { +		tmp = 0; +		err = sscanf (pats[ix], "%5i", &tmp); +		if (err != 1 || tmp > 0xff) { +			fprintf (stderr, "pattern or value error in pattern # %d [%s]\n", +					ix, pats[ix]); +			usage (); +		} +		patterns [ix] = tmp; +	} +	pat_len = pat_count; +} + +void search_pattern (void) +{ +	for (bix = 0; bix < filesize; bix++) { +		if (madr[bix] == patterns[0]) { +			if (memcmp (&madr[bix], patterns, pat_len) == 0) { +				if (num_matches == 0) +					firstloc = bix; +				num_matches++; +			} +		} +	} +} + +#ifdef NOTDEF +size_t get_filesize (int fd) +{ +	off_t end_off = lseek (fd, 0, SEEK_END); +	lseek (fd, 0, SEEK_SET); +	return (size_t) end_off; +} +#endif + +size_t get_filesize (int fd) +{ +	int err; +	struct stat stat; + +	err = fstat (fd, &stat); +	fprintf (stderr, "filesize: %ld\n", err < 0 ? (long)err : stat.st_size); +	if (err < 0) +		return err; +	return (size_t) stat.st_size; +} + +int main (int argc, char *argv []) +{ +	progname = argv[0]; + +	if (argc < 3) +		usage (); + +	get_pattern (argc - 2, argv + 2); + +	inputname = argv[1]; + +	inputfd = open (inputname, O_RDONLY); +	if (inputfd == -1) { +		fprintf (stderr, "%s: cannot open '%s'\n", +				progname, inputname); +		exit (3); +	} + +	filesize = get_filesize (inputfd); + +	madr = mmap (0, filesize, PROT_READ, MAP_PRIVATE, inputfd, 0); +	if (madr == MAP_FAILED) { +		fprintf (stderr, "mmap error = %d\n", errno); +		close (inputfd); +		exit (4); +	} + +	search_pattern (); + +	if (munmap (madr, filesize)) +		fprintf (stderr, "munmap error = %d\n", errno); + +	if (close (inputfd)) +		fprintf (stderr, "%s: error %d closing '%s'\n", +				progname, errno, inputname); + +	fprintf (stderr, "number of pattern matches = %d\n", num_matches); +	if (num_matches == 0) +		firstloc = ~0; +	printf ("%ld\n", firstloc); +	fprintf (stderr, "%ld\n", firstloc); + +	exit (num_matches ? 0 : 2); +} + +/* end binoffset.c */ diff --git a/scripts/checkconfig.pl b/scripts/checkconfig.pl new file mode 100755 index 000000000000..ca1f231b15a6 --- /dev/null +++ b/scripts/checkconfig.pl @@ -0,0 +1,65 @@ +#! /usr/bin/perl +# +# checkconfig: find uses of CONFIG_* names without matching definitions. +# Copyright abandoned, 1998, Michael Elizabeth Chastain <mailto:mec@shout.net>. + +use integer; + +$| = 1; + +foreach $file (@ARGV) +{ +    # Open this file. +    open(FILE, $file) || die "Can't open $file: $!\n"; + +    # Initialize variables. +    my $fInComment   = 0; +    my $fInString    = 0; +    my $fUseConfig   = 0; +    my $iLinuxConfig = 0; +    my %configList   = (); + +    LINE: while ( <FILE> ) +    { +	# Strip comments. +	$fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next); +	m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1))); + +	# Pick up definitions. +	if ( m/^\s*#/o ) +	{ +	    $iLinuxConfig      = $. if m/^\s*#\s*include\s*"linux\/config\.h"/o; +	    $configList{uc $1} = 1  if m/^\s*#\s*include\s*"config\/(\S*)\.h"/o; +	} + +	# Strip strings. +	$fInString && (s+^.*?"+ +o ? ($fInString = 0) : next); +	m+"+o && (s+".*?"+ +go, (s+".*$+ +o && ($fInString = 1))); + +	# Pick up definitions. +	if ( m/^\s*#/o ) +	{ +	    $iLinuxConfig      = $. if m/^\s*#\s*include\s*<linux\/config\.h>/o; +	    $configList{uc $1} = 1  if m/^\s*#\s*include\s*<config\/(\S*)\.h>/o; +	    $configList{$1}    = 1  if m/^\s*#\s*define\s+CONFIG_(\w*)/o; +	    $configList{$1}    = 1  if m/^\s*#\s*undef\s+CONFIG_(\w*)/o; +	} + +	# Look for usages. +	next unless m/CONFIG_/o; +	WORD: while ( m/\bCONFIG_(\w+)/og ) +	{ +	    $fUseConfig = 1; +	    last LINE if $iLinuxConfig; +	    next WORD if exists $configList{$1}; +	    print "$file: $.: need CONFIG_$1.\n"; +	    $configList{$1} = 0; +	} +    } + +    # Report superfluous includes. +    if ( $iLinuxConfig && ! $fUseConfig ) +	{ print "$file: $iLinuxConfig: linux/config.h not needed.\n"; } + +    close(FILE); +} diff --git a/scripts/checkincludes.pl b/scripts/checkincludes.pl new file mode 100755 index 000000000000..8e6b716c191c --- /dev/null +++ b/scripts/checkincludes.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl +# +# checkincludes: Find files included more than once in (other) files. +# Copyright abandoned, 2000, Niels Kristian Bech Jensen <nkbj@image.dk>. + +foreach $file (@ARGV) { +	open(FILE, $file) or die "Cannot open $file: $!.\n"; + +	my %includedfiles = (); + +	while (<FILE>) { +		if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) { +			++$includedfiles{$1}; +		} +	} +	 +	foreach $filename (keys %includedfiles) { +		if ($includedfiles{$filename} > 1) { +			print "$file: $filename is included more than once.\n"; +		} +	} + +	close(FILE); +} diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl new file mode 100644 index 000000000000..dadfa20ffec0 --- /dev/null +++ b/scripts/checkstack.pl @@ -0,0 +1,123 @@ +#!/usr/bin/perl + +#	Check the stack usage of functions +# +#	Copyright Joern Engel <joern@wh.fh-wedel.de> +#	Inspired by Linus Torvalds +#	Original idea maybe from Keith Owens +#	s390 port and big speedup by Arnd Bergmann <arnd@bergmann-dalldorf.de> +#	Mips port by Juan Quintela <quintela@mandrakesoft.com> +#	IA64 port via Andreas Dilger +#	Arm port by Holger Schurig +#	sh64 port by Paul Mundt +#	Random bits by Matt Mackall <mpm@selenic.com> +#	M68k port by Geert Uytterhoeven and Andreas Schwab +# +#	Usage: +#	objdump -d vmlinux | stackcheck.pl [arch] +# +#	TODO :	Port to all architectures (one regex per arch) + +# check for arch +# +# $re is used for two matches: +# $& (whole re) matches the complete objdump line with the stack growth +# $1 (first bracket) matches the size of the stack growth +# +# use anything else and feel the pain ;) +my (@stack, $re, $x, $xs); +{ +	my $arch = shift; +	if ($arch eq "") { +		$arch = `uname -m`; +	} + +	$x	= "[0-9a-f]";	# hex character +	$xs	= "[0-9a-f ]";	# hex character or space +	if ($arch eq 'arm') { +		#c0008ffc:	e24dd064	sub	sp, sp, #100	; 0x64 +		$re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o; +	} elsif ($arch =~ /^i[3456]86$/) { +		#c0105234:       81 ec ac 05 00 00       sub    $0x5ac,%esp +		$re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%esp$/o; +	} elsif ($arch eq 'x86_64') { +		#    2f60:	48 81 ec e8 05 00 00 	sub    $0x5e8,%rsp +		$re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%rsp$/o; +	} elsif ($arch eq 'ia64') { +		#e0000000044011fc:       01 0f fc 8c     adds r12=-384,r12 +		$re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; +	} elsif ($arch eq 'm68k') { +		#    2b6c:       4e56 fb70       linkw %fp,#-1168 +		#  1df770:       defc ffe4       addaw #-28,%sp +		$re = qr/.*(?:linkw %fp,|addaw )#-([0-9]{1,4})(?:,%sp)?$/o; +	} elsif ($arch eq 'mips64') { +		#8800402c:       67bdfff0        daddiu  sp,sp,-16 +		$re = qr/.*daddiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; +	} elsif ($arch eq 'mips') { +		#88003254:       27bdffe0        addiu   sp,sp,-32 +		$re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; +	} elsif ($arch eq 'ppc') { +		#c00029f4:       94 21 ff 30     stwu    r1,-208(r1) +		$re = qr/.*stwu.*r1,-($x{1,8})\(r1\)/o; +	} elsif ($arch eq 'ppc64') { +		#XXX +		$re = qr/.*stdu.*r1,-($x{1,8})\(r1\)/o; +	} elsif ($arch =~ /^s390x?$/) { +		#   11160:       a7 fb ff 60             aghi   %r15,-160 +		$re = qr/.*ag?hi.*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})/o; +	} elsif ($arch =~ /^sh64$/) { +		#XXX: we only check for the immediate case presently, +		#     though we will want to check for the movi/sub +		#     pair for larger users. -- PFM. +		#a00048e0:       d4fc40f0        addi.l  r15,-240,r15 +		$re = qr/.*addi\.l.*r15,-(([0-9]{2}|[3-9])[0-9]{2}),r15/o; +	} else { +		print("wrong or unknown architecture\n"); +		exit +	} +} + +sub bysize($) { +	my ($asize, $bsize); +	($asize = $a) =~ s/.*:	*(.*)$/$1/; +	($bsize = $b) =~ s/.*:	*(.*)$/$1/; +	$bsize <=> $asize +} + +# +# main() +# +my $funcre = qr/^$x* <(.*)>:$/; +my $func; +while (my $line = <STDIN>) { +	if ($line =~ m/$funcre/) { +		$func = $1; +	} +	if ($line =~ m/$re/) { +		my $size = $1; +		$size = hex($size) if ($size =~ /^0x/); + +		if ($size > 0xf0000000) { +			$size = - $size; +			$size += 0x80000000; +			$size += 0x80000000; +		} +		next if ($size > 0x10000000); + +		next if $line !~ m/^($xs*)/; +		my $addr = $1; +		$addr =~ s/ /0/g; +		$addr = "0x$addr"; + +		my $intro = "$addr $func:"; +		my $padlen = 56 - length($intro); +		while ($padlen > 0) { +			$intro .= '	'; +			$padlen -= 8; +		} +		next if ($size < 100); +		push @stack, "$intro$size\n"; +	} +} + +print sort bysize @stack; diff --git a/scripts/checkversion.pl b/scripts/checkversion.pl new file mode 100755 index 000000000000..df10db662eb1 --- /dev/null +++ b/scripts/checkversion.pl @@ -0,0 +1,72 @@ +#! /usr/bin/perl +# +# checkversion find uses of LINUX_VERSION_CODE, KERNEL_VERSION, or +# UTS_RELEASE without including <linux/version.h>, or cases of +# including <linux/version.h> that don't need it. +# Copyright (C) 2003, Randy Dunlap <rddunlap@osdl.org> + +$| = 1; + +my $debugging = 0; + +foreach $file (@ARGV) +{ +    # Open this file. +    open(FILE, $file) || die "Can't open $file: $!\n"; + +    # Initialize variables. +    my $fInComment   = 0; +    my $fInString    = 0; +    my $fUseVersion   = 0; +    my $iLinuxVersion = 0; + +    LINE: while ( <FILE> ) +    { +	# Strip comments. +	$fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next); +	m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1))); + +	# Pick up definitions. +	if ( m/^\s*#/o ) { +	    $iLinuxVersion      = $. if m/^\s*#\s*include\s*"linux\/version\.h"/o; +	} + +	# Strip strings. +	$fInString && (s+^.*?"+ +o ? ($fInString = 0) : next); +	m+"+o && (s+".*?"+ +go, (s+".*$+ +o && ($fInString = 1))); + +	# Pick up definitions. +	if ( m/^\s*#/o ) { +	    $iLinuxVersion      = $. if m/^\s*#\s*include\s*<linux\/version\.h>/o; +	} + +	# Look for uses: LINUX_VERSION_CODE, KERNEL_VERSION, UTS_RELEASE +	if (($_ =~ /LINUX_VERSION_CODE/) || ($_ =~ /\WKERNEL_VERSION/) || +		($_ =~ /UTS_RELEASE/)) { +	    $fUseVersion = 1; +	    last LINE if $iLinuxVersion; +	} +    } + +    # Report used version IDs without include? +    if ($fUseVersion && ! $iLinuxVersion) { +	print "$file: $.: need linux/version.h\n"; +    } + +    # Report superfluous includes. +    if ($iLinuxVersion && ! $fUseVersion) { +	print "$file: $iLinuxVersion linux/version.h not needed.\n"; +    } + +    # debug: report OK results: +    if ($debugging) { +        if ($iLinuxVersion && $fUseVersion) { +	    print "$file: version use is OK ($iLinuxVersion)\n"; +        } +        if (! $iLinuxVersion && ! $fUseVersion) { +	    print "$file: version use is OK (none)\n"; +        } +    } + +    close(FILE); +} diff --git a/scripts/conmakehash.c b/scripts/conmakehash.c new file mode 100644 index 000000000000..93dd23f21ec9 --- /dev/null +++ b/scripts/conmakehash.c @@ -0,0 +1,293 @@ +/* + * conmakehash.c + * + * Create arrays for initializing the kernel folded tables (using a hash + * table turned out to be to limiting...)  Unfortunately we can't simply + * preinitialize the tables at compile time since kfree() cannot accept + * memory not allocated by kmalloc(), and doing our own memory management + * just for this seems like massive overkill. + * + * Copyright (C) 1995-1997 H. Peter Anvin + * + * This program is a part of the Linux kernel, and may be freely + * copied under the terms of the GNU General Public License (GPL), + * version 2, or at your option any later version. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sysexits.h> +#include <string.h> +#include <ctype.h> + +#define MAX_FONTLEN 256 + +typedef unsigned short unicode; + +void usage(char *argv0) +{ +  fprintf(stderr, "Usage: \n" +         "        %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0); +  exit(EX_USAGE); +} + +int getunicode(char **p0) +{ +  unsigned char *p = *p0; + +  while (*p == ' ' || *p == '\t') +    p++; +  if (*p != 'U' || p[1] != '+' || +      !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) || +      !isxdigit(p[5]) || isxdigit(p[6])) +    return -1; +  *p0 = p+6; +  return strtol(p+2,0,16); +} + +unicode unitable[MAX_FONTLEN][255]; +				/* Massive overkill, but who cares? */ +int unicount[MAX_FONTLEN]; + +void addpair(int fp, int un) +{ +  int i; + +  if ( un <= 0xfffe ) +    { +      /* Check it isn't a duplicate */ + +      for ( i = 0 ; i < unicount[fp] ; i++ ) +	if ( unitable[fp][i] == un ) +	  return; + +      /* Add to list */ + +      if ( unicount[fp] > 254 ) +	{ +	  fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n"); +	  exit(EX_DATAERR); +	} + +      unitable[fp][unicount[fp]] = un; +      unicount[fp]++; +    } + +  /* otherwise: ignore */ +} + +int main(int argc, char *argv[]) +{ +  FILE *ctbl; +  char *tblname; +  char buffer[65536]; +  int fontlen; +  int i, nuni, nent; +  int fp0, fp1, un0, un1; +  char *p, *p1; + +  if ( argc < 2 || argc > 5 ) +    usage(argv[0]); + +  if ( !strcmp(argv[1],"-") ) +    { +      ctbl = stdin; +      tblname = "stdin"; +    } +  else +    { +      ctbl = fopen(tblname = argv[1], "r"); +      if ( !ctbl ) +	{ +	  perror(tblname); +	  exit(EX_NOINPUT); +	} +    } + +  /* For now we assume the default font is always 256 characters. */     +  fontlen = 256; + +  /* Initialize table */ + +  for ( i = 0 ; i < fontlen ; i++ ) +    unicount[i] = 0; + +  /* Now we come to the tricky part.  Parse the input table. */ + +  while ( fgets(buffer, sizeof(buffer), ctbl) != NULL ) +    { +      if ( (p = strchr(buffer, '\n')) != NULL ) +	*p = '\0'; +      else +	fprintf(stderr, "%s: Warning: line too long\n", tblname); + +      p = buffer; + +/* + * Syntax accepted: + *	<fontpos>	<unicode> <unicode> ... + *	<range>		idem + *	<range>		<unicode range> + * + * where <range> ::= <fontpos>-<fontpos> + * and <unicode> ::= U+<h><h><h><h> + * and <h> ::= <hexadecimal digit> + */ + +      while (*p == ' ' || *p == '\t') +	p++; +      if (!*p || *p == '#') +	continue;	/* skip comment or blank line */ + +      fp0 = strtol(p, &p1, 0); +      if (p1 == p) +	{ +	  fprintf(stderr, "Bad input line: %s\n", buffer); +	  exit(EX_DATAERR); +        } +      p = p1; + +      while (*p == ' ' || *p == '\t') +	p++; +      if (*p == '-') +	{ +	  p++; +	  fp1 = strtol(p, &p1, 0); +	  if (p1 == p) +	    { +	      fprintf(stderr, "Bad input line: %s\n", buffer); +	      exit(EX_DATAERR); +	    } +	  p = p1; +        } +      else +	fp1 = 0; + +      if ( fp0 < 0 || fp0 >= fontlen ) +	{ +	    fprintf(stderr, +		    "%s: Glyph number (0x%x) larger than font length\n", +		    tblname, fp0); +	    exit(EX_DATAERR); +	} +      if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) ) +	{ +	    fprintf(stderr, +		    "%s: Bad end of range (0x%x)\n", +		    tblname, fp1); +	    exit(EX_DATAERR); +	} + +      if (fp1) +	{ +	  /* we have a range; expect the word "idem" or a Unicode range of the +	     same length */ +	  while (*p == ' ' || *p == '\t') +	    p++; +	  if (!strncmp(p, "idem", 4)) +	    { +	      for (i=fp0; i<=fp1; i++) +		addpair(i,i); +	      p += 4; +	    } +	  else +	    { +	      un0 = getunicode(&p); +	      while (*p == ' ' || *p == '\t') +		p++; +	      if (*p != '-') +		{ +		  fprintf(stderr, +"%s: Corresponding to a range of font positions, there should be a Unicode range\n", +			  tblname); +		  exit(EX_DATAERR); +	        } +	      p++; +	      un1 = getunicode(&p); +	      if (un0 < 0 || un1 < 0) +		{ +		  fprintf(stderr, +"%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n", +			  tblname, fp0, fp1); +		  exit(EX_DATAERR); +	        } +	      if (un1 - un0 != fp1 - fp0) +		{ +		  fprintf(stderr, +"%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n", +			  tblname, un0, un1, fp0, fp1); +		  exit(EX_DATAERR); +	        } +	      for(i=fp0; i<=fp1; i++) +		addpair(i,un0-fp0+i); +	    } +        } +      else +	{ +	    /* no range; expect a list of unicode values for a single font position */ + +	    while ( (un0 = getunicode(&p)) >= 0 ) +	      addpair(fp0, un0); +	} +      while (*p == ' ' || *p == '\t') +	p++; +      if (*p && *p != '#') +	fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p); +    } + +  /* Okay, we hit EOF, now output hash table */ +   +  fclose(ctbl); +   + +  /* Compute total size of Unicode list */ +  nuni = 0; +  for ( i = 0 ; i < fontlen ; i++ ) +    nuni += unicount[i]; +   +  printf("\ +/*\n\ + * Do not edit this file; it was automatically generated by\n\ + *\n\ + * conmakehash %s > [this file]\n\ + *\n\ + */\n\ +\n\ +#include <linux/types.h>\n\ +\n\ +u8 dfont_unicount[%d] = \n\ +{\n\t", argv[1], fontlen); + +  for ( i = 0 ; i < fontlen ; i++ ) +    { +      printf("%3d", unicount[i]); +      if ( i == fontlen-1 ) +        printf("\n};\n"); +      else if ( i % 8 == 7 ) +        printf(",\n\t"); +      else +        printf(", "); +    } +   +  printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni); +   +  fp0 = 0; +  nent = 0; +  for ( i = 0 ; i < nuni ; i++ ) +    { +      while ( nent >= unicount[fp0] ) +	{ +	  fp0++; +	  nent = 0; +	} +      printf("0x%04x", unitable[fp0][nent++]); +      if ( i == nuni-1 ) +         printf("\n};\n"); +       else if ( i % 8 == 7 ) +         printf(",\n\t"); +       else +         printf(", "); +    } + +  exit(EX_OK); +} diff --git a/scripts/extract-ikconfig b/scripts/extract-ikconfig new file mode 100755 index 000000000000..d9f9f34b22ab --- /dev/null +++ b/scripts/extract-ikconfig @@ -0,0 +1,77 @@ +#!/bin/sh +# extracts .config info from a [b]zImage file +# uses: binoffset (new), dd, zcat, strings, grep +# $arg1 is [b]zImage filename + +binoffset="./scripts/binoffset" + +IKCFG_ST="0x49 0x4b 0x43 0x46 0x47 0x5f 0x53 0x54" +IKCFG_ED="0x49 0x4b 0x43 0x46 0x47 0x5f 0x45 0x44" +function dump_config { +    typeset file="$1" + +    start=`$binoffset $file $IKCFG_ST 2>/dev/null` +    [ "$?" != "0" ] && start="-1" +    if [ "$start" -eq "-1" ]; then +	return +    fi +    end=`$binoffset $file $IKCFG_ED 2>/dev/null` + +    let start="$start + 8" +    let size="$end - $start" + +    head --bytes="$end" "$file" | tail --bytes="$size" | zcat + +    clean_up +    exit 0 +} + + +usage() +{ +	echo "  usage: extract-ikconfig [b]zImage_filename" +} + +clean_up() +{ +	if [ "$TMPFILE" != "" ]; then +		rm -f $TMPFILE +	fi +} + +if [ $# -lt 1 ] +then +	usage +	exit 1 +fi + +TMPFILE="/tmp/ikconfig-$$" +image="$1" + +# vmlinux: Attempt to dump the configuration from the file directly +dump_config "$image" + +GZHDR1="0x1f 0x8b 0x08 0x00" +GZHDR2="0x1f 0x8b 0x08 0x08" + +# vmlinux.gz: Check for a compressed images +off=`$binoffset "$image" $GZHDR1 2>/dev/null` +[ "$?" != "0" ] && off="-1" +if [ "$off" -eq "-1" ]; then +	off=`$binoffset "$image" $GZHDR2 2>/dev/null` +	[ "$?" != "0" ] && off="-1" +fi +if [ "$off" -eq "0" ]; then +	zcat <"$image" >"$TMPFILE" +	dump_config "$TMPFILE" +elif [ "$off" -ne "-1" ]; then +	(dd ibs="$off" skip=1 count=0 && dd bs=512k) <"$image" 2>/dev/null | \ +		zcat >"$TMPFILE" +	dump_config "$TMPFILE" +fi + +echo "ERROR: Unable to extract kernel configuration information." +echo "       This kernel image may not have the config info." + +clean_up +exit 1 diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh new file mode 100644 index 000000000000..bb4fbeab8320 --- /dev/null +++ b/scripts/gcc-version.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# +# gcc-version gcc-command +# +# Prints the gcc version of `gcc-command' in a canonical 4-digit form +# such as `0295' for gcc-2.95, `0303' for gcc-3.3, etc. +# + +compiler="$*" + +MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1) +MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1) +printf "%02d%02d\\n" $MAJOR $MINOR + diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh new file mode 100644 index 000000000000..6d411169bfa6 --- /dev/null +++ b/scripts/gen_initramfs_list.sh @@ -0,0 +1,203 @@ +#!/bin/bash +# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org> +# Released under the terms of the GNU GPL +# +# Generate a newline separated list of entries from the file/directory +# supplied as an argument. +# +# If a file/directory is not supplied then generate a small dummy file. +# +# The output is suitable for gen_init_cpio built from usr/gen_init_cpio.c. +# + +default_initramfs() { +	cat <<-EOF +		# This is a very simple, default initramfs + +		dir /dev 0755 0 0 +		nod /dev/console 0600 0 0 c 5 1 +		dir /root 0700 0 0 +	EOF +} + +filetype() { +	local argv1="$1" + +	# symlink test must come before file test +	if [ -L "${argv1}" ]; then +		echo "slink" +	elif [ -f "${argv1}" ]; then +		echo "file" +	elif [ -d "${argv1}" ]; then +		echo "dir" +	elif [ -b "${argv1}" -o -c "${argv1}" ]; then +		echo "nod" +	elif [ -p "${argv1}" ]; then +		echo "pipe" +	elif [ -S "${argv1}" ]; then +		echo "sock" +	else +		echo "invalid" +	fi +	return 0 +} + +print_mtime() { +	local argv1="$1" +	local my_mtime="0" + +	if [ -e "${argv1}" ]; then +		my_mtime=$(find "${argv1}" -printf "%T@\n" | sort -r | head -n 1) +	fi +	 +	echo "# Last modified: ${my_mtime}" +	echo +} + +parse() { +	local location="$1" +	local name="${location/${srcdir}//}" +	# change '//' into '/' +	name="${name//\/\///}" +	local mode="$2" +	local uid="$3" +	local gid="$4" +	local ftype=$(filetype "${location}") +	# remap uid/gid to 0 if necessary +	[ "$uid" -eq "$root_uid" ] && uid=0 +	[ "$gid" -eq "$root_gid" ] && gid=0 +	local str="${mode} ${uid} ${gid}" + +	[ "${ftype}" == "invalid" ] && return 0 +	[ "${location}" == "${srcdir}" ] && return 0 + +	case "${ftype}" in +		"file") +			str="${ftype} ${name} ${location} ${str}" +			;; +		"nod") +			local dev_type= +			local maj=$(LC_ALL=C ls -l "${location}" | \ +					gawk '{sub(/,/, "", $5); print $5}') +			local min=$(LC_ALL=C ls -l "${location}" | \ +					gawk '{print $6}') + +			if [ -b "${location}" ]; then +				dev_type="b" +			else +				dev_type="c" +			fi +			str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}" +			;; +		"slink") +			local target=$(LC_ALL=C ls -l "${location}" | \ +					gawk '{print $11}') +			str="${ftype} ${name} ${target} ${str}" +			;; +		*) +			str="${ftype} ${name} ${str}" +			;; +	esac + +	echo "${str}" + +	return 0 +} + +usage() { +	printf    "Usage:\n" +	printf    "$0 [ [-u <root_uid>] [-g <root_gid>] [-d | <cpio_source>] ] . . .\n" +	printf    "\n" +	printf -- "-u <root_uid>  User ID to map to user ID 0 (root).\n" +	printf    "               <root_uid> is only meaningful if <cpio_source>\n" +	printf    "               is a directory.\n" +	printf -- "-g <root_gid>  Group ID to map to group ID 0 (root).\n" +	printf    "               <root_gid> is only meaningful if <cpio_source>\n" +	printf    "               is a directory.\n" +	printf    "<cpio_source>  File list or directory for cpio archive.\n" +	printf    "               If <cpio_source> is not provided then a\n" +	printf    "               a default list will be output.\n" +	printf -- "-d             Output the default cpio list.  If no <cpio_source>\n" +	printf    "               is given then the default cpio list will be output.\n" +	printf    "\n" +	printf    "All options may be repeated and are interpreted sequentially\n" +	printf    "and immediately.  -u and -g states are preserved across\n" +	printf    "<cpio_source> options so an explicit \"-u 0 -g 0\" is required\n" +	printf    "to reset the root/group mapping.\n" +} + +build_list() { +	printf "\n#####################\n# $cpio_source\n" + +	if [ -f "$cpio_source" ]; then +		print_mtime "$cpio_source" +		cat "$cpio_source" +	elif [ -d "$cpio_source" ]; then +		srcdir=$(echo "$cpio_source" | sed -e 's://*:/:g') +		dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null) + +		# If $dirlist is only one line, then the directory is empty +		if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then +			print_mtime "$cpio_source" +		 +			echo "${dirlist}" | \ +			while read x; do +				parse ${x} +			done +		else +			# Failsafe in case directory is empty +			default_initramfs +		fi +	else +		echo "  $0: Cannot open '$cpio_source'" >&2 +		exit 1 +	fi +} + + +root_uid=0 +root_gid=0 + +while [ $# -gt 0 ]; do +	arg="$1" +	shift +	case "$arg" in +		"-u") +			root_uid="$1" +			shift +			;; +		"-g") +			root_gid="$1" +			shift +			;; +		"-d") +			default_list="$arg" +			default_initramfs +			;; +		"-h") +			usage +			exit 0 +			;; +		*) +			case "$arg" in +				"-"*) +					printf "ERROR: unknown option \"$arg\"\n" >&2 +					printf "If the filename validly begins with '-', then it must be prefixed\n" >&2 +					printf "by './' so that it won't be interpreted as an option." >&2 +					printf "\n" >&2 +					usage >&2 +					exit 1 +					;; +				*) +					cpio_source="$arg" +					build_list +					;; +			esac +			;; +	esac +done + +# spit out the default cpio list if a source hasn't been specified +[ -z "$cpio_source" -a -z "$default_list" ] && default_initramfs + +exit 0 diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile new file mode 100644 index 000000000000..5875f29a8602 --- /dev/null +++ b/scripts/genksyms/Makefile @@ -0,0 +1,49 @@ + +hostprogs-y	:= genksyms +always		:= $(hostprogs-y) + +genksyms-objs	:= genksyms.o parse.o lex.o + +# -I needed for generated C source (shipped source) +HOSTCFLAGS_parse.o := -Wno-uninitialized -I$(src) + +# dependencies on generated files need to be listed explicitly +$(obj)/lex.o: $(obj)/parse.h $(obj)/keywords.c + +# -I needed for generated C source (shipped source) +HOSTCFLAGS_lex.o := -I$(src) + +ifdef GENERATE_PARSER + +# gperf + +quiet_cmd_keywords.c = GPERF   $@ +      cmd_keywords.c = gperf -L ANSI-C -a -C -E -g -H is_reserved_hash	\ +		       -k 1,3,$$ -N is_reserved_word -p -t $< > $@ + +$(obj)/keywords.c: $(obj)/keywords.gperf FORCE +	$(call if_changed,keywords.c) + +# flex + +quiet_cmd_lex.c = FLEX    $@ +      cmd_lex.c = flex -o$@ -d $(filter-out FORCE,$^) + +$(obj)/lex.c: $(obj)/lex.l $(obj)/parse.h FORCE +	$(call if_changed,lex.c) + +# bison + +quiet_cmd_parse.c = BISON   $@ +      cmd_parse.c = bison -o$@ -dtv $(filter-out FORCE,$^) + +$(obj)/parse.c: $(obj)/parse.y FORCE +	$(call if_changed,parse.c) + +$(obj)/parse.h: $(obj)/parse.c ; + +clean-files	+= parse.output + +endif + +targets += keywords.c lex.c parse.c parse.h diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c new file mode 100644 index 000000000000..416a694b0998 --- /dev/null +++ b/scripts/genksyms/genksyms.c @@ -0,0 +1,591 @@ +/* Generate kernel symbol version hashes. +   Copyright 1996, 1997 Linux International. + +   New implementation contributed by Richard Henderson <rth@tamu.edu> +   Based on original work by Bjorn Ekwall <bj0rn@blox.se> + +   This file was part of the Linux modutils 2.4.22: moved back into the +   kernel sources by Rusty Russell/Kai Germaschewski. + +   This program is free software; you can redistribute it and/or modify it +   under the terms of the GNU General Public License as published by the +   Free Software Foundation; either version 2 of the License, or (at your +   option) any later version. + +   This program is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software Foundation, +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <stdarg.h> +#ifdef __GNU_LIBRARY__ +#include <getopt.h> +#endif /* __GNU_LIBRARY__ */ + +#include "genksyms.h" + +/*----------------------------------------------------------------------*/ + +#define HASH_BUCKETS  4096 + +static struct symbol *symtab[HASH_BUCKETS]; +FILE *debugfile; + +int cur_line = 1; +char *cur_filename, *output_directory; + +int flag_debug, flag_dump_defs, flag_warnings; + +static int errors; +static int nsyms; + +static struct symbol *expansion_trail; + +static const char * const symbol_type_name[] = { +  "normal", "typedef", "enum", "struct", "union" +}; + +/*----------------------------------------------------------------------*/ + +static const unsigned int crctab32[] = +{ +  0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, +  0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, +  0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, +  0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, +  0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, +  0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, +  0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, +  0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, +  0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, +  0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, +  0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, +  0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, +  0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, +  0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, +  0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, +  0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, +  0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, +  0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, +  0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, +  0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, +  0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, +  0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, +  0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, +  0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, +  0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, +  0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, +  0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, +  0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, +  0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, +  0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, +  0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, +  0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, +  0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, +  0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, +  0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, +  0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, +  0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, +  0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, +  0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, +  0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, +  0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, +  0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, +  0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, +  0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, +  0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, +  0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, +  0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, +  0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, +  0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, +  0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, +  0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, +  0x2d02ef8dU +}; + +static inline unsigned long +partial_crc32_one(unsigned char c, unsigned long crc) +{ +  return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); +} + +static inline unsigned long +partial_crc32(const char *s, unsigned long crc) +{ +  while (*s) +    crc = partial_crc32_one(*s++, crc); +  return crc; +} + +static inline unsigned long +crc32(const char *s) +{ +  return partial_crc32(s, 0xffffffff) ^ 0xffffffff; +} + + +/*----------------------------------------------------------------------*/ + +static inline enum symbol_type +map_to_ns(enum symbol_type t) +{ +  if (t == SYM_TYPEDEF) +    t = SYM_NORMAL; +  else if (t == SYM_UNION) +    t = SYM_STRUCT; +  return t; +} + +struct symbol * +find_symbol(const char *name, enum symbol_type ns) +{ +  unsigned long h = crc32(name) % HASH_BUCKETS; +  struct symbol *sym; + +  for (sym = symtab[h]; sym ; sym = sym->hash_next) +    if (map_to_ns(sym->type) == map_to_ns(ns) && strcmp(name, sym->name) == 0) +      break; + +  return sym; +} + +struct symbol * +add_symbol(const char *name, enum symbol_type type, struct string_list *defn, int is_extern) +{ +  unsigned long h = crc32(name) % HASH_BUCKETS; +  struct symbol *sym; + +  for (sym = symtab[h]; sym ; sym = sym->hash_next) +    if (map_to_ns(sym->type) == map_to_ns(type) +	&& strcmp(name, sym->name) == 0) +      { +	if (!equal_list(sym->defn, defn)) +	  error_with_pos("redefinition of %s", name); +	return sym; +      } + +  sym = xmalloc(sizeof(*sym)); +  sym->name = name; +  sym->type = type; +  sym->defn = defn; +  sym->expansion_trail = NULL; +  sym->is_extern = is_extern; + +  sym->hash_next = symtab[h]; +  symtab[h] = sym; + +  if (flag_debug) +    { +      fprintf(debugfile, "Defn for %s %s == <", symbol_type_name[type],  name); +      if (is_extern) +        fputs("extern ", debugfile); +      print_list(debugfile, defn); +      fputs(">\n", debugfile); +    } + +  ++nsyms; +  return sym; +} + + +/*----------------------------------------------------------------------*/ + +inline void +free_node(struct string_list *node) +{ +  free(node->string); +  free(node); +} + +void +free_list(struct string_list *s, struct string_list *e) +{ +  while (s != e) +    { +      struct string_list *next = s->next; +      free_node(s); +      s = next; +    } +} + +inline struct string_list * +copy_node(struct string_list *node) +{ +  struct string_list *newnode; + +  newnode = xmalloc(sizeof(*newnode)); +  newnode->string = xstrdup(node->string); +  newnode->tag = node->tag; + +  return newnode; +} + +struct string_list * +copy_list(struct string_list *s, struct string_list *e) +{ +  struct string_list *h, *p; + +  if (s == e) +    return NULL; + +  p = h = copy_node(s); +  while ((s = s->next) != e) +    p = p->next = copy_node(s); +  p->next = NULL; + +  return h; +} + +int +equal_list(struct string_list *a, struct string_list *b) +{ +  while (a && b) +    { +      if (a->tag != b->tag || strcmp(a->string, b->string)) +	return 0; +      a = a->next; +      b = b->next; +    } + +  return !a && !b; +} + +static inline void +print_node(FILE *f, struct string_list *list) +{ +  switch (list->tag) +    { +    case SYM_STRUCT: +      putc('s', f); +      goto printit; +    case SYM_UNION: +      putc('u', f); +      goto printit; +    case SYM_ENUM: +      putc('e', f); +      goto printit; +    case SYM_TYPEDEF: +      putc('t', f); +      goto printit; + +    printit: +      putc('#', f); +    case SYM_NORMAL: +      fputs(list->string, f); +      break; +    } +} + +void +print_list(FILE *f, struct string_list *list) +{ +  struct string_list **e, **b; +  struct string_list *tmp, **tmp2; +  int elem = 1; + +  if (list == NULL) +    { +      fputs("(nil)", f); +      return; +    } + +  tmp = list; +  while((tmp = tmp->next) != NULL) +	  elem++; + +  b = alloca(elem * sizeof(*e)); +  e = b + elem; +  tmp2 = e - 1; + +  (*tmp2--) = list; +  while((list = list->next) != NULL) +	  *(tmp2--) = list; + +  while (b != e) +    { +      print_node(f, *b++); +      putc(' ', f); +    } +} + +static unsigned long +expand_and_crc_list(struct string_list *list, unsigned long crc) +{ +  struct string_list **e, **b; +  struct string_list *tmp, **tmp2; +  int elem = 1; + +  if (!list) +    return crc; + +  tmp = list; +  while((tmp = tmp->next) != NULL) +	  elem++; + +  b = alloca(elem * sizeof(*e)); +  e = b + elem; +  tmp2 = e - 1; + +  *(tmp2--) = list; +  while ((list = list->next) != NULL) +    *(tmp2--) = list; + +  while (b != e) +    { +      struct string_list *cur; +      struct symbol *subsym; + +      cur = *(b++); +      switch (cur->tag) +	{ +	case SYM_NORMAL: +	  if (flag_dump_defs) +	    fprintf(debugfile, "%s ", cur->string); +	  crc = partial_crc32(cur->string, crc); +	  crc = partial_crc32_one(' ', crc); +	  break; + +	case SYM_TYPEDEF: +	  subsym = find_symbol(cur->string, cur->tag); +	  if (subsym->expansion_trail) +	    { +	      if (flag_dump_defs) +		fprintf(debugfile, "%s ", cur->string); +	      crc = partial_crc32(cur->string, crc); +	      crc = partial_crc32_one(' ', crc); +	    } +	  else +	    { +	      subsym->expansion_trail = expansion_trail; +	      expansion_trail = subsym; +	      crc = expand_and_crc_list(subsym->defn, crc); +	    } +	  break; + +	case SYM_STRUCT: +	case SYM_UNION: +	case SYM_ENUM: +	  subsym = find_symbol(cur->string, cur->tag); +	  if (!subsym) +	    { +	      struct string_list *n, *t = NULL; + +	      error_with_pos("expand undefined %s %s", +			     symbol_type_name[cur->tag], cur->string); + +	      n = xmalloc(sizeof(*n)); +	      n->string = xstrdup(symbol_type_name[cur->tag]); +	      n->tag = SYM_NORMAL; +	      n->next = t; +	      t = n; + +	      n = xmalloc(sizeof(*n)); +	      n->string = xstrdup(cur->string); +	      n->tag = SYM_NORMAL; +	      n->next = t; +	      t = n; + +	      n = xmalloc(sizeof(*n)); +	      n->string = xstrdup("{ UNKNOWN }"); +	      n->tag = SYM_NORMAL; +	      n->next = t; + +	      subsym = add_symbol(cur->string, cur->tag, n, 0); +	    } +	  if (subsym->expansion_trail) +	    { +	      if (flag_dump_defs) +		{ +		  fprintf(debugfile, "%s %s ", symbol_type_name[cur->tag], +			  cur->string); +		} + +	      crc = partial_crc32(symbol_type_name[cur->tag], crc); +	      crc = partial_crc32_one(' ', crc); +	      crc = partial_crc32(cur->string, crc); +	      crc = partial_crc32_one(' ', crc); +	    } +	  else +	    { +	      subsym->expansion_trail = expansion_trail; +	      expansion_trail = subsym; +	      crc = expand_and_crc_list(subsym->defn, crc); +	    } +	  break; +	} +    } + +  return crc; +} + +void +export_symbol(const char *name) +{ +  struct symbol *sym; + +  sym = find_symbol(name, SYM_NORMAL); +  if (!sym) +    error_with_pos("export undefined symbol %s", name); +  else +    { +      unsigned long crc; + +      if (flag_dump_defs) +	fprintf(debugfile, "Export %s == <", name); + +      expansion_trail = (struct symbol *)-1L; + +      crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff; + +      sym = expansion_trail; +      while (sym != (struct symbol *)-1L) +	{ +	  struct symbol *n = sym->expansion_trail; +	  sym->expansion_trail = 0; +	  sym = n; +	} + +      if (flag_dump_defs) +	fputs(">\n", debugfile); + +      /* Used as a linker script. */ +      printf("__crc_%s = 0x%08lx ;\n", name, crc); +    } +} + +/*----------------------------------------------------------------------*/ + +void +error(const char *fmt, ...) +{ +  va_list args; + +  if (flag_warnings) +    { +      va_start(args, fmt); +      vfprintf(stderr, fmt, args); +      va_end(args); +      putc('\n', stderr); + +      errors++; +    } +} + +void +error_with_pos(const char *fmt, ...) +{ +  va_list args; + +  if (flag_warnings) +    { +      fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line); + +      va_start(args, fmt); +      vfprintf(stderr, fmt, args); +      va_end(args); +      putc('\n', stderr); + +      errors++; +    } +} + + +void genksyms_usage(void) +{ +	fputs("Usage:\n" +	      "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" +	      "\n" +#ifdef __GNU_LIBRARY__ +	      "  -d, --debug           Increment the debug level (repeatable)\n" +	      "  -D, --dump            Dump expanded symbol defs (for debugging only)\n" +	      "  -w, --warnings        Enable warnings\n" +	      "  -q, --quiet           Disable warnings (default)\n" +	      "  -h, --help            Print this message\n" +	      "  -V, --version         Print the release version\n" +#else  /* __GNU_LIBRARY__ */ +             "  -d                    Increment the debug level (repeatable)\n" +             "  -D                    Dump expanded symbol defs (for debugging only)\n" +             "  -w                    Enable warnings\n" +             "  -q                    Disable warnings (default)\n" +             "  -h                    Print this message\n" +             "  -V                    Print the release version\n" +#endif /* __GNU_LIBRARY__ */ +	      , stderr); +} + +int +main(int argc, char **argv) +{ +  int o; + +#ifdef __GNU_LIBRARY__ +  struct option long_opts[] = { +    {"debug", 0, 0, 'd'}, +    {"warnings", 0, 0, 'w'}, +    {"quiet", 0, 0, 'q'}, +    {"dump", 0, 0, 'D'}, +    {"version", 0, 0, 'V'}, +    {"help", 0, 0, 'h'}, +    {0, 0, 0, 0} +  }; + +  while ((o = getopt_long(argc, argv, "dwqVDk:p:", +			  &long_opts[0], NULL)) != EOF) +#else  /* __GNU_LIBRARY__ */ +  while ((o = getopt(argc, argv, "dwqVDk:p:")) != EOF) +#endif /* __GNU_LIBRARY__ */ +    switch (o) +      { +      case 'd': +	flag_debug++; +	break; +      case 'w': +	flag_warnings = 1; +	break; +      case 'q': +	flag_warnings = 0; +	break; +      case 'V': +	fputs("genksyms version 2.5.60\n", stderr); +	break; +      case 'D': +	flag_dump_defs = 1; +	break; +      case 'h': +	genksyms_usage(); +	return 0; +      default: +	genksyms_usage(); +	return 1; +      } + +    { +      extern int yydebug; +      extern int yy_flex_debug; + +      yydebug = (flag_debug > 1); +      yy_flex_debug = (flag_debug > 2); + +      debugfile = stderr; +      /* setlinebuf(debugfile); */ +    } + +  yyparse(); + +  if (flag_debug) +    { +      fprintf(debugfile, "Hash table occupancy %d/%d = %g\n", +	      nsyms, HASH_BUCKETS, (double)nsyms / (double)HASH_BUCKETS); +    } + +  return errors != 0; +} diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h new file mode 100644 index 000000000000..f09af47ab281 --- /dev/null +++ b/scripts/genksyms/genksyms.h @@ -0,0 +1,104 @@ +/* Generate kernel symbol version hashes. +   Copyright 1996, 1997 Linux International. + +   New implementation contributed by Richard Henderson <rth@tamu.edu> +   Based on original work by Bjorn Ekwall <bj0rn@blox.se> + +   This file is part of the Linux modutils. + +   This program is free software; you can redistribute it and/or modify it +   under the terms of the GNU General Public License as published by the +   Free Software Foundation; either version 2 of the License, or (at your +   option) any later version. + +   This program is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software Foundation, +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ + + +#ifndef MODUTILS_GENKSYMS_H +#define MODUTILS_GENKSYMS_H 1 + +#include <stdio.h> + + +enum symbol_type +{ +  SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION +}; + +struct string_list +{ +  struct string_list *next; +  enum symbol_type tag; +  char *string; +}; + +struct symbol +{ +  struct symbol *hash_next; +  const char *name; +  enum symbol_type type; +  struct string_list *defn; +  struct symbol *expansion_trail; +  int is_extern; +}; + +typedef struct string_list **yystype; +#define YYSTYPE yystype + +extern FILE *outfile, *debugfile; + +extern int cur_line; +extern char *cur_filename, *output_directory; + +extern int flag_debug, flag_dump_defs, flag_warnings; +extern int checksum_version, kernel_version; + +extern int want_brace_phrase, want_exp_phrase, discard_phrase_contents; +extern struct string_list *current_list, *next_list; + + +struct symbol *find_symbol(const char *name, enum symbol_type ns); +struct symbol *add_symbol(const char *name, enum symbol_type type, +			   struct string_list *defn, int is_extern); +void export_symbol(const char *); + +struct string_list *reset_list(void); +void free_list(struct string_list *s, struct string_list *e); +void free_node(struct string_list *list); +struct string_list *copy_node(struct string_list *); +struct string_list *copy_list(struct string_list *s, struct string_list *e); +int equal_list(struct string_list *a, struct string_list *b); +void print_list(FILE *, struct string_list *list); + +int yylex(void); +int yyparse(void); + +void error_with_pos(const char *, ...); + +#define version(a,b,c)  ((a << 16) | (b << 8) | (c)) + +/*----------------------------------------------------------------------*/ + +#define MODUTILS_VERSION "<in-kernel>" + +#define xmalloc(size) ({ void *__ptr = malloc(size);		\ +	if(!__ptr && size != 0) {				\ +		fprintf(stderr, "out of memory\n");		\ +		exit(1);					\ +	}							\ +	__ptr; }) +#define xstrdup(str)  ({ char *__str = strdup(str);		\ +	if (!__str) {						\ +		fprintf(stderr, "out of memory\n");		\ +		exit(1);					\ +	}							\ +	__str; }) + +#endif /* genksyms.h */ diff --git a/scripts/genksyms/keywords.c_shipped b/scripts/genksyms/keywords.c_shipped new file mode 100644 index 000000000000..eabaf7401cd6 --- /dev/null +++ b/scripts/genksyms/keywords.c_shipped @@ -0,0 +1,145 @@ +/* ANSI-C code produced by gperf version 2.7.2 */ +/* Command-line: gperf -L ANSI-C -a -C -E -g -H is_reserved_hash -k '1,3,$' -N is_reserved_word -p -t scripts/genksyms/keywords.gperf  */ +struct resword { const char *name; int token; }; +/* maximum key range = 109, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +is_reserved_hash (register const char *str, register unsigned int len) +{ +  static const unsigned char asso_values[] = +    { +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113,   5, +      113, 113, 113, 113, 113, 113,   0, 113, 113, 113, +        0, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113,   0, 113,   0, 113,  20, +       25,   0,  35,  30, 113,  20, 113, 113,  40,  30, +       30,   0,   0, 113,   0,  51,   0,  15,   5, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113, 113, 113, 113, 113, +      113, 113, 113, 113, 113, 113 +    }; +  return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]]; +} + +#ifdef __GNUC__ +__inline +#endif +const struct resword * +is_reserved_word (register const char *str, register unsigned int len) +{ +  enum +    { +      TOTAL_KEYWORDS = 41, +      MIN_WORD_LENGTH = 3, +      MAX_WORD_LENGTH = 17, +      MIN_HASH_VALUE = 4, +      MAX_HASH_VALUE = 112 +    }; + +  static const struct resword wordlist[] = +    { +      {""}, {""}, {""}, {""}, +      {"auto", AUTO_KEYW}, +      {""}, {""}, +      {"__asm__", ASM_KEYW}, +      {""}, +      {"_restrict", RESTRICT_KEYW}, +      {"__typeof__", TYPEOF_KEYW}, +      {"__attribute", ATTRIBUTE_KEYW}, +      {"__restrict__", RESTRICT_KEYW}, +      {"__attribute__", ATTRIBUTE_KEYW}, +      {""}, +      {"__volatile", VOLATILE_KEYW}, +      {""}, +      {"__volatile__", VOLATILE_KEYW}, +      {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW}, +      {""}, {""}, {""}, +      {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW}, +      {"int", INT_KEYW}, +      {"char", CHAR_KEYW}, +      {""}, {""}, +      {"__const", CONST_KEYW}, +      {"__inline", INLINE_KEYW}, +      {"__const__", CONST_KEYW}, +      {"__inline__", INLINE_KEYW}, +      {""}, {""}, {""}, {""}, +      {"__asm", ASM_KEYW}, +      {"extern", EXTERN_KEYW}, +      {""}, +      {"register", REGISTER_KEYW}, +      {""}, +      {"float", FLOAT_KEYW}, +      {"typeof", TYPEOF_KEYW}, +      {"typedef", TYPEDEF_KEYW}, +      {""}, {""}, +      {"_Bool", BOOL_KEYW}, +      {"double", DOUBLE_KEYW}, +      {""}, {""}, +      {"enum", ENUM_KEYW}, +      {""}, {""}, {""}, +      {"volatile", VOLATILE_KEYW}, +      {"void", VOID_KEYW}, +      {"const", CONST_KEYW}, +      {"short", SHORT_KEYW}, +      {"struct", STRUCT_KEYW}, +      {""}, +      {"restrict", RESTRICT_KEYW}, +      {""}, +      {"__signed__", SIGNED_KEYW}, +      {""}, +      {"asm", ASM_KEYW}, +      {""}, {""}, +      {"inline", INLINE_KEYW}, +      {""}, {""}, {""}, +      {"union", UNION_KEYW}, +      {""}, {""}, {""}, {""}, {""}, {""}, +      {"static", STATIC_KEYW}, +      {""}, {""}, {""}, {""}, {""}, {""}, +      {"__signed", SIGNED_KEYW}, +      {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +      {""}, {""}, {""}, {""}, {""}, +      {"unsigned", UNSIGNED_KEYW}, +      {""}, {""}, {""}, {""}, +      {"long", LONG_KEYW}, +      {""}, {""}, {""}, {""}, {""}, {""}, {""}, +      {"signed", SIGNED_KEYW} +    }; + +  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) +    { +      register int key = is_reserved_hash (str, len); + +      if (key <= MAX_HASH_VALUE && key >= 0) +        { +          register const char *s = wordlist[key].name; + +          if (*str == *s && !strcmp (str + 1, s + 1)) +            return &wordlist[key]; +        } +    } +  return 0; +} diff --git a/scripts/genksyms/keywords.gperf b/scripts/genksyms/keywords.gperf new file mode 100644 index 000000000000..b6bec765996e --- /dev/null +++ b/scripts/genksyms/keywords.gperf @@ -0,0 +1,50 @@ +%{ +%} +struct resword { const char *name; int token; } +%% +EXPORT_SYMBOL, EXPORT_SYMBOL_KEYW +EXPORT_SYMBOL_GPL, EXPORT_SYMBOL_KEYW +__asm, ASM_KEYW +__asm__, ASM_KEYW +__attribute, ATTRIBUTE_KEYW +__attribute__, ATTRIBUTE_KEYW +__const, CONST_KEYW +__const__, CONST_KEYW +__inline, INLINE_KEYW +__inline__, INLINE_KEYW +__signed, SIGNED_KEYW +__signed__, SIGNED_KEYW +__volatile, VOLATILE_KEYW +__volatile__, VOLATILE_KEYW +# According to rth, c99 defines _Bool, __restrict, __restrict__, restrict.  KAO +_Bool, BOOL_KEYW +_restrict, RESTRICT_KEYW +__restrict__, RESTRICT_KEYW +restrict, RESTRICT_KEYW +asm, ASM_KEYW +# attribute commented out in modutils 2.4.2.  People are using 'attribute' as a +# field name which breaks the genksyms parser.  It is not a gcc keyword anyway. +# KAO. +#   attribute, ATTRIBUTE_KEYW +auto, AUTO_KEYW +char, CHAR_KEYW +const, CONST_KEYW +double, DOUBLE_KEYW +enum, ENUM_KEYW +extern, EXTERN_KEYW +float, FLOAT_KEYW +inline, INLINE_KEYW +int, INT_KEYW +long, LONG_KEYW +register, REGISTER_KEYW +short, SHORT_KEYW +signed, SIGNED_KEYW +static, STATIC_KEYW +struct, STRUCT_KEYW +typedef, TYPEDEF_KEYW +union, UNION_KEYW +unsigned, UNSIGNED_KEYW +void, VOID_KEYW +volatile, VOLATILE_KEYW +typeof, TYPEOF_KEYW +__typeof__, TYPEOF_KEYW diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped new file mode 100644 index 000000000000..d9bfbb5948f2 --- /dev/null +++ b/scripts/genksyms/lex.c_shipped @@ -0,0 +1,2084 @@ +#line 2 "scripts/genksyms/lex.c" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> +#include <unistd.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else	/* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif	/* __STDC__ */ +#endif	/* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index.  If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition.  This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state.  The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator).  This + * avoids problems with code like: + * + * 	if ( condition_holds ) + *		yyless( 5 ); + *	else + *		do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ +	do \ +		{ \ +		/* Undo effects of setting up yytext. */ \ +		*yy_cp = yy_hold_char; \ +		YY_RESTORE_YY_MORE_OFFSET \ +		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ +		YY_DO_BEFORE_ACTION; /* set up yytext again */ \ +		} \ +	while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state +	{ +	FILE *yy_input_file; + +	char *yy_ch_buf;		/* input buffer */ +	char *yy_buf_pos;		/* current position in input buffer */ + +	/* Size of input buffer in bytes, not including room for EOB +	 * characters. +	 */ +	yy_size_t yy_buf_size; + +	/* Number of characters read into yy_ch_buf, not including EOB +	 * characters. +	 */ +	int yy_n_chars; + +	/* Whether we "own" the buffer - i.e., we know we created it, +	 * and can realloc() it to grow it, and should free() it to +	 * delete it. +	 */ +	int yy_is_our_buffer; + +	/* Whether this is an "interactive" input source; if so, and +	 * if we're using stdio for input, then we want to use getc() +	 * instead of fread(), to make sure we stop fetching input after +	 * each newline. +	 */ +	int yy_is_interactive; + +	/* Whether we're considered to be at the beginning of a line. +	 * If so, '^' rules will be active on the next match, otherwise +	 * not. +	 */ +	int yy_at_bol; + +	/* Whether to try to fill the input buffer when we reach the +	 * end of it. +	 */ +	int yy_fill_buffer; + +	int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 +	/* When an EOF's been seen but there's still some text to process +	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we +	 * shouldn't try reading from the input source any more.  We might +	 * still have a bunch of tokens to match, though, because of +	 * possible backing-up. +	 * +	 * When we actually see the EOF, we change the status to "new" +	 * (via yyrestart()), so that the user can continue scanning by +	 * just pointing yyin at a new input file. +	 */ +#define YY_BUFFER_EOF_PENDING 2 +	}; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars;		/* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1;		/* whether we need to initialize */ +static int yy_start = 0;	/* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin.  A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ +	{ \ +	if ( ! yy_current_buffer ) \ +		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ +	yy_current_buffer->yy_is_interactive = is_interactive; \ +	} + +#define yy_set_bol(at_bol) \ +	{ \ +	if ( ! yy_current_buffer ) \ +		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ +	yy_current_buffer->yy_at_bol = at_bol; \ +	} + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define yywrap() 1 +#define YY_SKIP_YYWRAP + +#define FLEX_DEBUG +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; + +#define FLEX_DEBUG +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ +	yytext_ptr = yy_bp; \ +	yyleng = (int) (yy_cp - yy_bp); \ +	yy_hold_char = *yy_cp; \ +	*yy_cp = '\0'; \ +	yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 13 +#define YY_END_OF_BUFFER 14 +static yyconst short int yy_accept[76] = +    {   0, +        0,    0,    0,    0,   14,   12,    4,    3,   12,    7, +       12,   12,    7,   12,   12,   12,   12,   12,    9,    9, +       12,   12,   12,    4,    0,    5,    0,    7,    0,    6, +        0,    0,    0,    0,    0,    0,    2,    8,   10,   10, +        9,    0,    0,    9,    9,    0,    9,    0,    0,   11, +        0,    0,    0,   10,    0,   10,    9,    9,    0,    0, +        0,    0,    0,    0,    0,   10,   10,    0,    0,    0, +        0,    0,    0,    1,    0 +    } ; + +static yyconst int yy_ec[256] = +    {   0, +        1,    1,    1,    1,    1,    1,    1,    1,    2,    3, +        4,    4,    4,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    2,    1,    5,    6,    7,    8,    9,   10,    1, +        1,    8,   11,    1,   12,   13,    8,   14,   15,   15, +       15,   15,   15,   15,   15,   16,   16,    1,    1,   17, +       18,   19,    1,    1,   20,   20,   20,   20,   21,   22, +        7,    7,    7,    7,    7,   23,    7,    7,    7,    7, +        7,    7,    7,    7,   24,    7,    7,   25,    7,    7, +        1,   26,    1,    8,    7,    1,   20,   20,   20,   20, + +       21,   22,    7,    7,    7,    7,    7,   27,    7,    7, +        7,    7,    7,    7,    7,    7,   24,    7,    7,   25, +        7,    7,    1,   28,    1,    8,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, + +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1 +    } ; + +static yyconst int yy_meta[29] = +    {   0, +        1,    1,    2,    1,    1,    1,    3,    1,    1,    1, +        4,    4,    5,    6,    6,    6,    1,    1,    1,    7, +        8,    7,    3,    3,    3,    1,    3,    1 +    } ; + +static yyconst short int yy_base[88] = +    {   0, +        0,  147,   21,  140,  145,  284,   39,  284,   26,    0, +       32,  126,   40,   44,  115,   35,   36,   46,   50,   53, +       39,   61,   54,   79,   65,  284,    0,    0,   66,  284, +        0,  119,   79,   75,  123,  104,  284,  284,  107,    0, +       79,   73,   76,   76,   66,    0,    0,   85,   86,  284, +      133,   83,   91,  284,   99,  147,  284,  114,  122,   70, +      107,  141,  172,  151,  135,  181,  284,  137,  114,  157, +      149,   48,   45,  284,  284,  208,  214,  222,  230,  238, +      246,  250,  255,  256,  261,  267,  275 +    } ; + +static yyconst short int yy_def[88] = +    {   0, +       75,    1,    1,    3,   75,   75,   75,   75,   76,   77, +       78,   75,   77,   79,   75,   75,   75,   75,   75,   19, +       75,   75,   75,   75,   76,   75,   80,   77,   78,   75, +       81,   75,   76,   78,   79,   79,   75,   75,   75,   39, +       19,   82,   83,   75,   75,   84,   20,   76,   78,   75, +       79,   51,   85,   75,   75,   75,   75,   84,   79,   51, +       79,   79,   79,   51,   75,   75,   75,   86,   79,   63, +       86,   87,   87,   75,    0,   75,   75,   75,   75,   75, +       75,   75,   75,   75,   75,   75,   75 +    } ; + +static yyconst short int yy_nxt[313] = +    {   0, +        6,    7,    8,    7,    9,    6,   10,    6,    6,   11, +        6,    6,   12,    6,    6,    6,    6,    6,    6,   10, +       10,   10,   13,   10,   10,    6,   10,    6,   15,   16, +       26,   15,   17,   18,   19,   20,   20,   21,   15,   22, +       24,   30,   24,   38,   33,   36,   37,   74,   23,   34, +       74,   27,   38,   38,   38,   38,   38,   31,   32,   39, +       39,   39,   40,   41,   41,   42,   47,   47,   47,   26, +       43,   38,   44,   45,   46,   30,   44,   75,   38,   38, +       24,   38,   24,   26,   30,   40,   55,   55,   57,   26, +       27,   31,   57,   43,   35,   30,   64,   64,   64,   57, + +       31,   65,   65,   75,   27,   36,   37,   35,   59,   37, +       27,   31,   56,   56,   56,   59,   37,   51,   52,   52, +       39,   39,   39,   59,   37,   37,   68,   53,   54,   54, +       69,   50,   38,   54,   59,   37,   44,   45,   32,   37, +       44,   35,   59,   37,   75,   14,   60,   60,   66,   66, +       66,   37,   14,   72,   75,   61,   62,   63,   59,   61, +       56,   56,   56,   69,   64,   64,   64,   69,   67,   67, +       75,   75,   75,   67,   37,   35,   75,   75,   75,   61, +       62,   75,   75,   61,   75,   70,   70,   70,   75,   75, +       75,   70,   70,   70,   66,   66,   66,   75,   75,   75, + +       75,   75,   54,   54,   75,   75,   75,   54,   25,   25, +       25,   25,   25,   25,   25,   25,   28,   75,   75,   28, +       28,   28,   29,   29,   29,   29,   29,   29,   29,   29, +       35,   35,   35,   35,   35,   35,   35,   35,   48,   75, +       48,   48,   48,   48,   48,   48,   49,   75,   49,   49, +       49,   49,   49,   49,   42,   42,   75,   42,   56,   75, +       56,   58,   58,   58,   66,   75,   66,   71,   71,   71, +       71,   71,   71,   71,   71,   73,   73,   73,   73,   73, +       73,   73,   73,    5,   75,   75,   75,   75,   75,   75, +       75,   75,   75,   75,   75,   75,   75,   75,   75,   75, + +       75,   75,   75,   75,   75,   75,   75,   75,   75,   75, +       75,   75 +    } ; + +static yyconst short int yy_chk[313] = +    {   0, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    3,    3, +        9,    3,    3,    3,    3,    3,    3,    3,    3,    3, +        7,   11,    7,   16,   13,   14,   14,   73,    3,   13, +       72,    9,   16,   17,   17,   21,   21,   11,   18,   18, +       18,   18,   19,   19,   19,   19,   20,   20,   20,   25, +       19,   23,   19,   19,   19,   29,   19,   20,   22,   22, +       24,   23,   24,   33,   34,   42,   43,   43,   45,   48, +       25,   29,   45,   42,   60,   49,   52,   52,   52,   44, + +       34,   53,   53,   41,   33,   36,   36,   52,   61,   61, +       48,   49,   55,   55,   55,   69,   69,   36,   36,   36, +       39,   39,   39,   59,   59,   35,   59,   39,   39,   39, +       61,   32,   15,   39,   51,   51,   58,   58,   12,   68, +       58,   68,   62,   62,    5,    4,   51,   51,   65,   65, +       65,   71,    2,   71,    0,   51,   51,   51,   70,   51, +       56,   56,   56,   62,   64,   64,   64,   62,   56,   56, +        0,    0,    0,   56,   63,   64,    0,    0,    0,   70, +       70,    0,    0,   70,    0,   63,   63,   63,    0,    0, +        0,   63,   63,   63,   66,   66,   66,    0,    0,    0, + +        0,    0,   66,   66,    0,    0,    0,   66,   76,   76, +       76,   76,   76,   76,   76,   76,   77,    0,    0,   77, +       77,   77,   78,   78,   78,   78,   78,   78,   78,   78, +       79,   79,   79,   79,   79,   79,   79,   79,   80,    0, +       80,   80,   80,   80,   80,   80,   81,    0,   81,   81, +       81,   81,   81,   81,   82,   82,    0,   82,   83,    0, +       83,   84,   84,   84,   85,    0,   85,   86,   86,   86, +       86,   86,   86,   86,   86,   87,   87,   87,   87,   87, +       87,   87,   87,   75,   75,   75,   75,   75,   75,   75, +       75,   75,   75,   75,   75,   75,   75,   75,   75,   75, + +       75,   75,   75,   75,   75,   75,   75,   75,   75,   75, +       75,   75 +    } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 1; + +static yyconst short int yy_rule_linenum[13] = +    {   0, +       69,   70,   71,   74,   77,   78,   79,   85,   86,   87, +       89,   92 +    } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "scripts/genksyms/lex.l" +#define INITIAL 0 +/* Lexical analysis for genksyms. +   Copyright 1996, 1997 Linux International. + +   New implementation contributed by Richard Henderson <rth@tamu.edu> +   Based on original work by Bjorn Ekwall <bj0rn@blox.se> + +   Taken from Linux modutils 2.4.22. + +   This program is free software; you can redistribute it and/or modify it +   under the terms of the GNU General Public License as published by the +   Free Software Foundation; either version 2 of the License, or (at your +   option) any later version. + +   This program is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software Foundation, +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ +#line 25 "scripts/genksyms/lex.l" + +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "genksyms.h" +#include "parse.h" + +/* We've got a two-level lexer here.  We let flex do basic tokenization +   and then we categorize those basic tokens in the second stage.  */ +#define YY_DECL		static int yylex1(void) + +/* Version 2 checksumming does proper tokenization; version 1 wasn't +   quite so pedantic.  */ +#define V2_TOKENS 1 + +/* We don't do multiple input files.  */ +#line 513 "scripts/genksyms/lex.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines.  This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +	if ( yy_current_buffer->yy_is_interactive ) \ +		{ \ +		int c = '*', n; \ +		for ( n = 0; n < max_size && \ +			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ +			buf[n] = (char) c; \ +		if ( c == '\n' ) \ +			buf[n++] = (char) c; \ +		if ( c == EOF && ferror( yyin ) ) \ +			YY_FATAL_ERROR( "input in flex scanner failed" ); \ +		result = n; \ +		} \ +	else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ +		  && ferror( yyin ) ) \ +		YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ +	if ( yyleng > 0 ) \ +		yy_current_buffer->yy_at_bol = \ +				(yytext[yyleng - 1] == '\n'); \ +	YY_USER_ACTION + +YY_DECL +	{ +	register yy_state_type yy_current_state; +	register char *yy_cp = NULL, *yy_bp = NULL; +	register int yy_act; + +#line 65 "scripts/genksyms/lex.l" + + + + /* Keep track of our location in the original source files.  */ +#line 672 "scripts/genksyms/lex.c" + +	if ( yy_init ) +		{ +		yy_init = 0; + +#ifdef YY_USER_INIT +		YY_USER_INIT; +#endif + +		if ( ! yy_start ) +			yy_start = 1;	/* first start state */ + +		if ( ! yyin ) +			yyin = stdin; + +		if ( ! yyout ) +			yyout = stdout; + +		if ( ! yy_current_buffer ) +			yy_current_buffer = +				yy_create_buffer( yyin, YY_BUF_SIZE ); + +		yy_load_buffer_state(); +		} + +	while ( 1 )		/* loops until end-of-file is reached */ +		{ +		yy_cp = yy_c_buf_p; + +		/* Support of yytext. */ +		*yy_cp = yy_hold_char; + +		/* yy_bp points to the position in yy_ch_buf of the start of +		 * the current run. +		 */ +		yy_bp = yy_cp; + +		yy_current_state = yy_start; +		yy_current_state += YY_AT_BOL(); +yy_match: +		do +			{ +			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; +			if ( yy_accept[yy_current_state] ) +				{ +				yy_last_accepting_state = yy_current_state; +				yy_last_accepting_cpos = yy_cp; +				} +			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) +				{ +				yy_current_state = (int) yy_def[yy_current_state]; +				if ( yy_current_state >= 76 ) +					yy_c = yy_meta[(unsigned int) yy_c]; +				} +			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; +			++yy_cp; +			} +		while ( yy_base[yy_current_state] != 284 ); + +yy_find_action: +		yy_act = yy_accept[yy_current_state]; +		if ( yy_act == 0 ) +			{ /* have to back up */ +			yy_cp = yy_last_accepting_cpos; +			yy_current_state = yy_last_accepting_state; +			yy_act = yy_accept[yy_current_state]; +			} + +		YY_DO_BEFORE_ACTION; + + +do_action:	/* This label is used only to access EOF actions. */ + +		if ( yy_flex_debug ) +			{ +			if ( yy_act == 0 ) +				fprintf( stderr, "--scanner backing up\n" ); +			else if ( yy_act < 13 ) +				fprintf( stderr, "--accepting rule at line %d (\"%s\")\n", +				         yy_rule_linenum[yy_act], yytext ); +			else if ( yy_act == 13 ) +				fprintf( stderr, "--accepting default rule (\"%s\")\n", +				         yytext ); +			else if ( yy_act == 14 ) +				fprintf( stderr, "--(end of buffer or a NUL)\n" ); +			else +				fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); +			} + +		switch ( yy_act ) +	{ /* beginning of action switch */ +			case 0: /* must back up */ +			/* undo the effects of YY_DO_BEFORE_ACTION */ +			*yy_cp = yy_hold_char; +			yy_cp = yy_last_accepting_cpos; +			yy_current_state = yy_last_accepting_state; +			goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 69 "scripts/genksyms/lex.l" +return FILENAME; +	YY_BREAK +case 2: +YY_RULE_SETUP +#line 70 "scripts/genksyms/lex.l" +cur_line++; +	YY_BREAK +case 3: +YY_RULE_SETUP +#line 71 "scripts/genksyms/lex.l" +cur_line++; +	YY_BREAK +/* Ignore all other whitespace.  */ +case 4: +YY_RULE_SETUP +#line 74 "scripts/genksyms/lex.l" +; +	YY_BREAK +case 5: +YY_RULE_SETUP +#line 77 "scripts/genksyms/lex.l" +return STRING; +	YY_BREAK +case 6: +YY_RULE_SETUP +#line 78 "scripts/genksyms/lex.l" +return CHAR; +	YY_BREAK +case 7: +YY_RULE_SETUP +#line 79 "scripts/genksyms/lex.l" +return IDENT; +	YY_BREAK +/* The Pedant requires that the other C multi-character tokens be +    recognized as tokens.  We don't actually use them since we don't +    parse expressions, but we do want whitespace to be arranged +    around them properly.  */ +case 8: +YY_RULE_SETUP +#line 85 "scripts/genksyms/lex.l" +return OTHER; +	YY_BREAK +case 9: +YY_RULE_SETUP +#line 86 "scripts/genksyms/lex.l" +return INT; +	YY_BREAK +case 10: +YY_RULE_SETUP +#line 87 "scripts/genksyms/lex.l" +return REAL; +	YY_BREAK +case 11: +YY_RULE_SETUP +#line 89 "scripts/genksyms/lex.l" +return DOTS; +	YY_BREAK +/* All other tokens are single characters.  */ +case 12: +YY_RULE_SETUP +#line 92 "scripts/genksyms/lex.l" +return yytext[0]; +	YY_BREAK +case 13: +YY_RULE_SETUP +#line 95 "scripts/genksyms/lex.l" +ECHO; +	YY_BREAK +#line 842 "scripts/genksyms/lex.c" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(V2_TOKENS): +	yyterminate(); + +	case YY_END_OF_BUFFER: +		{ +		/* Amount of text matched not including the EOB char. */ +		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + +		/* Undo the effects of YY_DO_BEFORE_ACTION. */ +		*yy_cp = yy_hold_char; +		YY_RESTORE_YY_MORE_OFFSET + +		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) +			{ +			/* We're scanning a new file or input source.  It's +			 * possible that this happened because the user +			 * just pointed yyin at a new source and called +			 * yylex().  If so, then we have to assure +			 * consistency between yy_current_buffer and our +			 * globals.  Here is the right place to do so, because +			 * this is the first action (other than possibly a +			 * back-up) that will match for the new input source. +			 */ +			yy_n_chars = yy_current_buffer->yy_n_chars; +			yy_current_buffer->yy_input_file = yyin; +			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; +			} + +		/* Note that here we test for yy_c_buf_p "<=" to the position +		 * of the first EOB in the buffer, since yy_c_buf_p will +		 * already have been incremented past the NUL character +		 * (since all states make transitions on EOB to the +		 * end-of-buffer state).  Contrast this with the test +		 * in input(). +		 */ +		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) +			{ /* This was really a NUL. */ +			yy_state_type yy_next_state; + +			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + +			yy_current_state = yy_get_previous_state(); + +			/* Okay, we're now positioned to make the NUL +			 * transition.  We couldn't have +			 * yy_get_previous_state() go ahead and do it +			 * for us because it doesn't know how to deal +			 * with the possibility of jamming (and we don't +			 * want to build jamming into it because then it +			 * will run more slowly). +			 */ + +			yy_next_state = yy_try_NUL_trans( yy_current_state ); + +			yy_bp = yytext_ptr + YY_MORE_ADJ; + +			if ( yy_next_state ) +				{ +				/* Consume the NUL. */ +				yy_cp = ++yy_c_buf_p; +				yy_current_state = yy_next_state; +				goto yy_match; +				} + +			else +				{ +				yy_cp = yy_c_buf_p; +				goto yy_find_action; +				} +			} + +		else switch ( yy_get_next_buffer() ) +			{ +			case EOB_ACT_END_OF_FILE: +				{ +				yy_did_buffer_switch_on_eof = 0; + +				if ( yywrap() ) +					{ +					/* Note: because we've taken care in +					 * yy_get_next_buffer() to have set up +					 * yytext, we can now set up +					 * yy_c_buf_p so that if some total +					 * hoser (like flex itself) wants to +					 * call the scanner after we return the +					 * YY_NULL, it'll still work - another +					 * YY_NULL will get returned. +					 */ +					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + +					yy_act = YY_STATE_EOF(YY_START); +					goto do_action; +					} + +				else +					{ +					if ( ! yy_did_buffer_switch_on_eof ) +						YY_NEW_FILE; +					} +				break; +				} + +			case EOB_ACT_CONTINUE_SCAN: +				yy_c_buf_p = +					yytext_ptr + yy_amount_of_matched_text; + +				yy_current_state = yy_get_previous_state(); + +				yy_cp = yy_c_buf_p; +				yy_bp = yytext_ptr + YY_MORE_ADJ; +				goto yy_match; + +			case EOB_ACT_LAST_MATCH: +				yy_c_buf_p = +				&yy_current_buffer->yy_ch_buf[yy_n_chars]; + +				yy_current_state = yy_get_previous_state(); + +				yy_cp = yy_c_buf_p; +				yy_bp = yytext_ptr + YY_MORE_ADJ; +				goto yy_find_action; +			} +		break; +		} + +	default: +		YY_FATAL_ERROR( +			"fatal flex scanner internal error--no action found" ); +	} /* end of action switch */ +		} /* end of scanning one token */ +	} /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + *	EOB_ACT_LAST_MATCH - + *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position + *	EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() +	{ +	register char *dest = yy_current_buffer->yy_ch_buf; +	register char *source = yytext_ptr; +	register int number_to_move, i; +	int ret_val; + +	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) +		YY_FATAL_ERROR( +		"fatal flex scanner internal error--end of buffer missed" ); + +	if ( yy_current_buffer->yy_fill_buffer == 0 ) +		{ /* Don't try to fill the buffer, so this is an EOF. */ +		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) +			{ +			/* We matched a single character, the EOB, so +			 * treat this as a final EOF. +			 */ +			return EOB_ACT_END_OF_FILE; +			} + +		else +			{ +			/* We matched some text prior to the EOB, first +			 * process it. +			 */ +			return EOB_ACT_LAST_MATCH; +			} +		} + +	/* Try to read more data. */ + +	/* First move last chars to start of buffer. */ +	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + +	for ( i = 0; i < number_to_move; ++i ) +		*(dest++) = *(source++); + +	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) +		/* don't do the read, it's not guaranteed to return an EOF, +		 * just force an EOF +		 */ +		yy_current_buffer->yy_n_chars = yy_n_chars = 0; + +	else +		{ +		int num_to_read = +			yy_current_buffer->yy_buf_size - number_to_move - 1; + +		while ( num_to_read <= 0 ) +			{ /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT +			YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + +			/* just a shorter name for the current buffer */ +			YY_BUFFER_STATE b = yy_current_buffer; + +			int yy_c_buf_p_offset = +				(int) (yy_c_buf_p - b->yy_ch_buf); + +			if ( b->yy_is_our_buffer ) +				{ +				int new_size = b->yy_buf_size * 2; + +				if ( new_size <= 0 ) +					b->yy_buf_size += b->yy_buf_size / 8; +				else +					b->yy_buf_size *= 2; + +				b->yy_ch_buf = (char *) +					/* Include room in for 2 EOB chars. */ +					yy_flex_realloc( (void *) b->yy_ch_buf, +							 b->yy_buf_size + 2 ); +				} +			else +				/* Can't grow it, we don't own it. */ +				b->yy_ch_buf = 0; + +			if ( ! b->yy_ch_buf ) +				YY_FATAL_ERROR( +				"fatal error - scanner input buffer overflow" ); + +			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + +			num_to_read = yy_current_buffer->yy_buf_size - +						number_to_move - 1; +#endif +			} + +		if ( num_to_read > YY_READ_BUF_SIZE ) +			num_to_read = YY_READ_BUF_SIZE; + +		/* Read in more data. */ +		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), +			yy_n_chars, num_to_read ); + +		yy_current_buffer->yy_n_chars = yy_n_chars; +		} + +	if ( yy_n_chars == 0 ) +		{ +		if ( number_to_move == YY_MORE_ADJ ) +			{ +			ret_val = EOB_ACT_END_OF_FILE; +			yyrestart( yyin ); +			} + +		else +			{ +			ret_val = EOB_ACT_LAST_MATCH; +			yy_current_buffer->yy_buffer_status = +				YY_BUFFER_EOF_PENDING; +			} +		} + +	else +		ret_val = EOB_ACT_CONTINUE_SCAN; + +	yy_n_chars += number_to_move; +	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; +	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + +	yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + +	return ret_val; +	} + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() +	{ +	register yy_state_type yy_current_state; +	register char *yy_cp; + +	yy_current_state = yy_start; +	yy_current_state += YY_AT_BOL(); + +	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) +		{ +		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); +		if ( yy_accept[yy_current_state] ) +			{ +			yy_last_accepting_state = yy_current_state; +			yy_last_accepting_cpos = yy_cp; +			} +		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) +			{ +			yy_current_state = (int) yy_def[yy_current_state]; +			if ( yy_current_state >= 76 ) +				yy_c = yy_meta[(unsigned int) yy_c]; +			} +		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; +		} + +	return yy_current_state; +	} + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + *	next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif +	{ +	register int yy_is_jam; +	register char *yy_cp = yy_c_buf_p; + +	register YY_CHAR yy_c = 1; +	if ( yy_accept[yy_current_state] ) +		{ +		yy_last_accepting_state = yy_current_state; +		yy_last_accepting_cpos = yy_cp; +		} +	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) +		{ +		yy_current_state = (int) yy_def[yy_current_state]; +		if ( yy_current_state >= 76 ) +			yy_c = yy_meta[(unsigned int) yy_c]; +		} +	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; +	yy_is_jam = (yy_current_state == 75); + +	return yy_is_jam ? 0 : yy_current_state; +	} + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif +	{ +	register char *yy_cp = yy_c_buf_p; + +	/* undo effects of setting up yytext */ +	*yy_cp = yy_hold_char; + +	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) +		{ /* need to shift things up to make room */ +		/* +2 for EOB chars. */ +		register int number_to_move = yy_n_chars + 2; +		register char *dest = &yy_current_buffer->yy_ch_buf[ +					yy_current_buffer->yy_buf_size + 2]; +		register char *source = +				&yy_current_buffer->yy_ch_buf[number_to_move]; + +		while ( source > yy_current_buffer->yy_ch_buf ) +			*--dest = *--source; + +		yy_cp += (int) (dest - source); +		yy_bp += (int) (dest - source); +		yy_current_buffer->yy_n_chars = +			yy_n_chars = yy_current_buffer->yy_buf_size; + +		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) +			YY_FATAL_ERROR( "flex scanner push-back overflow" ); +		} + +	*--yy_cp = (char) c; + + +	yytext_ptr = yy_bp; +	yy_hold_char = *yy_cp; +	yy_c_buf_p = yy_cp; +	} +#endif	/* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif +	{ +	int c; + +	*yy_c_buf_p = yy_hold_char; + +	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) +		{ +		/* yy_c_buf_p now points to the character we want to return. +		 * If this occurs *before* the EOB characters, then it's a +		 * valid NUL; if not, then we've hit the end of the buffer. +		 */ +		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) +			/* This was really a NUL. */ +			*yy_c_buf_p = '\0'; + +		else +			{ /* need more input */ +			int offset = yy_c_buf_p - yytext_ptr; +			++yy_c_buf_p; + +			switch ( yy_get_next_buffer() ) +				{ +				case EOB_ACT_LAST_MATCH: +					/* This happens because yy_g_n_b() +					 * sees that we've accumulated a +					 * token and flags that we need to +					 * try matching the token before +					 * proceeding.  But for input(), +					 * there's no matching to consider. +					 * So convert the EOB_ACT_LAST_MATCH +					 * to EOB_ACT_END_OF_FILE. +					 */ + +					/* Reset buffer status. */ +					yyrestart( yyin ); + +					/* fall through */ + +				case EOB_ACT_END_OF_FILE: +					{ +					if ( yywrap() ) +						return EOF; + +					if ( ! yy_did_buffer_switch_on_eof ) +						YY_NEW_FILE; +#ifdef __cplusplus +					return yyinput(); +#else +					return input(); +#endif +					} + +				case EOB_ACT_CONTINUE_SCAN: +					yy_c_buf_p = yytext_ptr + offset; +					break; +				} +			} +		} + +	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */ +	*yy_c_buf_p = '\0';	/* preserve yytext */ +	yy_hold_char = *++yy_c_buf_p; + +	yy_current_buffer->yy_at_bol = (c == '\n'); + +	return c; +	} + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif +	{ +	if ( ! yy_current_buffer ) +		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + +	yy_init_buffer( yy_current_buffer, input_file ); +	yy_load_buffer_state(); +	} + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif +	{ +	if ( yy_current_buffer == new_buffer ) +		return; + +	if ( yy_current_buffer ) +		{ +		/* Flush out information for old buffer. */ +		*yy_c_buf_p = yy_hold_char; +		yy_current_buffer->yy_buf_pos = yy_c_buf_p; +		yy_current_buffer->yy_n_chars = yy_n_chars; +		} + +	yy_current_buffer = new_buffer; +	yy_load_buffer_state(); + +	/* We don't actually know whether we did this switch during +	 * EOF (yywrap()) processing, but the only time this flag +	 * is looked at is after yywrap() is called, so it's safe +	 * to go ahead and always set it. +	 */ +	yy_did_buffer_switch_on_eof = 1; +	} + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif +	{ +	yy_n_chars = yy_current_buffer->yy_n_chars; +	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; +	yyin = yy_current_buffer->yy_input_file; +	yy_hold_char = *yy_c_buf_p; +	} + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif +	{ +	YY_BUFFER_STATE b; + +	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); +	if ( ! b ) +		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + +	b->yy_buf_size = size; + +	/* yy_ch_buf has to be 2 characters longer than the size given because +	 * we need to put in 2 end-of-buffer characters. +	 */ +	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); +	if ( ! b->yy_ch_buf ) +		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + +	b->yy_is_our_buffer = 1; + +	yy_init_buffer( b, file ); + +	return b; +	} + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif +	{ +	if ( ! b ) +		return; + +	if ( b == yy_current_buffer ) +		yy_current_buffer = (YY_BUFFER_STATE) 0; + +	if ( b->yy_is_our_buffer ) +		yy_flex_free( (void *) b->yy_ch_buf ); + +	yy_flex_free( (void *) b ); +	} + + + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + +	{ +	yy_flush_buffer( b ); + +	b->yy_input_file = file; +	b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE +	b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE +	b->yy_is_interactive = 0; +#else +	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif +	} + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + +	{ +	if ( ! b ) +		return; + +	b->yy_n_chars = 0; + +	/* We always need two end-of-buffer characters.  The first causes +	 * a transition to the end-of-buffer state.  The second causes +	 * a jam in that state. +	 */ +	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; +	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + +	b->yy_buf_pos = &b->yy_ch_buf[0]; + +	b->yy_at_bol = 1; +	b->yy_buffer_status = YY_BUFFER_NEW; + +	if ( b == yy_current_buffer ) +		yy_load_buffer_state(); +	} + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif +	{ +	YY_BUFFER_STATE b; + +	if ( size < 2 || +	     base[size-2] != YY_END_OF_BUFFER_CHAR || +	     base[size-1] != YY_END_OF_BUFFER_CHAR ) +		/* They forgot to leave room for the EOB's. */ +		return 0; + +	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); +	if ( ! b ) +		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + +	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */ +	b->yy_buf_pos = b->yy_ch_buf = base; +	b->yy_is_our_buffer = 0; +	b->yy_input_file = 0; +	b->yy_n_chars = b->yy_buf_size; +	b->yy_is_interactive = 0; +	b->yy_at_bol = 1; +	b->yy_fill_buffer = 0; +	b->yy_buffer_status = YY_BUFFER_NEW; + +	yy_switch_to_buffer( b ); + +	return b; +	} +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif +	{ +	int len; +	for ( len = 0; yy_str[len]; ++len ) +		; + +	return yy_scan_bytes( yy_str, len ); +	} +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif +	{ +	YY_BUFFER_STATE b; +	char *buf; +	yy_size_t n; +	int i; + +	/* Get memory for full buffer, including space for trailing EOB's. */ +	n = len + 2; +	buf = (char *) yy_flex_alloc( n ); +	if ( ! buf ) +		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + +	for ( i = 0; i < len; ++i ) +		buf[i] = bytes[i]; + +	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + +	b = yy_scan_buffer( buf, n ); +	if ( ! b ) +		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + +	/* It's okay to grow etc. this buffer, and we should throw it +	 * away when we're done. +	 */ +	b->yy_is_our_buffer = 1; + +	return b; +	} +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif +	{ +	if ( yy_start_stack_ptr >= yy_start_stack_depth ) +		{ +		yy_size_t new_size; + +		yy_start_stack_depth += YY_START_STACK_INCR; +		new_size = yy_start_stack_depth * sizeof( int ); + +		if ( ! yy_start_stack ) +			yy_start_stack = (int *) yy_flex_alloc( new_size ); + +		else +			yy_start_stack = (int *) yy_flex_realloc( +					(void *) yy_start_stack, new_size ); + +		if ( ! yy_start_stack ) +			YY_FATAL_ERROR( +			"out of memory expanding start-condition stack" ); +		} + +	yy_start_stack[yy_start_stack_ptr++] = YY_START; + +	BEGIN(new_state); +	} +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() +	{ +	if ( --yy_start_stack_ptr < 0 ) +		YY_FATAL_ERROR( "start-condition stack underflow" ); + +	BEGIN(yy_start_stack[yy_start_stack_ptr]); +	} +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() +	{ +	return yy_start_stack[yy_start_stack_ptr - 1]; +	} +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif +	{ +	(void) fprintf( stderr, "%s\n", msg ); +	exit( YY_EXIT_FAILURE ); +	} + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ +	do \ +		{ \ +		/* Undo effects of setting up yytext. */ \ +		yytext[yyleng] = yy_hold_char; \ +		yy_c_buf_p = yytext + n; \ +		yy_hold_char = *yy_c_buf_p; \ +		*yy_c_buf_p = '\0'; \ +		yyleng = n; \ +		} \ +	while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif +	{ +	register int i; +	for ( i = 0; i < n; ++i ) +		s1[i] = s2[i]; +	} +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif +	{ +	register int n; +	for ( n = 0; s[n]; ++n ) +		; + +	return n; +	} +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif +	{ +	return (void *) malloc( size ); +	} + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif +	{ +	/* The cast to (char *) in the following accommodates both +	 * implementations that use char* generic pointers, and those +	 * that use void* generic pointers.  It works with the latter +	 * because both ANSI C and C++ allow castless assignment from +	 * any pointer type to void*, and deal with argument conversions +	 * as though doing an assignment. +	 */ +	return (void *) realloc( (char *) ptr, size ); +	} + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif +	{ +	free( ptr ); +	} + +#if YY_MAIN +int main() +	{ +	yylex(); +	return 0; +	} +#endif +#line 95 "scripts/genksyms/lex.l" + + +/* Bring in the keyword recognizer.  */ + +#include "keywords.c" + + +/* Macros to append to our phrase collection list.  */ + +#define _APP(T,L)	do {						   \ +			  cur_node = next_node;				   \ +			  next_node = xmalloc(sizeof(*next_node));	   \ +			  next_node->next = cur_node;			   \ +			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \ +			  cur_node->tag = SYM_NORMAL;			   \ +			} while (0) + +#define APP		_APP(yytext, yyleng) + + +/* The second stage lexer.  Here we incorporate knowledge of the state +   of the parser to tailor the tokens that are returned.  */ + +int +yylex(void) +{ +  static enum { +    ST_NOTSTARTED, ST_NORMAL, ST_ATTRIBUTE, ST_ASM, ST_BRACKET, ST_BRACE, +    ST_EXPRESSION, ST_TABLE_1, ST_TABLE_2, ST_TABLE_3, ST_TABLE_4, +    ST_TABLE_5, ST_TABLE_6 +  } lexstate = ST_NOTSTARTED; + +  static int suppress_type_lookup, dont_want_brace_phrase; +  static struct string_list *next_node; + +  int token, count = 0; +  struct string_list *cur_node; + +  if (lexstate == ST_NOTSTARTED) +    { +      BEGIN(V2_TOKENS); +      next_node = xmalloc(sizeof(*next_node)); +      next_node->next = NULL; +      lexstate = ST_NORMAL; +    } + +repeat: +  token = yylex1(); + +  if (token == 0) +    return 0; +  else if (token == FILENAME) +    { +      char *file, *e; + +      /* Save the filename and line number for later error messages.  */ + +      if (cur_filename) +	free(cur_filename); + +      file = strchr(yytext, '\"')+1; +      e = strchr(file, '\"'); +      *e = '\0'; +      cur_filename = memcpy(xmalloc(e-file+1), file, e-file+1); +      cur_line = atoi(yytext+2); + +      goto repeat; +    } + +  switch (lexstate) +    { +    case ST_NORMAL: +      switch (token) +	{ +	case IDENT: +	  APP; +	  { +	    const struct resword *r = is_reserved_word(yytext, yyleng); +	    if (r) +	      { +		switch (token = r->token) +		  { +		  case ATTRIBUTE_KEYW: +		    lexstate = ST_ATTRIBUTE; +		    count = 0; +		    goto repeat; +		  case ASM_KEYW: +		    lexstate = ST_ASM; +		    count = 0; +		    goto repeat; + +		  case STRUCT_KEYW: +		  case UNION_KEYW: +		    dont_want_brace_phrase = 3; +		  case ENUM_KEYW: +		    suppress_type_lookup = 2; +		    goto fini; + +		  case EXPORT_SYMBOL_KEYW: +		      goto fini; +		  } +	      } +	    if (!suppress_type_lookup) +	      { +		struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF); +		if (sym && sym->type == SYM_TYPEDEF) +		  token = TYPE; +	      } +	  } +	  break; + +	case '[': +	  APP; +	  lexstate = ST_BRACKET; +	  count = 1; +	  goto repeat; + +	case '{': +	  APP; +	  if (dont_want_brace_phrase) +	    break; +	  lexstate = ST_BRACE; +	  count = 1; +	  goto repeat; + +	case '=': case ':': +	  APP; +	  lexstate = ST_EXPRESSION; +	  break; + +	case DOTS: +	default: +	  APP; +	  break; +	} +      break; + +    case ST_ATTRIBUTE: +      APP; +      switch (token) +	{ +	case '(': +	  ++count; +	  goto repeat; +	case ')': +	  if (--count == 0) +	    { +	      lexstate = ST_NORMAL; +	      token = ATTRIBUTE_PHRASE; +	      break; +	    } +	  goto repeat; +	default: +	  goto repeat; +	} +      break; + +    case ST_ASM: +      APP; +      switch (token) +	{ +	case '(': +	  ++count; +	  goto repeat; +	case ')': +	  if (--count == 0) +	    { +	      lexstate = ST_NORMAL; +	      token = ASM_PHRASE; +	      break; +	    } +	  goto repeat; +	default: +	  goto repeat; +	} +      break; + +    case ST_BRACKET: +      APP; +      switch (token) +	{ +	case '[': +	  ++count; +	  goto repeat; +	case ']': +	  if (--count == 0) +	    { +	      lexstate = ST_NORMAL; +	      token = BRACKET_PHRASE; +	      break; +	    } +	  goto repeat; +	default: +	  goto repeat; +	} +      break; + +    case ST_BRACE: +      APP; +      switch (token) +	{ +	case '{': +	  ++count; +	  goto repeat; +	case '}': +	  if (--count == 0) +	    { +	      lexstate = ST_NORMAL; +	      token = BRACE_PHRASE; +	      break; +	    } +	  goto repeat; +	default: +	  goto repeat; +	} +      break; + +    case ST_EXPRESSION: +      switch (token) +	{ +	case '(': case '[': case '{': +	  ++count; +	  APP; +	  goto repeat; +	case ')': case ']': case '}': +	  --count; +	  APP; +	  goto repeat; +	case ',': case ';': +	  if (count == 0) +	    { +	      /* Put back the token we just read so's we can find it again +		 after registering the expression.  */ +	      unput(token); + +	      lexstate = ST_NORMAL; +	      token = EXPRESSION_PHRASE; +	      break; +	    } +	  APP; +	  goto repeat; +	default: +	  APP; +	  goto repeat; +	} +      break; + +    case ST_TABLE_1: +      goto repeat; + +    case ST_TABLE_2: +      if (token == IDENT && yyleng == 1 && yytext[0] == 'X') +	{ +	  token = EXPORT_SYMBOL_KEYW; +	  lexstate = ST_TABLE_5; +	  APP; +	  break; +	} +      lexstate = ST_TABLE_6; +      /* FALLTHRU */ + +    case ST_TABLE_6: +      switch (token) +	{ +	case '{': case '[': case '(': +	  ++count; +	  break; +	case '}': case ']': case ')': +	  --count; +	  break; +	case ',': +	  if (count == 0) +	    lexstate = ST_TABLE_2; +	  break; +	}; +      goto repeat; + +    case ST_TABLE_3: +      goto repeat; + +    case ST_TABLE_4: +      if (token == ';') +	lexstate = ST_NORMAL; +      goto repeat; + +    case ST_TABLE_5: +      switch (token) +	{ +	case ',': +	  token = ';'; +	  lexstate = ST_TABLE_2; +	  APP; +	  break; +	default: +	  APP; +	  break; +	} +      break; + +    default: +      abort(); +    } +fini: + +  if (suppress_type_lookup > 0) +    --suppress_type_lookup; +  if (dont_want_brace_phrase > 0) +    --dont_want_brace_phrase; + +  yylval = &next_node->next; + +  return token; +} +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#define	ASM_KEYW	257 +#define	ATTRIBUTE_KEYW	258 +#define	AUTO_KEYW	259 +#define	BOOL_KEYW	260 +#define	CHAR_KEYW	261 +#define	CONST_KEYW	262 +#define	DOUBLE_KEYW	263 +#define	ENUM_KEYW	264 +#define	EXTERN_KEYW	265 +#define	FLOAT_KEYW	266 +#define	INLINE_KEYW	267 +#define	INT_KEYW	268 +#define	LONG_KEYW	269 +#define	REGISTER_KEYW	270 +#define	RESTRICT_KEYW	271 +#define	SHORT_KEYW	272 +#define	SIGNED_KEYW	273 +#define	STATIC_KEYW	274 +#define	STRUCT_KEYW	275 +#define	TYPEDEF_KEYW	276 +#define	UNION_KEYW	277 +#define	UNSIGNED_KEYW	278 +#define	VOID_KEYW	279 +#define	VOLATILE_KEYW	280 +#define	TYPEOF_KEYW	281 +#define	EXPORT_SYMBOL_KEYW	282 +#define	ASM_PHRASE	283 +#define	ATTRIBUTE_PHRASE	284 +#define	BRACE_PHRASE	285 +#define	BRACKET_PHRASE	286 +#define	EXPRESSION_PHRASE	287 +#define	CHAR	288 +#define	DOTS	289 +#define	IDENT	290 +#define	INT	291 +#define	REAL	292 +#define	STRING	293 +#define	TYPE	294 +#define	OTHER	295 +#define	FILENAME	296 + + +extern YYSTYPE yylval; diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l new file mode 100644 index 000000000000..fe0dfeedf0ff --- /dev/null +++ b/scripts/genksyms/lex.l @@ -0,0 +1,407 @@ +/* Lexical analysis for genksyms. +   Copyright 1996, 1997 Linux International. + +   New implementation contributed by Richard Henderson <rth@tamu.edu> +   Based on original work by Bjorn Ekwall <bj0rn@blox.se> + +   Taken from Linux modutils 2.4.22. + +   This program is free software; you can redistribute it and/or modify it +   under the terms of the GNU General Public License as published by the +   Free Software Foundation; either version 2 of the License, or (at your +   option) any later version. + +   This program is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software Foundation, +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ + + +%{ + +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "genksyms.h" +#include "parse.h" + +/* We've got a two-level lexer here.  We let flex do basic tokenization +   and then we categorize those basic tokens in the second stage.  */ +#define YY_DECL		static int yylex1(void) + +%} + +IDENT			[A-Za-z_\$][A-Za-z0-9_\$]* + +O_INT			0[0-7]* +D_INT			[1-9][0-9]* +X_INT			0[Xx][0-9A-Fa-f]+ +I_SUF			[Uu]|[Ll]|[Uu][Ll]|[Ll][Uu] +INT			({O_INT}|{D_INT}|{X_INT}){I_SUF}? + +FRAC			([0-9]*\.[0-9]+)|([0-9]+\.) +EXP			[Ee][+-]?[0-9]+ +F_SUF			[FfLl] +REAL			({FRAC}{EXP}?{F_SUF}?)|([0-9]+{EXP}{F_SUF}?) + +STRING			L?\"([^\\\"]*\\.)*[^\\\"]*\" +CHAR			L?\'([^\\\']*\\.)*[^\\\']*\' + +MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>) + +/* Version 2 checksumming does proper tokenization; version 1 wasn't +   quite so pedantic.  */ +%s V2_TOKENS + +/* We don't do multiple input files.  */ +%option noyywrap + +%% + + + /* Keep track of our location in the original source files.  */ +^#[ \t]+{INT}[ \t]+\"[^\"\n]+\".*\n	return FILENAME; +^#.*\n					cur_line++; +\n					cur_line++; + + /* Ignore all other whitespace.  */ +[ \t\f\v\r]+				; + + +{STRING}				return STRING; +{CHAR}					return CHAR; +{IDENT}					return IDENT; + + /* The Pedant requires that the other C multi-character tokens be +    recognized as tokens.  We don't actually use them since we don't +    parse expressions, but we do want whitespace to be arranged +    around them properly.  */ +<V2_TOKENS>{MC_TOKEN}			return OTHER; +<V2_TOKENS>{INT}			return INT; +<V2_TOKENS>{REAL}			return REAL; + +"..."					return DOTS; + + /* All other tokens are single characters.  */ +.					return yytext[0]; + + +%% + +/* Bring in the keyword recognizer.  */ + +#include "keywords.c" + + +/* Macros to append to our phrase collection list.  */ + +#define _APP(T,L)	do {						   \ +			  cur_node = next_node;				   \ +			  next_node = xmalloc(sizeof(*next_node));	   \ +			  next_node->next = cur_node;			   \ +			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \ +			  cur_node->tag = SYM_NORMAL;			   \ +			} while (0) + +#define APP		_APP(yytext, yyleng) + + +/* The second stage lexer.  Here we incorporate knowledge of the state +   of the parser to tailor the tokens that are returned.  */ + +int +yylex(void) +{ +  static enum { +    ST_NOTSTARTED, ST_NORMAL, ST_ATTRIBUTE, ST_ASM, ST_BRACKET, ST_BRACE, +    ST_EXPRESSION, ST_TABLE_1, ST_TABLE_2, ST_TABLE_3, ST_TABLE_4, +    ST_TABLE_5, ST_TABLE_6 +  } lexstate = ST_NOTSTARTED; + +  static int suppress_type_lookup, dont_want_brace_phrase; +  static struct string_list *next_node; + +  int token, count = 0; +  struct string_list *cur_node; + +  if (lexstate == ST_NOTSTARTED) +    { +      BEGIN(V2_TOKENS); +      next_node = xmalloc(sizeof(*next_node)); +      next_node->next = NULL; +      lexstate = ST_NORMAL; +    } + +repeat: +  token = yylex1(); + +  if (token == 0) +    return 0; +  else if (token == FILENAME) +    { +      char *file, *e; + +      /* Save the filename and line number for later error messages.  */ + +      if (cur_filename) +	free(cur_filename); + +      file = strchr(yytext, '\"')+1; +      e = strchr(file, '\"'); +      *e = '\0'; +      cur_filename = memcpy(xmalloc(e-file+1), file, e-file+1); +      cur_line = atoi(yytext+2); + +      goto repeat; +    } + +  switch (lexstate) +    { +    case ST_NORMAL: +      switch (token) +	{ +	case IDENT: +	  APP; +	  { +	    const struct resword *r = is_reserved_word(yytext, yyleng); +	    if (r) +	      { +		switch (token = r->token) +		  { +		  case ATTRIBUTE_KEYW: +		    lexstate = ST_ATTRIBUTE; +		    count = 0; +		    goto repeat; +		  case ASM_KEYW: +		    lexstate = ST_ASM; +		    count = 0; +		    goto repeat; + +		  case STRUCT_KEYW: +		  case UNION_KEYW: +		    dont_want_brace_phrase = 3; +		  case ENUM_KEYW: +		    suppress_type_lookup = 2; +		    goto fini; + +		  case EXPORT_SYMBOL_KEYW: +		      goto fini; +		  } +	      } +	    if (!suppress_type_lookup) +	      { +		struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF); +		if (sym && sym->type == SYM_TYPEDEF) +		  token = TYPE; +	      } +	  } +	  break; + +	case '[': +	  APP; +	  lexstate = ST_BRACKET; +	  count = 1; +	  goto repeat; + +	case '{': +	  APP; +	  if (dont_want_brace_phrase) +	    break; +	  lexstate = ST_BRACE; +	  count = 1; +	  goto repeat; + +	case '=': case ':': +	  APP; +	  lexstate = ST_EXPRESSION; +	  break; + +	case DOTS: +	default: +	  APP; +	  break; +	} +      break; + +    case ST_ATTRIBUTE: +      APP; +      switch (token) +	{ +	case '(': +	  ++count; +	  goto repeat; +	case ')': +	  if (--count == 0) +	    { +	      lexstate = ST_NORMAL; +	      token = ATTRIBUTE_PHRASE; +	      break; +	    } +	  goto repeat; +	default: +	  goto repeat; +	} +      break; + +    case ST_ASM: +      APP; +      switch (token) +	{ +	case '(': +	  ++count; +	  goto repeat; +	case ')': +	  if (--count == 0) +	    { +	      lexstate = ST_NORMAL; +	      token = ASM_PHRASE; +	      break; +	    } +	  goto repeat; +	default: +	  goto repeat; +	} +      break; + +    case ST_BRACKET: +      APP; +      switch (token) +	{ +	case '[': +	  ++count; +	  goto repeat; +	case ']': +	  if (--count == 0) +	    { +	      lexstate = ST_NORMAL; +	      token = BRACKET_PHRASE; +	      break; +	    } +	  goto repeat; +	default: +	  goto repeat; +	} +      break; + +    case ST_BRACE: +      APP; +      switch (token) +	{ +	case '{': +	  ++count; +	  goto repeat; +	case '}': +	  if (--count == 0) +	    { +	      lexstate = ST_NORMAL; +	      token = BRACE_PHRASE; +	      break; +	    } +	  goto repeat; +	default: +	  goto repeat; +	} +      break; + +    case ST_EXPRESSION: +      switch (token) +	{ +	case '(': case '[': case '{': +	  ++count; +	  APP; +	  goto repeat; +	case ')': case ']': case '}': +	  --count; +	  APP; +	  goto repeat; +	case ',': case ';': +	  if (count == 0) +	    { +	      /* Put back the token we just read so's we can find it again +		 after registering the expression.  */ +	      unput(token); + +	      lexstate = ST_NORMAL; +	      token = EXPRESSION_PHRASE; +	      break; +	    } +	  APP; +	  goto repeat; +	default: +	  APP; +	  goto repeat; +	} +      break; + +    case ST_TABLE_1: +      goto repeat; + +    case ST_TABLE_2: +      if (token == IDENT && yyleng == 1 && yytext[0] == 'X') +	{ +	  token = EXPORT_SYMBOL_KEYW; +	  lexstate = ST_TABLE_5; +	  APP; +	  break; +	} +      lexstate = ST_TABLE_6; +      /* FALLTHRU */ + +    case ST_TABLE_6: +      switch (token) +	{ +	case '{': case '[': case '(': +	  ++count; +	  break; +	case '}': case ']': case ')': +	  --count; +	  break; +	case ',': +	  if (count == 0) +	    lexstate = ST_TABLE_2; +	  break; +	}; +      goto repeat; + +    case ST_TABLE_3: +      goto repeat; + +    case ST_TABLE_4: +      if (token == ';') +	lexstate = ST_NORMAL; +      goto repeat; + +    case ST_TABLE_5: +      switch (token) +	{ +	case ',': +	  token = ';'; +	  lexstate = ST_TABLE_2; +	  APP; +	  break; +	default: +	  APP; +	  break; +	} +      break; + +    default: +      abort(); +    } +fini: + +  if (suppress_type_lookup > 0) +    --suppress_type_lookup; +  if (dont_want_brace_phrase > 0) +    --dont_want_brace_phrase; + +  yylval = &next_node->next; + +  return token; +} diff --git a/scripts/genksyms/parse.c_shipped b/scripts/genksyms/parse.c_shipped new file mode 100644 index 000000000000..2c6b1286b638 --- /dev/null +++ b/scripts/genksyms/parse.c_shipped @@ -0,0 +1,1577 @@ + +/*  A Bison parser, made from scripts/genksyms/parse.y +    by GNU Bison version 1.28  */ + +#define YYBISON 1  /* Identify Bison output.  */ + +#define	ASM_KEYW	257 +#define	ATTRIBUTE_KEYW	258 +#define	AUTO_KEYW	259 +#define	BOOL_KEYW	260 +#define	CHAR_KEYW	261 +#define	CONST_KEYW	262 +#define	DOUBLE_KEYW	263 +#define	ENUM_KEYW	264 +#define	EXTERN_KEYW	265 +#define	FLOAT_KEYW	266 +#define	INLINE_KEYW	267 +#define	INT_KEYW	268 +#define	LONG_KEYW	269 +#define	REGISTER_KEYW	270 +#define	RESTRICT_KEYW	271 +#define	SHORT_KEYW	272 +#define	SIGNED_KEYW	273 +#define	STATIC_KEYW	274 +#define	STRUCT_KEYW	275 +#define	TYPEDEF_KEYW	276 +#define	UNION_KEYW	277 +#define	UNSIGNED_KEYW	278 +#define	VOID_KEYW	279 +#define	VOLATILE_KEYW	280 +#define	TYPEOF_KEYW	281 +#define	EXPORT_SYMBOL_KEYW	282 +#define	ASM_PHRASE	283 +#define	ATTRIBUTE_PHRASE	284 +#define	BRACE_PHRASE	285 +#define	BRACKET_PHRASE	286 +#define	EXPRESSION_PHRASE	287 +#define	CHAR	288 +#define	DOTS	289 +#define	IDENT	290 +#define	INT	291 +#define	REAL	292 +#define	STRING	293 +#define	TYPE	294 +#define	OTHER	295 +#define	FILENAME	296 + +#line 24 "scripts/genksyms/parse.y" + + +#include <assert.h> +#include <malloc.h> +#include "genksyms.h" + +static int is_typedef; +static int is_extern; +static char *current_name; +static struct string_list *decl_spec; + +static void yyerror(const char *); + +static inline void +remove_node(struct string_list **p) +{ +  struct string_list *node = *p; +  *p = node->next; +  free_node(node); +} + +static inline void +remove_list(struct string_list **pb, struct string_list **pe) +{ +  struct string_list *b = *pb, *e = *pe; +  *pb = e; +  free_list(b, e); +} + +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#ifndef YYDEBUG +#define YYDEBUG 1 +#endif + +#include <stdio.h> + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define	YYFINAL		172 +#define	YYFLAG		-32768 +#define	YYNTBASE	52 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 296 ? yytranslate[x] : 96) + +static const char yytranslate[] = {     0, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,    46, +    47,    48,     2,    45,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,    51,    43,     2, +    49,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,    50,     2,    44,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +     2,     2,     2,     2,     2,     1,     3,     4,     5,     6, +     7,     8,     9,    10,    11,    12,    13,    14,    15,    16, +    17,    18,    19,    20,    21,    22,    23,    24,    25,    26, +    27,    28,    29,    30,    31,    32,    33,    34,    35,    36, +    37,    38,    39,    40,    41,    42 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = {     0, +     0,     2,     5,     6,     9,    10,    14,    16,    18,    20, +    22,    25,    28,    32,    33,    35,    37,    41,    46,    47, +    49,    51,    54,    56,    58,    60,    62,    64,    66,    68, +    70,    72,    77,    80,    83,    86,    90,    94,    98,   101, +   104,   107,   109,   111,   113,   115,   117,   119,   121,   123, +   125,   127,   129,   132,   133,   135,   137,   140,   142,   144, +   146,   148,   151,   153,   155,   160,   165,   168,   172,   176, +   179,   181,   183,   185,   190,   195,   198,   202,   206,   209, +   211,   215,   216,   218,   220,   224,   227,   230,   232,   233, +   235,   237,   242,   247,   250,   254,   258,   262,   263,   265, +   268,   272,   276,   277,   279,   281,   284,   288,   291,   292, +   294,   296,   300,   303,   306,   308,   311,   312,   314,   317, +   318,   320 +}; + +static const short yyrhs[] = {    53, +     0,    52,    53,     0,     0,    54,    55,     0,     0,    22, +    56,    57,     0,    57,     0,    81,     0,    93,     0,    95, +     0,     1,    43,     0,     1,    44,     0,    61,    58,    43, +     0,     0,    59,     0,    60,     0,    59,    45,    60,     0, +    71,    94,    92,    82,     0,     0,    62,     0,    63,     0, +    62,    63,     0,    64,     0,    65,     0,     5,     0,    16, +     0,    20,     0,    11,     0,    13,     0,    66,     0,    70, +     0,    27,    46,    62,    47,     0,    21,    36,     0,    23, +    36,     0,    10,    36,     0,    21,    36,    84,     0,    23, +    36,    84,     0,    10,    36,    31,     0,    10,    31,     0, +    21,    84,     0,    23,    84,     0,     7,     0,    18,     0, +    14,     0,    15,     0,    19,     0,    24,     0,    12,     0, +     9,     0,    25,     0,     6,     0,    40,     0,    48,    68, +     0,     0,    69,     0,    70,     0,    69,    70,     0,     8, +     0,    26,     0,    30,     0,    17,     0,    67,    71,     0, +    72,     0,    36,     0,    72,    46,    75,    47,     0,    72, +    46,     1,    47,     0,    72,    32,     0,    46,    71,    47, +     0,    46,     1,    47,     0,    67,    73,     0,    74,     0, +    36,     0,    40,     0,    74,    46,    75,    47,     0,    74, +    46,     1,    47,     0,    74,    32,     0,    46,    73,    47, +     0,    46,     1,    47,     0,    76,    35,     0,    76,     0, +    77,    45,    35,     0,     0,    77,     0,    78,     0,    77, +    45,    78,     0,    62,    79,     0,    67,    79,     0,    80, +     0,     0,    36,     0,    40,     0,    80,    46,    75,    47, +     0,    80,    46,     1,    47,     0,    80,    32,     0,    46, +    79,    47,     0,    46,     1,    47,     0,    61,    71,    31, +     0,     0,    83,     0,    49,    33,     0,    50,    85,    44, +     0,    50,     1,    44,     0,     0,    86,     0,    87,     0, +    86,    87,     0,    61,    88,    43,     0,     1,    43,     0, +     0,    89,     0,    90,     0,    89,    45,    90,     0,    73, +    92,     0,    36,    91,     0,    91,     0,    51,    33,     0, +     0,    30,     0,    29,    43,     0,     0,    29,     0,    28, +    46,    36,    47,    43,     0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, +   101,   103,   106,   109,   112,   114,   115,   116,   117,   118, +   119,   120,   123,   137,   139,   142,   151,   163,   169,   171, +   174,   176,   179,   186,   189,   191,   192,   193,   194,   197, +   199,   200,   204,   206,   208,   212,   219,   226,   235,   236, +   237,   240,   242,   243,   244,   245,   246,   247,   248,   249, +   250,   251,   254,   259,   261,   264,   266,   269,   270,   270, +   271,   278,   280,   283,   293,   295,   297,   299,   301,   307, +   309,   312,   314,   315,   317,   319,   321,   323,   327,   329, +   330,   333,   335,   338,   340,   344,   349,   352,   355,   357, +   365,   369,   371,   373,   375,   377,   381,   390,   392,   396, +   401,   403,   406,   408,   411,   413,   416,   419,   423,   425, +   428,   430,   433,   435,   436,   439,   443,   445,   448,   452, +   454,   457 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = {   "$","error","$undefined.","ASM_KEYW", +"ATTRIBUTE_KEYW","AUTO_KEYW","BOOL_KEYW","CHAR_KEYW","CONST_KEYW","DOUBLE_KEYW", +"ENUM_KEYW","EXTERN_KEYW","FLOAT_KEYW","INLINE_KEYW","INT_KEYW","LONG_KEYW", +"REGISTER_KEYW","RESTRICT_KEYW","SHORT_KEYW","SIGNED_KEYW","STATIC_KEYW","STRUCT_KEYW", +"TYPEDEF_KEYW","UNION_KEYW","UNSIGNED_KEYW","VOID_KEYW","VOLATILE_KEYW","TYPEOF_KEYW", +"EXPORT_SYMBOL_KEYW","ASM_PHRASE","ATTRIBUTE_PHRASE","BRACE_PHRASE","BRACKET_PHRASE", +"EXPRESSION_PHRASE","CHAR","DOTS","IDENT","INT","REAL","STRING","TYPE","OTHER", +"FILENAME","';'","'}'","','","'('","')'","'*'","'='","'{'","':'","declaration_seq", +"declaration","@1","declaration1","@2","simple_declaration","init_declarator_list_opt", +"init_declarator_list","init_declarator","decl_specifier_seq_opt","decl_specifier_seq", +"decl_specifier","storage_class_specifier","type_specifier","simple_type_specifier", +"ptr_operator","cvar_qualifier_seq_opt","cvar_qualifier_seq","cvar_qualifier", +"declarator","direct_declarator","nested_declarator","direct_nested_declarator", +"parameter_declaration_clause","parameter_declaration_list_opt","parameter_declaration_list", +"parameter_declaration","m_abstract_declarator","direct_m_abstract_declarator", +"function_definition","initializer_opt","initializer","class_body","member_specification_opt", +"member_specification","member_declaration","member_declarator_list_opt","member_declarator_list", +"member_declarator","member_bitfield_declarator","attribute_opt","asm_definition", +"asm_phrase_opt","export_definition", NULL +}; +#endif + +static const short yyr1[] = {     0, +    52,    52,    54,    53,    56,    55,    55,    55,    55,    55, +    55,    55,    57,    58,    58,    59,    59,    60,    61,    61, +    62,    62,    63,    63,    64,    64,    64,    64,    64,    65, +    65,    65,    65,    65,    65,    65,    65,    65,    65,    65, +    65,    66,    66,    66,    66,    66,    66,    66,    66,    66, +    66,    66,    67,    68,    68,    69,    69,    70,    70,    70, +    70,    71,    71,    72,    72,    72,    72,    72,    72,    73, +    73,    74,    74,    74,    74,    74,    74,    74,    75,    75, +    75,    76,    76,    77,    77,    78,    79,    79,    80,    80, +    80,    80,    80,    80,    80,    80,    81,    82,    82,    83, +    84,    84,    85,    85,    86,    86,    87,    87,    88,    88, +    89,    89,    90,    90,    90,    91,    92,    92,    93,    94, +    94,    95 +}; + +static const short yyr2[] = {     0, +     1,     2,     0,     2,     0,     3,     1,     1,     1,     1, +     2,     2,     3,     0,     1,     1,     3,     4,     0,     1, +     1,     2,     1,     1,     1,     1,     1,     1,     1,     1, +     1,     4,     2,     2,     2,     3,     3,     3,     2,     2, +     2,     1,     1,     1,     1,     1,     1,     1,     1,     1, +     1,     1,     2,     0,     1,     1,     2,     1,     1,     1, +     1,     2,     1,     1,     4,     4,     2,     3,     3,     2, +     1,     1,     1,     4,     4,     2,     3,     3,     2,     1, +     3,     0,     1,     1,     3,     2,     2,     1,     0,     1, +     1,     4,     4,     2,     3,     3,     3,     0,     1,     2, +     3,     3,     0,     1,     1,     2,     3,     2,     0,     1, +     1,     3,     2,     2,     1,     2,     0,     1,     2,     0, +     1,     5 +}; + +static const short yydefact[] = {     3, +     3,     1,     0,     2,     0,    25,    51,    42,    58,    49, +     0,    28,    48,    29,    44,    45,    26,    61,    43,    46, +    27,     0,     5,     0,    47,    50,    59,     0,     0,     0, +    60,    52,     4,     7,    14,    20,    21,    23,    24,    30, +    31,     8,     9,    10,    11,    12,    39,    35,    33,     0, +    40,    19,    34,    41,     0,     0,   119,    64,     0,    54, +     0,    15,    16,     0,   120,    63,    22,    38,    36,     0, +   109,     0,     0,   105,     6,    14,    37,     0,     0,     0, +     0,    53,    55,    56,    13,     0,    62,   121,    97,   117, +    67,     0,   108,   102,    72,    73,     0,     0,     0,   117, +    71,     0,   110,   111,   115,   101,     0,   106,   120,    32, +     0,    69,    68,    57,    17,   118,    98,     0,    89,     0, +    80,    83,    84,   114,     0,    72,     0,   116,    70,   113, +    76,     0,   107,     0,   122,     0,    18,    99,    66,    90, +    52,     0,    89,    86,    88,    65,    79,     0,    78,    77, +     0,     0,   112,   100,     0,    91,     0,    87,    94,     0, +    81,    85,    75,    74,    96,    95,     0,     0,    93,    92, +     0,     0 +}; + +static const short yydefgoto[] = {     1, +     2,     3,    33,    52,    34,    61,    62,    63,    71,    36, +    37,    38,    39,    40,    64,    82,    83,    41,   109,    66, +   100,   101,   120,   121,   122,   123,   144,   145,    42,   137, +   138,    51,    72,    73,    74,   102,   103,   104,   105,   117, +    43,    90,    44 +}; + +static const short yypact[] = {-32768, +    15,-32768,   197,-32768,    23,-32768,-32768,-32768,-32768,-32768, +   -18,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,   -28,-32768,   -25,-32768,-32768,-32768,   -26,   -22,   -12, +-32768,-32768,-32768,-32768,    49,   493,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,    27,    -8,   101, +-32768,   493,    -8,-32768,   493,    10,-32768,-32768,    11,     9, +    18,    26,-32768,    49,   -15,   -13,-32768,-32768,-32768,    25, +    24,    48,   149,-32768,-32768,    49,-32768,   414,    39,    40, +    47,-32768,     9,-32768,-32768,    49,-32768,-32768,-32768,    66, +-32768,   241,-32768,-32768,    50,-32768,     5,    65,    42,    66, +    17,    56,    55,-32768,-32768,-32768,    60,-32768,    75,-32768, +    80,-32768,-32768,-32768,-32768,-32768,    81,    82,   370,    85, +    98,    89,-32768,-32768,    88,-32768,    91,-32768,-32768,-32768, +-32768,   284,-32768,    24,-32768,   103,-32768,-32768,-32768,-32768, +-32768,     8,    43,-32768,    30,-32768,-32768,   457,-32768,-32768, +    92,    93,-32768,-32768,    95,-32768,    96,-32768,-32768,   327, +-32768,-32768,-32768,-32768,-32768,-32768,    99,   104,-32768,-32768, +   148,-32768 +}; + +static const short yypgoto[] = {-32768, +   152,-32768,-32768,-32768,   119,-32768,-32768,    94,     0,   -55, +   -35,-32768,-32768,-32768,   -69,-32768,-32768,   -56,   -30,-32768, +   -76,-32768,  -122,-32768,-32768,    29,   -62,-32768,-32768,-32768, +-32768,   -17,-32768,-32768,   105,-32768,-32768,    52,    86,    83, +-32768,-32768,-32768 +}; + + +#define	YYLAST		533 + + +static const short yytable[] = {    78, +    67,    99,    35,    84,    65,   125,    54,    49,   155,   152, +    53,    80,    47,    88,   171,    89,     9,    48,    91,    55, +   127,    50,   129,    56,    50,    18,   114,    99,    81,    99, +    57,    69,    92,    87,    27,    77,   119,   168,    31,   -89, +   126,    50,    67,   140,    96,    79,    58,   156,   131,   143, +    97,    76,    60,   142,   -89,    60,    59,    68,    60,    95, +    85,   159,   132,    96,    99,    45,    46,    93,    94,    97, +    86,    60,   143,   143,    98,   160,   119,   126,   140,   157, +   158,    96,   156,    67,    58,   111,   112,    97,   142,    60, +    60,   106,   119,   113,    59,   116,    60,   128,   133,   134, +    98,    70,    93,    88,   119,     6,     7,     8,     9,    10, +    11,    12,    13,    14,    15,    16,    17,    18,    19,    20, +    21,    22,   135,    24,    25,    26,    27,    28,   139,   136, +    31,   146,   147,   148,   149,   154,   -19,   150,   163,   164, +    32,   165,   166,   -19,  -103,   169,   -19,   172,   -19,   107, +   170,   -19,     4,     6,     7,     8,     9,    10,    11,    12, +    13,    14,    15,    16,    17,    18,    19,    20,    21,    22, +    75,    24,    25,    26,    27,    28,   162,   108,    31,   115, +   124,     0,   130,     0,   -19,   153,     0,     0,    32,     0, +     0,   -19,  -104,     0,   -19,     0,   -19,     5,     0,   -19, +     0,     6,     7,     8,     9,    10,    11,    12,    13,    14, +    15,    16,    17,    18,    19,    20,    21,    22,    23,    24, +    25,    26,    27,    28,    29,    30,    31,     0,     0,     0, +     0,     0,   -19,     0,     0,     0,    32,     0,     0,   -19, +     0,   118,   -19,     0,   -19,     6,     7,     8,     9,    10, +    11,    12,    13,    14,    15,    16,    17,    18,    19,    20, +    21,    22,     0,    24,    25,    26,    27,    28,     0,     0, +    31,     0,     0,     0,     0,   -82,     0,     0,     0,     0, +    32,     0,     0,     0,   151,     0,     0,   -82,     6,     7, +     8,     9,    10,    11,    12,    13,    14,    15,    16,    17, +    18,    19,    20,    21,    22,     0,    24,    25,    26,    27, +    28,     0,     0,    31,     0,     0,     0,     0,   -82,     0, +     0,     0,     0,    32,     0,     0,     0,   167,     0,     0, +   -82,     6,     7,     8,     9,    10,    11,    12,    13,    14, +    15,    16,    17,    18,    19,    20,    21,    22,     0,    24, +    25,    26,    27,    28,     0,     0,    31,     0,     0,     0, +     0,   -82,     0,     0,     0,     0,    32,     0,     0,     0, +     0,     0,     0,   -82,     6,     7,     8,     9,    10,    11, +    12,    13,    14,    15,    16,    17,    18,    19,    20,    21, +    22,     0,    24,    25,    26,    27,    28,     0,     0,    31, +     0,     0,     0,     0,     0,   140,     0,     0,     0,   141, +     0,     0,     0,     0,     0,   142,     0,    60,     6,     7, +     8,     9,    10,    11,    12,    13,    14,    15,    16,    17, +    18,    19,    20,    21,    22,     0,    24,    25,    26,    27, +    28,     0,     0,    31,     0,     0,     0,     0,     0,     0, +     0,     0,     0,    32,     0,     0,     0,     0,     0,     0, +   110,     6,     7,     8,     9,    10,    11,    12,    13,    14, +    15,    16,    17,    18,    19,    20,    21,    22,     0,    24, +    25,    26,    27,    28,     0,     0,    31,     0,     0,     0, +     0,   161,     0,     0,     0,     0,    32,     6,     7,     8, +     9,    10,    11,    12,    13,    14,    15,    16,    17,    18, +    19,    20,    21,    22,     0,    24,    25,    26,    27,    28, +     0,     0,    31,     0,     0,     0,     0,     0,     0,     0, +     0,     0,    32 +}; + +static const short yycheck[] = {    55, +    36,    71,     3,    60,    35,     1,    24,    36,     1,   132, +    36,     1,    31,    29,     0,    31,     8,    36,    32,    46, +    97,    50,    99,    46,    50,    17,    83,    97,    59,    99, +    43,    49,    46,    64,    26,    53,    92,   160,    30,    32, +    36,    50,    78,    36,    40,    36,    36,    40,    32,   119, +    46,    52,    48,    46,    47,    48,    46,    31,    48,    36, +    43,    32,    46,    40,   134,    43,    44,    43,    44,    46, +    45,    48,   142,   143,    51,    46,   132,    36,    36,   142, +   143,    40,    40,   119,    36,    47,    47,    46,    46,    48, +    48,    44,   148,    47,    46,    30,    48,    33,    43,    45, +    51,     1,    43,    29,   160,     5,     6,     7,     8,     9, +    10,    11,    12,    13,    14,    15,    16,    17,    18,    19, +    20,    21,    43,    23,    24,    25,    26,    27,    47,    49, +    30,    47,    35,    45,    47,    33,    36,    47,    47,    47, +    40,    47,    47,    43,    44,    47,    46,     0,    48,     1, +    47,    51,     1,     5,     6,     7,     8,     9,    10,    11, +    12,    13,    14,    15,    16,    17,    18,    19,    20,    21, +    52,    23,    24,    25,    26,    27,   148,    73,    30,    86, +    95,    -1,   100,    -1,    36,   134,    -1,    -1,    40,    -1, +    -1,    43,    44,    -1,    46,    -1,    48,     1,    -1,    51, +    -1,     5,     6,     7,     8,     9,    10,    11,    12,    13, +    14,    15,    16,    17,    18,    19,    20,    21,    22,    23, +    24,    25,    26,    27,    28,    29,    30,    -1,    -1,    -1, +    -1,    -1,    36,    -1,    -1,    -1,    40,    -1,    -1,    43, +    -1,     1,    46,    -1,    48,     5,     6,     7,     8,     9, +    10,    11,    12,    13,    14,    15,    16,    17,    18,    19, +    20,    21,    -1,    23,    24,    25,    26,    27,    -1,    -1, +    30,    -1,    -1,    -1,    -1,    35,    -1,    -1,    -1,    -1, +    40,    -1,    -1,    -1,     1,    -1,    -1,    47,     5,     6, +     7,     8,     9,    10,    11,    12,    13,    14,    15,    16, +    17,    18,    19,    20,    21,    -1,    23,    24,    25,    26, +    27,    -1,    -1,    30,    -1,    -1,    -1,    -1,    35,    -1, +    -1,    -1,    -1,    40,    -1,    -1,    -1,     1,    -1,    -1, +    47,     5,     6,     7,     8,     9,    10,    11,    12,    13, +    14,    15,    16,    17,    18,    19,    20,    21,    -1,    23, +    24,    25,    26,    27,    -1,    -1,    30,    -1,    -1,    -1, +    -1,    35,    -1,    -1,    -1,    -1,    40,    -1,    -1,    -1, +    -1,    -1,    -1,    47,     5,     6,     7,     8,     9,    10, +    11,    12,    13,    14,    15,    16,    17,    18,    19,    20, +    21,    -1,    23,    24,    25,    26,    27,    -1,    -1,    30, +    -1,    -1,    -1,    -1,    -1,    36,    -1,    -1,    -1,    40, +    -1,    -1,    -1,    -1,    -1,    46,    -1,    48,     5,     6, +     7,     8,     9,    10,    11,    12,    13,    14,    15,    16, +    17,    18,    19,    20,    21,    -1,    23,    24,    25,    26, +    27,    -1,    -1,    30,    -1,    -1,    -1,    -1,    -1,    -1, +    -1,    -1,    -1,    40,    -1,    -1,    -1,    -1,    -1,    -1, +    47,     5,     6,     7,     8,     9,    10,    11,    12,    13, +    14,    15,    16,    17,    18,    19,    20,    21,    -1,    23, +    24,    25,    26,    27,    -1,    -1,    30,    -1,    -1,    -1, +    -1,    35,    -1,    -1,    -1,    -1,    40,     5,     6,     7, +     8,     9,    10,    11,    12,    13,    14,    15,    16,    17, +    18,    19,    20,    21,    -1,    23,    24,    25,    26,    27, +    -1,    -1,    30,    -1,    -1,    -1,    -1,    -1,    -1,    -1, +    -1,    -1,    40 +}; +/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */ +#line 3 "/usr/lib/bison.simple" +/* This file comes from bison-1.28.  */ + +/* Skeleton output parser for bison, +   Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + +   This program is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published by +   the Free Software Foundation; either version 2, or (at your option) +   any later version. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software +   Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* As a special exception, when this file is copied by Bison into a +   Bison output file, you may use that output file without restriction. +   This special exception was added by the Free Software Foundation +   in version 1.24 of Bison.  */ + +/* This is the parser code that is written into each bison parser +  when the %semantic_parser declaration is not specified in the grammar. +  It was written by Richard Stallman by simplifying the hairy parser +  used when %semantic_parser is specified.  */ + +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ +#ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#else /* not GNU C.  */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA +#include <alloca.h> +#else /* not sparc */ +/* We think this test detects Watcom and Microsoft C.  */ +/* This used to test MSDOS, but that is a bad idea +   since that symbol is in the user namespace.  */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; +	 instead, just don't use alloca.  */ +#include <malloc.h> +#endif +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +/* I don't know what this was needed for, but it pollutes the namespace. +   So I turned it off.   rms, 2 May 1997.  */ +/* #include <malloc.h>  */ + #pragma alloca +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, +		 and on HPUX 10.  Eventually we can turn this on.  */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#endif /* __hpux */ +#endif +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ + +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc +#endif + +/* Note: there must be only one dollar sign in this file. +   It is replaced by the list of actions, each action +   as one case of the switch.  */ + +#define yyerrok		(yyerrstatus = 0) +#define yyclearin	(yychar = YYEMPTY) +#define YYEMPTY		-2 +#define YYEOF		0 +#define YYACCEPT	goto yyacceptlab +#define YYABORT 	goto yyabortlab +#define YYERROR		goto yyerrlab1 +/* Like YYERROR except do call yyerror. +   This remains here temporarily to ease the +   transition to the new meaning of YYERROR, for GCC. +   Once GCC version 2 has supplanted version 1, this can go.  */ +#define YYFAIL		goto yyerrlab +#define YYRECOVERING()  (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do								\ +  if (yychar == YYEMPTY && yylen == 1)				\ +    { yychar = (token), yylval = (value);			\ +      yychar1 = YYTRANSLATE (yychar);				\ +      YYPOPSTACK;						\ +      goto yybackup;						\ +    }								\ +  else								\ +    { yyerror ("syntax error: cannot back up"); YYERROR; }	\ +while (0) + +#define YYTERROR	1 +#define YYERRCODE	256 + +#ifndef YYPURE +#define YYLEX		yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX		yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX		yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX		yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX		yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int	yychar;			/*  the lookahead symbol		*/ +YYSTYPE	yylval;			/*  the semantic value of the		*/ +				/*  lookahead symbol			*/ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc;			/*  location data for the lookahead	*/ +				/*  symbol				*/ +#endif + +int yynerrs;			/*  number of parse errors so far       */ +#endif  /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug;			/*  nonzero means print parse trace	*/ +/* Since this is uninitialized, it does not stop multiple parsers +   from coexisting.  */ +#endif + +/*  YYINITDEPTH indicates the initial size of the parser's stacks	*/ + +#ifndef	YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/*  YYMAXDEPTH is the maximum size the stacks can grow to +    (effective only if the built-in stack extension method is used).  */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Define __yy_memcpy.  Note that the size argument +   should be passed with type unsigned int, because that is what the non-GCC +   definitions require.  With GCC, __builtin_memcpy takes an arg +   of type size_t, but it can handle unsigned int.  */ + +#if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */ +#define __yy_memcpy(TO,FROM,COUNT)	__builtin_memcpy(TO,FROM,COUNT) +#else				/* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities +   in available built-in functions on various systems.  */ +static void +__yy_memcpy (to, from, count) +     char *to; +     char *from; +     unsigned int count; +{ +  register char *f = from; +  register char *t = to; +  register int i = count; + +  while (i-- > 0) +    *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities +   in available built-in functions on various systems.  */ +static void +__yy_memcpy (char *to, char *from, unsigned int count) +{ +  register char *t = to; +  register char *f = from; +  register int i = count; + +  while (i-- > 0) +    *t++ = *f++; +} + +#endif +#endif + +#line 217 "/usr/lib/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed +   into yyparse.  The argument should have type void *. +   It should actually point to an object. +   Grammar actions can access the variable by casting it +   to the proper pointer type.  */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes.  */ +#ifdef __GNUC__ +#ifdef YYPARSE_PARAM +int yyparse (void *); +#else +int yyparse (void); +#endif +#endif + +int +yyparse(YYPARSE_PARAM_ARG) +     YYPARSE_PARAM_DECL +{ +  register int yystate; +  register int yyn; +  register short *yyssp; +  register YYSTYPE *yyvsp; +  int yyerrstatus;	/*  number of tokens to shift before error messages enabled */ +  int yychar1 = 0;		/*  lookahead token as an internal (translated) token number */ + +  short	yyssa[YYINITDEPTH];	/*  the state stack			*/ +  YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/ + +  short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */ +  YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED +  YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/ +  YYLTYPE *yyls = yylsa; +  YYLTYPE *yylsp; + +#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK   (yyvsp--, yyssp--) +#endif + +  int yystacksize = YYINITDEPTH; +  int yyfree_stacks = 0; + +#ifdef YYPURE +  int yychar; +  YYSTYPE yylval; +  int yynerrs; +#ifdef YYLSP_NEEDED +  YYLTYPE yylloc; +#endif +#endif + +  YYSTYPE yyval;		/*  the variable used to return		*/ +				/*  semantic values from the action	*/ +				/*  routines				*/ + +  int yylen; + +#if YYDEBUG != 0 +  if (yydebug) +    fprintf(stderr, "Starting parse\n"); +#endif + +  yystate = 0; +  yyerrstatus = 0; +  yynerrs = 0; +  yychar = YYEMPTY;		/* Cause a token to be read.  */ + +  /* Initialize stack pointers. +     Waste one element of value and location stack +     so that they stay on the same level as the state stack. +     The wasted elements are never initialized.  */ + +  yyssp = yyss - 1; +  yyvsp = yyvs; +#ifdef YYLSP_NEEDED +  yylsp = yyls; +#endif + +/* Push a new state, which is found in  yystate  .  */ +/* In all cases, when you get here, the value and location stacks +   have just been pushed. so pushing a state here evens the stacks.  */ +yynewstate: + +  *++yyssp = yystate; + +  if (yyssp >= yyss + yystacksize - 1) +    { +      /* Give user a chance to reallocate the stack */ +      /* Use copies of these so that the &'s don't force the real ones into memory. */ +      YYSTYPE *yyvs1 = yyvs; +      short *yyss1 = yyss; +#ifdef YYLSP_NEEDED +      YYLTYPE *yyls1 = yyls; +#endif + +      /* Get the current used size of the three stacks, in elements.  */ +      int size = yyssp - yyss + 1; + +#ifdef yyoverflow +      /* Each stack pointer address is followed by the size of +	 the data in use in that stack, in bytes.  */ +#ifdef YYLSP_NEEDED +      /* This used to be a conditional around just the two extra args, +	 but that might be undefined if yyoverflow is a macro.  */ +      yyoverflow("parser stack overflow", +		 &yyss1, size * sizeof (*yyssp), +		 &yyvs1, size * sizeof (*yyvsp), +		 &yyls1, size * sizeof (*yylsp), +		 &yystacksize); +#else +      yyoverflow("parser stack overflow", +		 &yyss1, size * sizeof (*yyssp), +		 &yyvs1, size * sizeof (*yyvsp), +		 &yystacksize); +#endif + +      yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED +      yyls = yyls1; +#endif +#else /* no yyoverflow */ +      /* Extend the stack our own way.  */ +      if (yystacksize >= YYMAXDEPTH) +	{ +	  yyerror("parser stack overflow"); +	  if (yyfree_stacks) +	    { +	      free (yyss); +	      free (yyvs); +#ifdef YYLSP_NEEDED +	      free (yyls); +#endif +	    } +	  return 2; +	} +      yystacksize *= 2; +      if (yystacksize > YYMAXDEPTH) +	yystacksize = YYMAXDEPTH; +#ifndef YYSTACK_USE_ALLOCA +      yyfree_stacks = 1; +#endif +      yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); +      __yy_memcpy ((char *)yyss, (char *)yyss1, +		   size * (unsigned int) sizeof (*yyssp)); +      yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); +      __yy_memcpy ((char *)yyvs, (char *)yyvs1, +		   size * (unsigned int) sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED +      yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); +      __yy_memcpy ((char *)yyls, (char *)yyls1, +		   size * (unsigned int) sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + +      yyssp = yyss + size - 1; +      yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED +      yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 +      if (yydebug) +	fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + +      if (yyssp >= yyss + yystacksize - 1) +	YYABORT; +    } + +#if YYDEBUG != 0 +  if (yydebug) +    fprintf(stderr, "Entering state %d\n", yystate); +#endif + +  goto yybackup; + yybackup: + +/* Do appropriate processing given the current state.  */ +/* Read a lookahead token if we need one and don't already have one.  */ +/* yyresume: */ + +  /* First try to decide what to do without reference to lookahead token.  */ + +  yyn = yypact[yystate]; +  if (yyn == YYFLAG) +    goto yydefault; + +  /* Not known => get a lookahead token if don't already have one.  */ + +  /* yychar is either YYEMPTY or YYEOF +     or a valid token in external form.  */ + +  if (yychar == YYEMPTY) +    { +#if YYDEBUG != 0 +      if (yydebug) +	fprintf(stderr, "Reading a token: "); +#endif +      yychar = YYLEX; +    } + +  /* Convert token to internal form (in yychar1) for indexing tables with */ + +  if (yychar <= 0)		/* This means end of input. */ +    { +      yychar1 = 0; +      yychar = YYEOF;		/* Don't call YYLEX any more */ + +#if YYDEBUG != 0 +      if (yydebug) +	fprintf(stderr, "Now at end of input.\n"); +#endif +    } +  else +    { +      yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 +      if (yydebug) +	{ +	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); +	  /* Give the individual parser a way to print the precise meaning +	     of a token, for further debugging info.  */ +#ifdef YYPRINT +	  YYPRINT (stderr, yychar, yylval); +#endif +	  fprintf (stderr, ")\n"); +	} +#endif +    } + +  yyn += yychar1; +  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) +    goto yydefault; + +  yyn = yytable[yyn]; + +  /* yyn is what to do for this token type in this state. +     Negative => reduce, -yyn is rule number. +     Positive => shift, yyn is new state. +       New state is final state => don't bother to shift, +       just return success. +     0, or most negative number => error.  */ + +  if (yyn < 0) +    { +      if (yyn == YYFLAG) +	goto yyerrlab; +      yyn = -yyn; +      goto yyreduce; +    } +  else if (yyn == 0) +    goto yyerrlab; + +  if (yyn == YYFINAL) +    YYACCEPT; + +  /* Shift the lookahead token.  */ + +#if YYDEBUG != 0 +  if (yydebug) +    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + +  /* Discard the token being shifted unless it is eof.  */ +  if (yychar != YYEOF) +    yychar = YYEMPTY; + +  *++yyvsp = yylval; +#ifdef YYLSP_NEEDED +  *++yylsp = yylloc; +#endif + +  /* count tokens shifted since error; after three, turn off error status.  */ +  if (yyerrstatus) yyerrstatus--; + +  yystate = yyn; +  goto yynewstate; + +/* Do the default action for the current state.  */ +yydefault: + +  yyn = yydefact[yystate]; +  if (yyn == 0) +    goto yyerrlab; + +/* Do a reduction.  yyn is the number of a rule to reduce with.  */ +yyreduce: +  yylen = yyr2[yyn]; +  if (yylen > 0) +    yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 +  if (yydebug) +    { +      int i; + +      fprintf (stderr, "Reducing via rule %d (line %d), ", +	       yyn, yyrline[yyn]); + +      /* Print the symbols being reduced, and their result.  */ +      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) +	fprintf (stderr, "%s ", yytname[yyrhs[i]]); +      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); +    } +#endif + + +  switch (yyn) { + +case 3: +#line 107 "scripts/genksyms/parse.y" +{ is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; ; +    break;} +case 4: +#line 109 "scripts/genksyms/parse.y" +{ free_list(*yyvsp[0], NULL); *yyvsp[0] = NULL; ; +    break;} +case 5: +#line 113 "scripts/genksyms/parse.y" +{ is_typedef = 1; ; +    break;} +case 6: +#line 114 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 11: +#line 119 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 12: +#line 120 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 13: +#line 125 "scripts/genksyms/parse.y" +{ if (current_name) { +		    struct string_list *decl = (*yyvsp[0])->next; +		    (*yyvsp[0])->next = NULL; +		    add_symbol(current_name, +			       is_typedef ? SYM_TYPEDEF : SYM_NORMAL, +			       decl, is_extern); +		    current_name = NULL; +		  } +		  yyval = yyvsp[0]; +		; +    break;} +case 14: +#line 138 "scripts/genksyms/parse.y" +{ yyval = NULL; ; +    break;} +case 16: +#line 144 "scripts/genksyms/parse.y" +{ struct string_list *decl = *yyvsp[0]; +		  *yyvsp[0] = NULL; +		  add_symbol(current_name, +			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); +		  current_name = NULL; +		  yyval = yyvsp[0]; +		; +    break;} +case 17: +#line 152 "scripts/genksyms/parse.y" +{ struct string_list *decl = *yyvsp[0]; +		  *yyvsp[0] = NULL; +		  free_list(*yyvsp[-1], NULL); +		  *yyvsp[-1] = decl_spec; +		  add_symbol(current_name, +			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); +		  current_name = NULL; +		  yyval = yyvsp[0]; +		; +    break;} +case 18: +#line 165 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1] ? yyvsp[-1] : yyvsp[-2] ? yyvsp[-2] : yyvsp[-3]; ; +    break;} +case 19: +#line 170 "scripts/genksyms/parse.y" +{ decl_spec = NULL; ; +    break;} +case 21: +#line 175 "scripts/genksyms/parse.y" +{ decl_spec = *yyvsp[0]; ; +    break;} +case 22: +#line 176 "scripts/genksyms/parse.y" +{ decl_spec = *yyvsp[0]; ; +    break;} +case 23: +#line 181 "scripts/genksyms/parse.y" +{ /* Version 2 checksumming ignores storage class, as that +		     is really irrelevant to the linkage.  */ +		  remove_node(yyvsp[0]); +		  yyval = yyvsp[0]; +		; +    break;} +case 28: +#line 193 "scripts/genksyms/parse.y" +{ is_extern = 1; yyval = yyvsp[0]; ; +    break;} +case 29: +#line 194 "scripts/genksyms/parse.y" +{ is_extern = 0; yyval = yyvsp[0]; ; +    break;} +case 33: +#line 205 "scripts/genksyms/parse.y" +{ remove_node(yyvsp[-1]); (*yyvsp[0])->tag = SYM_STRUCT; yyval = yyvsp[0]; ; +    break;} +case 34: +#line 207 "scripts/genksyms/parse.y" +{ remove_node(yyvsp[-1]); (*yyvsp[0])->tag = SYM_UNION; yyval = yyvsp[0]; ; +    break;} +case 35: +#line 209 "scripts/genksyms/parse.y" +{ remove_node(yyvsp[-1]); (*yyvsp[0])->tag = SYM_ENUM; yyval = yyvsp[0]; ; +    break;} +case 36: +#line 213 "scripts/genksyms/parse.y" +{ struct string_list *s = *yyvsp[0], *i = *yyvsp[-1], *r; +		  r = copy_node(i); r->tag = SYM_STRUCT; +		  r->next = (*yyvsp[-2])->next; *yyvsp[0] = r; (*yyvsp[-2])->next = NULL; +		  add_symbol(i->string, SYM_STRUCT, s, is_extern); +		  yyval = yyvsp[0]; +		; +    break;} +case 37: +#line 220 "scripts/genksyms/parse.y" +{ struct string_list *s = *yyvsp[0], *i = *yyvsp[-1], *r; +		  r = copy_node(i); r->tag = SYM_UNION; +		  r->next = (*yyvsp[-2])->next; *yyvsp[0] = r; (*yyvsp[-2])->next = NULL; +		  add_symbol(i->string, SYM_UNION, s, is_extern); +		  yyval = yyvsp[0]; +		; +    break;} +case 38: +#line 227 "scripts/genksyms/parse.y" +{ struct string_list *s = *yyvsp[0], *i = *yyvsp[-1], *r; +		  r = copy_node(i); r->tag = SYM_ENUM; +		  r->next = (*yyvsp[-2])->next; *yyvsp[0] = r; (*yyvsp[-2])->next = NULL; +		  add_symbol(i->string, SYM_ENUM, s, is_extern); +		  yyval = yyvsp[0]; +		; +    break;} +case 39: +#line 235 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 40: +#line 236 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 41: +#line 237 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 52: +#line 251 "scripts/genksyms/parse.y" +{ (*yyvsp[0])->tag = SYM_TYPEDEF; yyval = yyvsp[0]; ; +    break;} +case 53: +#line 256 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1]; ; +    break;} +case 54: +#line 260 "scripts/genksyms/parse.y" +{ yyval = NULL; ; +    break;} +case 57: +#line 266 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 61: +#line 272 "scripts/genksyms/parse.y" +{ /* restrict has no effect in prototypes so ignore it */ +		  remove_node(yyvsp[0]); +		  yyval = yyvsp[0]; +		; +    break;} +case 62: +#line 279 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 64: +#line 285 "scripts/genksyms/parse.y" +{ if (current_name != NULL) { +		    error_with_pos("unexpected second declaration name"); +		    YYERROR; +		  } else { +		    current_name = (*yyvsp[0])->string; +		    yyval = yyvsp[0]; +		  } +		; +    break;} +case 65: +#line 294 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 66: +#line 296 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 67: +#line 298 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 68: +#line 300 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 69: +#line 302 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 70: +#line 308 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 74: +#line 316 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 75: +#line 318 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 76: +#line 320 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 77: +#line 322 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 78: +#line 324 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 79: +#line 328 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 81: +#line 330 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 82: +#line 334 "scripts/genksyms/parse.y" +{ yyval = NULL; ; +    break;} +case 85: +#line 341 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 86: +#line 346 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1]; ; +    break;} +case 87: +#line 351 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1]; ; +    break;} +case 89: +#line 356 "scripts/genksyms/parse.y" +{ yyval = NULL; ; +    break;} +case 90: +#line 358 "scripts/genksyms/parse.y" +{ /* For version 2 checksums, we don't want to remember +		     private parameter names.  */ +		  remove_node(yyvsp[0]); +		  yyval = yyvsp[0]; +		; +    break;} +case 91: +#line 366 "scripts/genksyms/parse.y" +{ remove_node(yyvsp[0]); +		  yyval = yyvsp[0]; +		; +    break;} +case 92: +#line 370 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 93: +#line 372 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 94: +#line 374 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 95: +#line 376 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 96: +#line 378 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 97: +#line 383 "scripts/genksyms/parse.y" +{ struct string_list *decl = *yyvsp[-1]; +		  *yyvsp[-1] = NULL; +		  add_symbol(current_name, SYM_NORMAL, decl, is_extern); +		  yyval = yyvsp[0]; +		; +    break;} +case 98: +#line 391 "scripts/genksyms/parse.y" +{ yyval = NULL; ; +    break;} +case 100: +#line 398 "scripts/genksyms/parse.y" +{ remove_list(yyvsp[0], &(*yyvsp[-1])->next); yyval = yyvsp[0]; ; +    break;} +case 101: +#line 402 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 102: +#line 403 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 103: +#line 407 "scripts/genksyms/parse.y" +{ yyval = NULL; ; +    break;} +case 106: +#line 413 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 107: +#line 418 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 108: +#line 420 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 109: +#line 424 "scripts/genksyms/parse.y" +{ yyval = NULL; ; +    break;} +case 112: +#line 430 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 113: +#line 434 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1]; ; +    break;} +case 114: +#line 435 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 116: +#line 440 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 117: +#line 444 "scripts/genksyms/parse.y" +{ yyval = NULL; ; +    break;} +case 119: +#line 449 "scripts/genksyms/parse.y" +{ yyval = yyvsp[0]; ; +    break;} +case 120: +#line 453 "scripts/genksyms/parse.y" +{ yyval = NULL; ; +    break;} +case 122: +#line 459 "scripts/genksyms/parse.y" +{ export_symbol((*yyvsp[-2])->string); yyval = yyvsp[0]; ; +    break;} +} +   /* the action file gets copied in in place of this dollarsign */ +#line 543 "/usr/lib/bison.simple" + +  yyvsp -= yylen; +  yyssp -= yylen; +#ifdef YYLSP_NEEDED +  yylsp -= yylen; +#endif + +#if YYDEBUG != 0 +  if (yydebug) +    { +      short *ssp1 = yyss - 1; +      fprintf (stderr, "state stack now"); +      while (ssp1 != yyssp) +	fprintf (stderr, " %d", *++ssp1); +      fprintf (stderr, "\n"); +    } +#endif + +  *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED +  yylsp++; +  if (yylen == 0) +    { +      yylsp->first_line = yylloc.first_line; +      yylsp->first_column = yylloc.first_column; +      yylsp->last_line = (yylsp-1)->last_line; +      yylsp->last_column = (yylsp-1)->last_column; +      yylsp->text = 0; +    } +  else +    { +      yylsp->last_line = (yylsp+yylen-1)->last_line; +      yylsp->last_column = (yylsp+yylen-1)->last_column; +    } +#endif + +  /* Now "shift" the result of the reduction. +     Determine what state that goes to, +     based on the state we popped back to +     and the rule number reduced by.  */ + +  yyn = yyr1[yyn]; + +  yystate = yypgoto[yyn - YYNTBASE] + *yyssp; +  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) +    yystate = yytable[yystate]; +  else +    yystate = yydefgoto[yyn - YYNTBASE]; + +  goto yynewstate; + +yyerrlab:   /* here on detecting error */ + +  if (! yyerrstatus) +    /* If not already recovering from an error, report this error.  */ +    { +      ++yynerrs; + +#ifdef YYERROR_VERBOSE +      yyn = yypact[yystate]; + +      if (yyn > YYFLAG && yyn < YYLAST) +	{ +	  int size = 0; +	  char *msg; +	  int x, count; + +	  count = 0; +	  /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */ +	  for (x = (yyn < 0 ? -yyn : 0); +	       x < (sizeof(yytname) / sizeof(char *)); x++) +	    if (yycheck[x + yyn] == x) +	      size += strlen(yytname[x]) + 15, count++; +	  msg = (char *) malloc(size + 15); +	  if (msg != 0) +	    { +	      strcpy(msg, "parse error"); + +	      if (count < 5) +		{ +		  count = 0; +		  for (x = (yyn < 0 ? -yyn : 0); +		       x < (sizeof(yytname) / sizeof(char *)); x++) +		    if (yycheck[x + yyn] == x) +		      { +			strcat(msg, count == 0 ? ", expecting `" : " or `"); +			strcat(msg, yytname[x]); +			strcat(msg, "'"); +			count++; +		      } +		} +	      yyerror(msg); +	      free(msg); +	    } +	  else +	    yyerror ("parse error; also virtual memory exceeded"); +	} +      else +#endif /* YYERROR_VERBOSE */ +	yyerror("parse error"); +    } + +  goto yyerrlab1; +yyerrlab1:   /* here on error raised explicitly by an action */ + +  if (yyerrstatus == 3) +    { +      /* if just tried and failed to reuse lookahead token after an error, discard it.  */ + +      /* return failure if at end of input */ +      if (yychar == YYEOF) +	YYABORT; + +#if YYDEBUG != 0 +      if (yydebug) +	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + +      yychar = YYEMPTY; +    } + +  /* Else will try to reuse lookahead token +     after shifting the error token.  */ + +  yyerrstatus = 3;		/* Each real token shifted decrements this */ + +  goto yyerrhandle; + +yyerrdefault:  /* current state does not do anything special for the error token. */ + +#if 0 +  /* This is wrong; only states that explicitly want error tokens +     should shift them.  */ +  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/ +  if (yyn) goto yydefault; +#endif + +yyerrpop:   /* pop the current state because it cannot handle the error token */ + +  if (yyssp == yyss) YYABORT; +  yyvsp--; +  yystate = *--yyssp; +#ifdef YYLSP_NEEDED +  yylsp--; +#endif + +#if YYDEBUG != 0 +  if (yydebug) +    { +      short *ssp1 = yyss - 1; +      fprintf (stderr, "Error: state stack now"); +      while (ssp1 != yyssp) +	fprintf (stderr, " %d", *++ssp1); +      fprintf (stderr, "\n"); +    } +#endif + +yyerrhandle: + +  yyn = yypact[yystate]; +  if (yyn == YYFLAG) +    goto yyerrdefault; + +  yyn += YYTERROR; +  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) +    goto yyerrdefault; + +  yyn = yytable[yyn]; +  if (yyn < 0) +    { +      if (yyn == YYFLAG) +	goto yyerrpop; +      yyn = -yyn; +      goto yyreduce; +    } +  else if (yyn == 0) +    goto yyerrpop; + +  if (yyn == YYFINAL) +    YYACCEPT; + +#if YYDEBUG != 0 +  if (yydebug) +    fprintf(stderr, "Shifting error token, "); +#endif + +  *++yyvsp = yylval; +#ifdef YYLSP_NEEDED +  *++yylsp = yylloc; +#endif + +  yystate = yyn; +  goto yynewstate; + + yyacceptlab: +  /* YYACCEPT comes here.  */ +  if (yyfree_stacks) +    { +      free (yyss); +      free (yyvs); +#ifdef YYLSP_NEEDED +      free (yyls); +#endif +    } +  return 0; + + yyabortlab: +  /* YYABORT comes here.  */ +  if (yyfree_stacks) +    { +      free (yyss); +      free (yyvs); +#ifdef YYLSP_NEEDED +      free (yyls); +#endif +    } +  return 1; +} +#line 463 "scripts/genksyms/parse.y" + + +static void +yyerror(const char *e) +{ +  error_with_pos("%s", e); +} diff --git a/scripts/genksyms/parse.h_shipped b/scripts/genksyms/parse.h_shipped new file mode 100644 index 000000000000..d5b27e3b20c4 --- /dev/null +++ b/scripts/genksyms/parse.h_shipped @@ -0,0 +1,46 @@ +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#define	ASM_KEYW	257 +#define	ATTRIBUTE_KEYW	258 +#define	AUTO_KEYW	259 +#define	BOOL_KEYW	260 +#define	CHAR_KEYW	261 +#define	CONST_KEYW	262 +#define	DOUBLE_KEYW	263 +#define	ENUM_KEYW	264 +#define	EXTERN_KEYW	265 +#define	FLOAT_KEYW	266 +#define	INLINE_KEYW	267 +#define	INT_KEYW	268 +#define	LONG_KEYW	269 +#define	REGISTER_KEYW	270 +#define	RESTRICT_KEYW	271 +#define	SHORT_KEYW	272 +#define	SIGNED_KEYW	273 +#define	STATIC_KEYW	274 +#define	STRUCT_KEYW	275 +#define	TYPEDEF_KEYW	276 +#define	UNION_KEYW	277 +#define	UNSIGNED_KEYW	278 +#define	VOID_KEYW	279 +#define	VOLATILE_KEYW	280 +#define	TYPEOF_KEYW	281 +#define	EXPORT_SYMBOL_KEYW	282 +#define	ASM_PHRASE	283 +#define	ATTRIBUTE_PHRASE	284 +#define	BRACE_PHRASE	285 +#define	BRACKET_PHRASE	286 +#define	EXPRESSION_PHRASE	287 +#define	CHAR	288 +#define	DOTS	289 +#define	IDENT	290 +#define	INT	291 +#define	REAL	292 +#define	STRING	293 +#define	TYPE	294 +#define	OTHER	295 +#define	FILENAME	296 + + +extern YYSTYPE yylval; diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y new file mode 100644 index 000000000000..099043713db4 --- /dev/null +++ b/scripts/genksyms/parse.y @@ -0,0 +1,469 @@ +/* C global declaration parser for genksyms. +   Copyright 1996, 1997 Linux International. + +   New implementation contributed by Richard Henderson <rth@tamu.edu> +   Based on original work by Bjorn Ekwall <bj0rn@blox.se> + +   This file is part of the Linux modutils. + +   This program is free software; you can redistribute it and/or modify it +   under the terms of the GNU General Public License as published by the +   Free Software Foundation; either version 2 of the License, or (at your +   option) any later version. + +   This program is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software Foundation, +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ + + +%{ + +#include <assert.h> +#include <malloc.h> +#include "genksyms.h" + +static int is_typedef; +static int is_extern; +static char *current_name; +static struct string_list *decl_spec; + +static void yyerror(const char *); + +static inline void +remove_node(struct string_list **p) +{ +  struct string_list *node = *p; +  *p = node->next; +  free_node(node); +} + +static inline void +remove_list(struct string_list **pb, struct string_list **pe) +{ +  struct string_list *b = *pb, *e = *pe; +  *pb = e; +  free_list(b, e); +} + +%} + +%token ASM_KEYW +%token ATTRIBUTE_KEYW +%token AUTO_KEYW +%token BOOL_KEYW +%token CHAR_KEYW +%token CONST_KEYW +%token DOUBLE_KEYW +%token ENUM_KEYW +%token EXTERN_KEYW +%token FLOAT_KEYW +%token INLINE_KEYW +%token INT_KEYW +%token LONG_KEYW +%token REGISTER_KEYW +%token RESTRICT_KEYW +%token SHORT_KEYW +%token SIGNED_KEYW +%token STATIC_KEYW +%token STRUCT_KEYW +%token TYPEDEF_KEYW +%token UNION_KEYW +%token UNSIGNED_KEYW +%token VOID_KEYW +%token VOLATILE_KEYW +%token TYPEOF_KEYW + +%token EXPORT_SYMBOL_KEYW + +%token ASM_PHRASE +%token ATTRIBUTE_PHRASE +%token BRACE_PHRASE +%token BRACKET_PHRASE +%token EXPRESSION_PHRASE + +%token CHAR +%token DOTS +%token IDENT +%token INT +%token REAL +%token STRING +%token TYPE +%token OTHER +%token FILENAME + +%% + +declaration_seq: +	declaration +	| declaration_seq declaration +	; + +declaration: +	{ is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; } +	declaration1 +	{ free_list(*$2, NULL); *$2 = NULL; } +	; + +declaration1: +	TYPEDEF_KEYW { is_typedef = 1; } simple_declaration +		{ $$ = $3; } +	| simple_declaration +	| function_definition +	| asm_definition +	| export_definition +	| error ';'				{ $$ = $2; } +	| error '}'				{ $$ = $2; } +	; + +simple_declaration: +	decl_specifier_seq_opt init_declarator_list_opt ';' +		{ if (current_name) { +		    struct string_list *decl = (*$3)->next; +		    (*$3)->next = NULL; +		    add_symbol(current_name, +			       is_typedef ? SYM_TYPEDEF : SYM_NORMAL, +			       decl, is_extern); +		    current_name = NULL; +		  } +		  $$ = $3; +		} +	; + +init_declarator_list_opt: +	/* empty */				{ $$ = NULL; } +	| init_declarator_list +	; + +init_declarator_list: +	init_declarator +		{ struct string_list *decl = *$1; +		  *$1 = NULL; +		  add_symbol(current_name, +			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); +		  current_name = NULL; +		  $$ = $1; +		} +	| init_declarator_list ',' init_declarator +		{ struct string_list *decl = *$3; +		  *$3 = NULL; +		  free_list(*$2, NULL); +		  *$2 = decl_spec; +		  add_symbol(current_name, +			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); +		  current_name = NULL; +		  $$ = $3; +		} +	; + +init_declarator: +	declarator asm_phrase_opt attribute_opt initializer_opt +		{ $$ = $4 ? $4 : $3 ? $3 : $2 ? $2 : $1; } +	; + +/* Hang on to the specifiers so that we can reuse them.  */ +decl_specifier_seq_opt: +	/* empty */				{ decl_spec = NULL; } +	| decl_specifier_seq +	; + +decl_specifier_seq: +	decl_specifier				{ decl_spec = *$1; } +	| decl_specifier_seq decl_specifier	{ decl_spec = *$2; } +	; + +decl_specifier: +	storage_class_specifier +		{ /* Version 2 checksumming ignores storage class, as that +		     is really irrelevant to the linkage.  */ +		  remove_node($1); +		  $$ = $1; +		} +	| type_specifier +	; + +storage_class_specifier: +	AUTO_KEYW +	| REGISTER_KEYW +	| STATIC_KEYW +	| EXTERN_KEYW	{ is_extern = 1; $$ = $1; } +	| INLINE_KEYW	{ is_extern = 0; $$ = $1; } +	; + +type_specifier: +	simple_type_specifier +	| cvar_qualifier +	| TYPEOF_KEYW '(' decl_specifier_seq ')' + +	/* References to s/u/e's defined elsewhere.  Rearrange things +	   so that it is easier to expand the definition fully later.  */ +	| STRUCT_KEYW IDENT +		{ remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; } +	| UNION_KEYW IDENT +		{ remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; } +	| ENUM_KEYW IDENT +		{ remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; } + +	/* Full definitions of an s/u/e.  Record it.  */ +	| STRUCT_KEYW IDENT class_body +		{ struct string_list *s = *$3, *i = *$2, *r; +		  r = copy_node(i); r->tag = SYM_STRUCT; +		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; +		  add_symbol(i->string, SYM_STRUCT, s, is_extern); +		  $$ = $3; +		} +	| UNION_KEYW IDENT class_body +		{ struct string_list *s = *$3, *i = *$2, *r; +		  r = copy_node(i); r->tag = SYM_UNION; +		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; +		  add_symbol(i->string, SYM_UNION, s, is_extern); +		  $$ = $3; +		} +	| ENUM_KEYW IDENT BRACE_PHRASE +		{ struct string_list *s = *$3, *i = *$2, *r; +		  r = copy_node(i); r->tag = SYM_ENUM; +		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL; +		  add_symbol(i->string, SYM_ENUM, s, is_extern); +		  $$ = $3; +		} + +	/* Anonymous s/u/e definitions.  Nothing needs doing.  */ +	| ENUM_KEYW BRACE_PHRASE			{ $$ = $2; } +	| STRUCT_KEYW class_body			{ $$ = $2; } +	| UNION_KEYW class_body				{ $$ = $2; } +	; + +simple_type_specifier: +	CHAR_KEYW +	| SHORT_KEYW +	| INT_KEYW +	| LONG_KEYW +	| SIGNED_KEYW +	| UNSIGNED_KEYW +	| FLOAT_KEYW +	| DOUBLE_KEYW +	| VOID_KEYW +	| BOOL_KEYW +	| TYPE			{ (*$1)->tag = SYM_TYPEDEF; $$ = $1; } +	; + +ptr_operator: +	'*' cvar_qualifier_seq_opt +		{ $$ = $2 ? $2 : $1; } +	; + +cvar_qualifier_seq_opt: +	/* empty */					{ $$ = NULL; } +	| cvar_qualifier_seq +	; + +cvar_qualifier_seq: +	cvar_qualifier +	| cvar_qualifier_seq cvar_qualifier		{ $$ = $2; } +	; + +cvar_qualifier: +	CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE +	| RESTRICT_KEYW +		{ /* restrict has no effect in prototypes so ignore it */ +		  remove_node($1); +		  $$ = $1; +		} +	; + +declarator: +	ptr_operator declarator			{ $$ = $2; } +	| direct_declarator +	; + +direct_declarator: +	IDENT +		{ if (current_name != NULL) { +		    error_with_pos("unexpected second declaration name"); +		    YYERROR; +		  } else { +		    current_name = (*$1)->string; +		    $$ = $1; +		  } +		} +	| direct_declarator '(' parameter_declaration_clause ')' +		{ $$ = $4; } +	| direct_declarator '(' error ')' +		{ $$ = $4; } +	| direct_declarator BRACKET_PHRASE +		{ $$ = $2; } +	| '(' declarator ')' +		{ $$ = $3; } +	| '(' error ')' +		{ $$ = $3; } +	; + +/* Nested declarators differ from regular declarators in that they do +   not record the symbols they find in the global symbol table.  */ +nested_declarator: +	ptr_operator nested_declarator		{ $$ = $2; } +	| direct_nested_declarator +	; + +direct_nested_declarator: +	IDENT +	| TYPE +	| direct_nested_declarator '(' parameter_declaration_clause ')' +		{ $$ = $4; } +	| direct_nested_declarator '(' error ')' +		{ $$ = $4; } +	| direct_nested_declarator BRACKET_PHRASE +		{ $$ = $2; } +	| '(' nested_declarator ')' +		{ $$ = $3; } +	| '(' error ')' +		{ $$ = $3; } +	; + +parameter_declaration_clause: +	parameter_declaration_list_opt DOTS		{ $$ = $2; } +	| parameter_declaration_list_opt +	| parameter_declaration_list ',' DOTS		{ $$ = $3; } +	; + +parameter_declaration_list_opt: +	/* empty */					{ $$ = NULL; } +	| parameter_declaration_list +	; + +parameter_declaration_list: +	parameter_declaration +	| parameter_declaration_list ',' parameter_declaration +		{ $$ = $3; } +	; + +parameter_declaration: +	decl_specifier_seq m_abstract_declarator +		{ $$ = $2 ? $2 : $1; } +	; + +m_abstract_declarator: +	ptr_operator m_abstract_declarator +		{ $$ = $2 ? $2 : $1; } +	| direct_m_abstract_declarator +	; + +direct_m_abstract_declarator: +	/* empty */					{ $$ = NULL; } +	| IDENT +		{ /* For version 2 checksums, we don't want to remember +		     private parameter names.  */ +		  remove_node($1); +		  $$ = $1; +		} +	/* This wasn't really a typedef name but an identifier that +	   shadows one.  */ +	| TYPE +		{ remove_node($1); +		  $$ = $1; +		} +	| direct_m_abstract_declarator '(' parameter_declaration_clause ')' +		{ $$ = $4; } +	| direct_m_abstract_declarator '(' error ')' +		{ $$ = $4; } +	| direct_m_abstract_declarator BRACKET_PHRASE +		{ $$ = $2; } +	| '(' m_abstract_declarator ')' +		{ $$ = $3; } +	| '(' error ')' +		{ $$ = $3; } +	; + +function_definition: +	decl_specifier_seq_opt declarator BRACE_PHRASE +		{ struct string_list *decl = *$2; +		  *$2 = NULL; +		  add_symbol(current_name, SYM_NORMAL, decl, is_extern); +		  $$ = $3; +		} +	; + +initializer_opt: +	/* empty */					{ $$ = NULL; } +	| initializer +	; + +/* We never care about the contents of an initializer.  */ +initializer: +	'=' EXPRESSION_PHRASE +		{ remove_list($2, &(*$1)->next); $$ = $2; } +	; + +class_body: +	'{' member_specification_opt '}'		{ $$ = $3; } +	| '{' error '}'					{ $$ = $3; } +	; + +member_specification_opt: +	/* empty */					{ $$ = NULL; } +	| member_specification +	; + +member_specification: +	member_declaration +	| member_specification member_declaration	{ $$ = $2; } +	; + +member_declaration: +	decl_specifier_seq_opt member_declarator_list_opt ';' +		{ $$ = $3; } +	| error ';' +		{ $$ = $2; } +	; + +member_declarator_list_opt: +	/* empty */					{ $$ = NULL; } +	| member_declarator_list +	; + +member_declarator_list: +	member_declarator +	| member_declarator_list ',' member_declarator	{ $$ = $3; } +	; + +member_declarator: +	nested_declarator attribute_opt			{ $$ = $2 ? $2 : $1; } +	| IDENT member_bitfield_declarator		{ $$ = $2; } +	| member_bitfield_declarator +	; + +member_bitfield_declarator: +	':' EXPRESSION_PHRASE				{ $$ = $2; } +	; + +attribute_opt: +	/* empty */					{ $$ = NULL; } +	| ATTRIBUTE_PHRASE +	; + +asm_definition: +	ASM_PHRASE ';'					{ $$ = $2; } +	; + +asm_phrase_opt: +	/* empty */					{ $$ = NULL; } +	| ASM_PHRASE +	; + +export_definition: +	EXPORT_SYMBOL_KEYW '(' IDENT ')' ';' +		{ export_symbol((*$3)->string); $$ = $5; } +	; + + +%% + +static void +yyerror(const char *e) +{ +  error_with_pos("%s", e); +} diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c new file mode 100644 index 000000000000..090ffda4adbc --- /dev/null +++ b/scripts/kallsyms.c @@ -0,0 +1,686 @@ +/* Generate assembler source containing symbol information + * + * Copyright 2002       by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * Usage: nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S + * + * ChangeLog: + * + * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com> + *      Changed the compression method from stem compression to "table lookup" + *      compression + * + *      Table compression uses all the unused char codes on the symbols and + *  maps these to the most used substrings (tokens). For instance, it might + *  map char code 0xF7 to represent "write_" and then in every symbol where + *  "write_" appears it can be replaced by 0xF7, saving 5 bytes. + *      The used codes themselves are also placed in the table so that the + *  decompresion can work without "special cases". + *      Applied to kernel symbols, this usually produces a compression ratio + *  of about 50%. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +/* maximum token length used. It doesn't pay to increase it a lot, because + * very long substrings probably don't repeat themselves too often. */ +#define MAX_TOK_SIZE		11 +#define KSYM_NAME_LEN		127 + +/* we use only a subset of the complete symbol table to gather the token count, + * to speed up compression, at the expense of a little compression ratio */ +#define WORKING_SET		1024 + +/* first find the best token only on the list of tokens that would profit more + * than GOOD_BAD_THRESHOLD. Only if this list is empty go to the "bad" list. + * Increasing this value will put less tokens on the "good" list, so the search + * is faster. However, if the good list runs out of tokens, we must painfully + * search the bad list. */ +#define GOOD_BAD_THRESHOLD	10 + +/* token hash parameters */ +#define HASH_BITS		18 +#define HASH_TABLE_SIZE		(1 << HASH_BITS) +#define HASH_MASK		(HASH_TABLE_SIZE - 1) +#define HASH_BASE_OFFSET	2166136261U +#define HASH_FOLD(a)		((a)&(HASH_MASK)) + +/* flags to mark symbols */ +#define SYM_FLAG_VALID		1 +#define SYM_FLAG_SAMPLED	2 + +struct sym_entry { +	unsigned long long addr; +	char type; +	unsigned char flags; +	unsigned char len; +	unsigned char *sym; +}; + + +static struct sym_entry *table; +static int size, cnt; +static unsigned long long _stext, _etext, _sinittext, _einittext; +static int all_symbols = 0; + +struct token { +	unsigned char data[MAX_TOK_SIZE]; +	unsigned char len; +	/* profit: the number of bytes that could be saved by inserting this +	 * token into the table */ +	int profit; +	struct token *next;	/* next token on the hash list */ +	struct token *right;	/* next token on the good/bad list */ +	struct token *left;    /* previous token on the good/bad list */ +	struct token *smaller; /* token that is less one letter than this one */ +	}; + +struct token bad_head, good_head; +struct token *hash_table[HASH_TABLE_SIZE]; + +/* the table that holds the result of the compression */ +unsigned char best_table[256][MAX_TOK_SIZE+1]; +unsigned char best_table_len[256]; + + +static void +usage(void) +{ +	fprintf(stderr, "Usage: kallsyms [--all-symbols] < in.map > out.S\n"); +	exit(1); +} + +/* + * This ignores the intensely annoying "mapping symbols" found + * in ARM ELF files: $a, $t and $d. + */ +static inline int +is_arm_mapping_symbol(const char *str) +{ +	return str[0] == '$' && strchr("atd", str[1]) +	       && (str[2] == '\0' || str[2] == '.'); +} + +static int +read_symbol(FILE *in, struct sym_entry *s) +{ +	char str[500]; +	int rc; + +	rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str); +	if (rc != 3) { +		if (rc != EOF) { +			/* skip line */ +			fgets(str, 500, in); +		} +		return -1; +	} + +	/* Ignore most absolute/undefined (?) symbols. */ +	if (strcmp(str, "_stext") == 0) +		_stext = s->addr; +	else if (strcmp(str, "_etext") == 0) +		_etext = s->addr; +	else if (strcmp(str, "_sinittext") == 0) +		_sinittext = s->addr; +	else if (strcmp(str, "_einittext") == 0) +		_einittext = s->addr; +	else if (toupper(s->type) == 'A') +	{ +		/* Keep these useful absolute symbols */ +		if (strcmp(str, "__kernel_syscall_via_break") && +		    strcmp(str, "__kernel_syscall_via_epc") && +		    strcmp(str, "__kernel_sigtramp") && +		    strcmp(str, "__gp")) +			return -1; + +	} +	else if (toupper(s->type) == 'U' || +		 is_arm_mapping_symbol(str)) +		return -1; + +	/* include the type field in the symbol name, so that it gets +	 * compressed together */ +	s->len = strlen(str) + 1; +	s->sym = (char *) malloc(s->len + 1); +	strcpy(s->sym + 1, str); +	s->sym[0] = s->type; + +	return 0; +} + +static int +symbol_valid(struct sym_entry *s) +{ +	/* Symbols which vary between passes.  Passes 1 and 2 must have +	 * identical symbol lists.  The kallsyms_* symbols below are only added +	 * after pass 1, they would be included in pass 2 when --all-symbols is +	 * specified so exclude them to get a stable symbol list. +	 */ +	static char *special_symbols[] = { +		"kallsyms_addresses", +		"kallsyms_num_syms", +		"kallsyms_names", +		"kallsyms_markers", +		"kallsyms_token_table", +		"kallsyms_token_index", + +	/* Exclude linker generated symbols which vary between passes */ +		"_SDA_BASE_",		/* ppc */ +		"_SDA2_BASE_",		/* ppc */ +		NULL }; +	int i; + +	/* if --all-symbols is not specified, then symbols outside the text +	 * and inittext sections are discarded */ +	if (!all_symbols) { +		if ((s->addr < _stext || s->addr > _etext) +		    && (s->addr < _sinittext || s->addr > _einittext)) +			return 0; +		/* Corner case.  Discard any symbols with the same value as +		 * _etext or _einittext, they can move between pass 1 and 2 +		 * when the kallsyms data is added.  If these symbols move then +		 * they may get dropped in pass 2, which breaks the kallsyms +		 * rules. +		 */ +		if ((s->addr == _etext && strcmp(s->sym + 1, "_etext")) || +		    (s->addr == _einittext && strcmp(s->sym + 1, "_einittext"))) +			return 0; +	} + +	/* Exclude symbols which vary between passes. */ +	if (strstr(s->sym + 1, "_compiled.")) +		return 0; + +	for (i = 0; special_symbols[i]; i++) +		if( strcmp(s->sym + 1, special_symbols[i]) == 0 ) +			return 0; + +	return 1; +} + +static void +read_map(FILE *in) +{ +	while (!feof(in)) { +		if (cnt >= size) { +			size += 10000; +			table = realloc(table, sizeof(*table) * size); +			if (!table) { +				fprintf(stderr, "out of memory\n"); +				exit (1); +			} +		} +		if (read_symbol(in, &table[cnt]) == 0) +			cnt++; +	} +} + +static void output_label(char *label) +{ +	printf(".globl %s\n",label); +	printf("\tALGN\n"); +	printf("%s:\n",label); +} + +/* uncompress a compressed symbol. When this function is called, the best table + * might still be compressed itself, so the function needs to be recursive */ +static int expand_symbol(unsigned char *data, int len, char *result) +{ +	int c, rlen, total=0; + +	while (len) { +		c = *data; +		/* if the table holds a single char that is the same as the one +		 * we are looking for, then end the search */ +		if (best_table[c][0]==c && best_table_len[c]==1) { +			*result++ = c; +			total++; +		} else { +			/* if not, recurse and expand */ +			rlen = expand_symbol(best_table[c], best_table_len[c], result); +			total += rlen; +			result += rlen; +		} +		data++; +		len--; +	} +	*result=0; + +	return total; +} + +static void +write_src(void) +{ +	int i, k, off, valid; +	unsigned int best_idx[256]; +	unsigned int *markers; +	char buf[KSYM_NAME_LEN+1]; + +	printf("#include <asm/types.h>\n"); +	printf("#if BITS_PER_LONG == 64\n"); +	printf("#define PTR .quad\n"); +	printf("#define ALGN .align 8\n"); +	printf("#else\n"); +	printf("#define PTR .long\n"); +	printf("#define ALGN .align 4\n"); +	printf("#endif\n"); + +	printf(".data\n"); + +	output_label("kallsyms_addresses"); +	valid = 0; +	for (i = 0; i < cnt; i++) { +		if (table[i].flags & SYM_FLAG_VALID) { +			printf("\tPTR\t%#llx\n", table[i].addr); +			valid++; +		} +	} +	printf("\n"); + +	output_label("kallsyms_num_syms"); +	printf("\tPTR\t%d\n", valid); +	printf("\n"); + +	/* table of offset markers, that give the offset in the compressed stream +	 * every 256 symbols */ +	markers = (unsigned int *) malloc(sizeof(unsigned int)*((valid + 255) / 256)); + +	output_label("kallsyms_names"); +	valid = 0; +	off = 0; +	for (i = 0; i < cnt; i++) { + +		if (!table[i].flags & SYM_FLAG_VALID) +			continue; + +		if ((valid & 0xFF) == 0) +			markers[valid >> 8] = off; + +		printf("\t.byte 0x%02x", table[i].len); +		for (k = 0; k < table[i].len; k++) +			printf(", 0x%02x", table[i].sym[k]); +		printf("\n"); + +		off += table[i].len + 1; +		valid++; +	} +	printf("\n"); + +	output_label("kallsyms_markers"); +	for (i = 0; i < ((valid + 255) >> 8); i++) +		printf("\tPTR\t%d\n", markers[i]); +	printf("\n"); + +	free(markers); + +	output_label("kallsyms_token_table"); +	off = 0; +	for (i = 0; i < 256; i++) { +		best_idx[i] = off; +		expand_symbol(best_table[i],best_table_len[i],buf); +		printf("\t.asciz\t\"%s\"\n", buf); +		off += strlen(buf) + 1; +	} +	printf("\n"); + +	output_label("kallsyms_token_index"); +	for (i = 0; i < 256; i++) +		printf("\t.short\t%d\n", best_idx[i]); +	printf("\n"); +} + + +/* table lookup compression functions */ + +static inline unsigned int rehash_token(unsigned int hash, unsigned char data) +{ +	return ((hash * 16777619) ^ data); +} + +static unsigned int hash_token(unsigned char *data, int len) +{ +	unsigned int hash=HASH_BASE_OFFSET; +	int i; + +	for (i = 0; i < len; i++) +		hash = rehash_token(hash, data[i]); + +	return HASH_FOLD(hash); +} + +/* find a token given its data and hash value */ +static struct token *find_token_hash(unsigned char *data, int len, unsigned int hash) +{ +	struct token *ptr; + +	ptr = hash_table[hash]; + +	while (ptr) { +		if ((ptr->len == len) && (memcmp(ptr->data, data, len) == 0)) +			return ptr; +		ptr=ptr->next; +	} + +	return NULL; +} + +static inline void insert_token_in_group(struct token *head, struct token *ptr) +{ +	ptr->right = head->right; +	ptr->right->left = ptr; +	head->right = ptr; +	ptr->left = head; +} + +static inline void remove_token_from_group(struct token *ptr) +{ +	ptr->left->right = ptr->right; +	ptr->right->left = ptr->left; +} + + +/* build the counts for all the tokens that start with "data", and have lenghts + * from 2 to "len" */ +static void learn_token(unsigned char *data, int len) +{ +	struct token *ptr,*last_ptr; +	int i, newprofit; +	unsigned int hash = HASH_BASE_OFFSET; +	unsigned int hashes[MAX_TOK_SIZE + 1]; + +	if (len > MAX_TOK_SIZE) +		len = MAX_TOK_SIZE; + +	/* calculate and store the hash values for all the sub-tokens */ +	hash = rehash_token(hash, data[0]); +	for (i = 2; i <= len; i++) { +		hash = rehash_token(hash, data[i-1]); +		hashes[i] = HASH_FOLD(hash); +	} + +	last_ptr = NULL; +	ptr = NULL; + +	for (i = len; i >= 2; i--) { +		hash = hashes[i]; + +		if (!ptr) ptr = find_token_hash(data, i, hash); + +		if (!ptr) { +			/* create a new token entry */ +			ptr = (struct token *) malloc(sizeof(*ptr)); + +			memcpy(ptr->data, data, i); +			ptr->len = i; + +			/* when we create an entry, it's profit is 0 because +			 * we also take into account the size of the token on +			 * the compressed table. We then subtract GOOD_BAD_THRESHOLD +			 * so that the test to see if this token belongs to +			 * the good or bad list, is a comparison to zero */ +			ptr->profit = -GOOD_BAD_THRESHOLD; + +			ptr->next = hash_table[hash]; +			hash_table[hash] = ptr; + +			insert_token_in_group(&bad_head, ptr); + +			ptr->smaller = NULL; +		} else { +			newprofit = ptr->profit + (ptr->len - 1); +			/* check to see if this token needs to be moved to a +			 * different list */ +			if((ptr->profit < 0) && (newprofit >= 0)) { +				remove_token_from_group(ptr); +				insert_token_in_group(&good_head,ptr); +			} +			ptr->profit = newprofit; +		} + +		if (last_ptr) last_ptr->smaller = ptr; +		last_ptr = ptr; + +		ptr = ptr->smaller; +	} +} + +/* decrease the counts for all the tokens that start with "data", and have lenghts + * from 2 to "len". This function is much simpler than learn_token because we have + * more guarantees (tho tokens exist, the ->smaller pointer is set, etc.) + * The two separate functions exist only because of compression performance */ +static void forget_token(unsigned char *data, int len) +{ +	struct token *ptr; +	int i, newprofit; +	unsigned int hash=0; + +	if (len > MAX_TOK_SIZE) len = MAX_TOK_SIZE; + +	hash = hash_token(data, len); +	ptr = find_token_hash(data, len, hash); + +	for (i = len; i >= 2; i--) { + +		newprofit = ptr->profit - (ptr->len - 1); +		if ((ptr->profit >= 0) && (newprofit < 0)) { +			remove_token_from_group(ptr); +			insert_token_in_group(&bad_head, ptr); +		} +		ptr->profit=newprofit; + +		ptr=ptr->smaller; +	} +} + +/* count all the possible tokens in a symbol */ +static void learn_symbol(unsigned char *symbol, int len) +{ +	int i; + +	for (i = 0; i < len - 1; i++) +		learn_token(symbol + i, len - i); +} + +/* decrease the count for all the possible tokens in a symbol */ +static void forget_symbol(unsigned char *symbol, int len) +{ +	int i; + +	for (i = 0; i < len - 1; i++) +		forget_token(symbol + i, len - i); +} + +/* set all the symbol flags and do the initial token count */ +static void build_initial_tok_table(void) +{ +	int i, use_it, valid; + +	valid = 0; +	for (i = 0; i < cnt; i++) { +		table[i].flags = 0; +		if ( symbol_valid(&table[i]) ) { +			table[i].flags |= SYM_FLAG_VALID; +			valid++; +		} +	} + +	use_it = 0; +	for (i = 0; i < cnt; i++) { + +		/* subsample the available symbols. This method is almost like +		 * a Bresenham's algorithm to get uniformly distributed samples +		 * across the symbol table */ +		if (table[i].flags & SYM_FLAG_VALID) { + +			use_it += WORKING_SET; + +			if (use_it >= valid) { +				table[i].flags |= SYM_FLAG_SAMPLED; +				use_it -= valid; +			} +		} +		if (table[i].flags & SYM_FLAG_SAMPLED) +			learn_symbol(table[i].sym, table[i].len); +	} +} + +/* replace a given token in all the valid symbols. Use the sampled symbols + * to update the counts */ +static void compress_symbols(unsigned char *str, int tlen, int idx) +{ +	int i, len, learn, size; +	unsigned char *p; + +	for (i = 0; i < cnt; i++) { + +		if (!(table[i].flags & SYM_FLAG_VALID)) continue; + +		len = table[i].len; +		learn = 0; +		p = table[i].sym; + +		do { +			/* find the token on the symbol */ +			p = (unsigned char *) strstr((char *) p, (char *) str); +			if (!p) break; + +			if (!learn) { +				/* if this symbol was used to count, decrease it */ +				if (table[i].flags & SYM_FLAG_SAMPLED) +					forget_symbol(table[i].sym, len); +				learn = 1; +			} + +			*p = idx; +			size = (len - (p - table[i].sym)) - tlen + 1; +			memmove(p + 1, p + tlen, size); +			p++; +			len -= tlen - 1; + +		} while (size >= tlen); + +		if(learn) { +			table[i].len = len; +			/* if this symbol was used to count, learn it again */ +			if(table[i].flags & SYM_FLAG_SAMPLED) +				learn_symbol(table[i].sym, len); +		} +	} +} + +/* search the token with the maximum profit */ +static struct token *find_best_token(void) +{ +	struct token *ptr,*best,*head; +	int bestprofit; + +	bestprofit=-10000; + +	/* failsafe: if the "good" list is empty search from the "bad" list */ +	if(good_head.right == &good_head) head = &bad_head; +	else head = &good_head; + +	ptr = head->right; +	best = NULL; +	while (ptr != head) { +		if (ptr->profit > bestprofit) { +			bestprofit = ptr->profit; +			best = ptr; +		} +		ptr = ptr->right; +	} + +	return best; +} + +/* this is the core of the algorithm: calculate the "best" table */ +static void optimize_result(void) +{ +	struct token *best; +	int i; + +	/* using the '\0' symbol last allows compress_symbols to use standard +	 * fast string functions */ +	for (i = 255; i >= 0; i--) { + +		/* if this table slot is empty (it is not used by an actual +		 * original char code */ +		if (!best_table_len[i]) { + +			/* find the token with the breates profit value */ +			best = find_best_token(); + +			/* place it in the "best" table */ +			best_table_len[i] = best->len; +			memcpy(best_table[i], best->data, best_table_len[i]); +			/* zero terminate the token so that we can use strstr +			   in compress_symbols */ +			best_table[i][best_table_len[i]]='\0'; + +			/* replace this token in all the valid symbols */ +			compress_symbols(best_table[i], best_table_len[i], i); +		} +	} +} + +/* start by placing the symbols that are actually used on the table */ +static void insert_real_symbols_in_table(void) +{ +	int i, j, c; + +	memset(best_table, 0, sizeof(best_table)); +	memset(best_table_len, 0, sizeof(best_table_len)); + +	for (i = 0; i < cnt; i++) { +		if (table[i].flags & SYM_FLAG_VALID) { +			for (j = 0; j < table[i].len; j++) { +				c = table[i].sym[j]; +				best_table[c][0]=c; +				best_table_len[c]=1; +			} +		} +	} +} + +static void optimize_token_table(void) +{ +	memset(hash_table, 0, sizeof(hash_table)); + +	good_head.left = &good_head; +	good_head.right = &good_head; + +	bad_head.left = &bad_head; +	bad_head.right = &bad_head; + +	build_initial_tok_table(); + +	insert_real_symbols_in_table(); + +	optimize_result(); +} + + +int +main(int argc, char **argv) +{ +	if (argc == 2 && strcmp(argv[1], "--all-symbols") == 0) +		all_symbols = 1; +	else if (argc != 1) +		usage(); + +	read_map(stdin); +	optimize_token_table(); +	write_src(); + +	return 0; +} + diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile new file mode 100644 index 000000000000..5a5ddc40f36c --- /dev/null +++ b/scripts/kconfig/Makefile @@ -0,0 +1,208 @@ +# =========================================================================== +# Kernel configuration targets +# These targets are used from top-level makefile + +.PHONY: oldconfig xconfig gconfig menuconfig config silentoldconfig + +xconfig: $(obj)/qconf +	$< arch/$(ARCH)/Kconfig + +gconfig: $(obj)/gconf +	$< arch/$(ARCH)/Kconfig + +menuconfig: $(obj)/mconf +	$(Q)$(MAKE) $(build)=scripts/lxdialog +	$< arch/$(ARCH)/Kconfig + +config: $(obj)/conf +	$< arch/$(ARCH)/Kconfig + +oldconfig: $(obj)/conf +	$< -o arch/$(ARCH)/Kconfig + +silentoldconfig: $(obj)/conf +	$< -s arch/$(ARCH)/Kconfig + +.PHONY: randconfig allyesconfig allnoconfig allmodconfig defconfig + +randconfig: $(obj)/conf +	$< -r arch/$(ARCH)/Kconfig + +allyesconfig: $(obj)/conf +	$< -y arch/$(ARCH)/Kconfig + +allnoconfig: $(obj)/conf +	$< -n arch/$(ARCH)/Kconfig + +allmodconfig: $(obj)/conf +	$< -m arch/$(ARCH)/Kconfig + +defconfig: $(obj)/conf +ifeq ($(KBUILD_DEFCONFIG),) +	$< -d arch/$(ARCH)/Kconfig +else +	@echo *** Default configuration is based on '$(KBUILD_DEFCONFIG)' +	$(Q)$< -D arch/$(ARCH)/configs/$(KBUILD_DEFCONFIG) arch/$(ARCH)/Kconfig +endif + +%_defconfig: $(obj)/conf +	$(Q)$< -D arch/$(ARCH)/configs/$@ arch/$(ARCH)/Kconfig + +# Help text used by make help +help: +	@echo  '  config	  - Update current config utilising a line-oriented program' +	@echo  '  menuconfig	  - Update current config utilising a menu based program' +	@echo  '  xconfig	  - Update current config utilising a QT based front-end' +	@echo  '  gconfig	  - Update current config utilising a GTK based front-end' +	@echo  '  oldconfig	  - Update current config utilising a provided .config as base' +	@echo  '  randconfig	  - New config with random answer to all options' +	@echo  '  defconfig	  - New config with default answer to all options' +	@echo  '  allmodconfig	  - New config selecting modules when possible' +	@echo  '  allyesconfig	  - New config where all options are accepted with yes' +	@echo  '  allnoconfig	  - New minimal config' + +# =========================================================================== +# Shared Makefile for the various kconfig executables: +# conf:	  Used for defconfig, oldconfig and related targets +# mconf:  Used for the mconfig target. +#         Utilizes the lxdialog package +# qconf:  Used for the xconfig target +#         Based on QT which needs to be installed to compile it +# gconf:  Used for the gconfig target +#         Based on GTK which needs to be installed to compile it +# object files used by all kconfig flavours + +hostprogs-y	:= conf mconf qconf gconf +conf-objs	:= conf.o  zconf.tab.o +mconf-objs	:= mconf.o zconf.tab.o + +ifeq ($(MAKECMDGOALS),xconfig) +	qconf-target := 1 +endif +ifeq ($(MAKECMDGOALS),gconfig) +	gconf-target := 1 +endif + + +ifeq ($(qconf-target),1) +qconf-cxxobjs	:= qconf.o +qconf-objs	:= kconfig_load.o zconf.tab.o +endif + +ifeq ($(gconf-target),1) +gconf-objs	:= gconf.o kconfig_load.o zconf.tab.o +endif + +clean-files	:= lkc_defs.h qconf.moc .tmp_qtcheck \ +		   .tmp_gtkcheck zconf.tab.c zconf.tab.h lex.zconf.c + +# generated files seem to need this to find local include files +HOSTCFLAGS_lex.zconf.o	:= -I$(src) +HOSTCFLAGS_zconf.tab.o	:= -I$(src) + +HOSTLOADLIBES_qconf	= -L$(QTLIBPATH) -Wl,-rpath,$(QTLIBPATH) -l$(QTLIB) -ldl +HOSTCXXFLAGS_qconf.o	= -I$(QTDIR)/include -D LKC_DIRECT_LINK + +HOSTLOADLIBES_gconf	= `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --libs` +HOSTCFLAGS_gconf.o	= `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --cflags` \ +                          -D LKC_DIRECT_LINK + +$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o $(obj)/gconf.o: $(obj)/zconf.tab.h + +$(obj)/zconf.tab.h: $(src)/zconf.tab.h_shipped +$(obj)/zconf.tab.c: $(src)/zconf.tab.c_shipped +$(obj)/lex.zconf.c: $(src)/lex.zconf.c_shipped + +$(obj)/qconf.o: $(obj)/.tmp_qtcheck + +ifeq ($(qconf-target),1) +MOC = $(QTDIR)/bin/moc +QTLIBPATH = $(QTDIR)/lib +-include $(obj)/.tmp_qtcheck + +# QT needs some extra effort... +$(obj)/.tmp_qtcheck: +	@set -e; for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ +	  if [ -f $$d/include/qconfig.h ]; then DIR=$$d; break; fi; \ +	done; \ +	if [ -z "$$DIR" ]; then \ +	  echo "*"; \ +	  echo "* Unable to find the QT installation. Please make sure that the"; \ +	  echo "* QT development package is correctly installed and the QTDIR"; \ +	  echo "* environment variable is set to the correct location."; \ +	  echo "*"; \ +	  false; \ +	fi; \ +	LIBPATH=$$DIR/lib; LIB=qt; \ +	$(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ +	  LIBPATH=$$DIR/lib/$$($(HOSTCXX) -print-multi-os-directory); \ +	if [ -f $$LIBPATH/libqt-mt.so ]; then LIB=qt-mt; fi; \ +	echo "QTDIR=$$DIR" > $@; echo "QTLIBPATH=$$LIBPATH" >> $@; \ +	echo "QTLIB=$$LIB" >> $@; \ +	if [ ! -x $$DIR/bin/moc -a -x /usr/bin/moc ]; then \ +	  echo "*"; \ +	  echo "* Unable to find $$DIR/bin/moc, using /usr/bin/moc instead."; \ +	  echo "*"; \ +	  echo "MOC=/usr/bin/moc" >> $@; \ +	fi +endif + +$(obj)/gconf.o: $(obj)/.tmp_gtkcheck + +ifeq ($(gconf-target),1) +-include $(obj)/.tmp_gtkcheck + +# GTK needs some extra effort, too... +$(obj)/.tmp_gtkcheck: +	@if `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --exists`; then		\ +		if `pkg-config gtk+-2.0 --atleast-version=2.0.0`; then			\ +			touch $@;								\ +		else									\ +			echo "*"; 							\ +			echo "* GTK+ is present but version >= 2.0.0 is required.";	\ +			echo "*";							\ +			false;								\ +		fi									\ +	else										\ +		echo "*"; 								\ +		echo "* Unable to find the GTK+ installation. Please make sure that"; 	\ +		echo "* the GTK+ 2.0 development package is correctly installed..."; 	\ +		echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; 		\ +		echo "*"; 								\ +		false;									\ +	fi +endif + +$(obj)/zconf.tab.o: $(obj)/lex.zconf.c + +$(obj)/kconfig_load.o: $(obj)/lkc_defs.h + +$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h + +$(obj)/gconf.o: $(obj)/lkc_defs.h + +$(obj)/%.moc: $(src)/%.h +	$(MOC) -i $< -o $@ + +$(obj)/lkc_defs.h: $(src)/lkc_proto.h +	sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' + + +### +# The following requires flex/bison +# By default we use the _shipped versions, uncomment the following line if +# you are modifying the flex/bison src. +# LKC_GENPARSER := 1 + +ifdef LKC_GENPARSER + +$(obj)/zconf.tab.c: $(obj)/zconf.y  +$(obj)/zconf.tab.h: $(obj)/zconf.tab.c + +%.tab.c: %.y +	bison -t -d -v -b $* -p $(notdir $*) $< + +lex.%.c: %.l +	flex -P$(notdir $*) -o$@ $< + +endif diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c new file mode 100644 index 000000000000..a494d1aeb9f9 --- /dev/null +++ b/scripts/kconfig/conf.c @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <sys/stat.h> + +#define LKC_DIRECT_LINK +#include "lkc.h" + +static void conf(struct menu *menu); +static void check_conf(struct menu *menu); + +enum { +	ask_all, +	ask_new, +	ask_silent, +	set_default, +	set_yes, +	set_mod, +	set_no, +	set_random +} input_mode = ask_all; +char *defconfig_file; + +static int indent = 1; +static int valid_stdin = 1; +static int conf_cnt; +static signed char line[128]; +static struct menu *rootEntry; + +static char nohelp_text[] = "Sorry, no help available for this option yet.\n"; + +static void strip(signed char *str) +{ +	signed char *p = str; +	int l; + +	while ((isspace(*p))) +		p++; +	l = strlen(p); +	if (p != str) +		memmove(str, p, l + 1); +	if (!l) +		return; +	p = str + l - 1; +	while ((isspace(*p))) +		*p-- = 0; +} + +static void check_stdin(void) +{ +	if (!valid_stdin && input_mode == ask_silent) { +		printf("aborted!\n\n"); +		printf("Console input/output is redirected. "); +		printf("Run 'make oldconfig' to update configuration.\n\n"); +		exit(1); +	} +} + +static void conf_askvalue(struct symbol *sym, const char *def) +{ +	enum symbol_type type = sym_get_type(sym); +	tristate val; + +	if (!sym_has_value(sym)) +		printf("(NEW) "); + +	line[0] = '\n'; +	line[1] = 0; + +	if (!sym_is_changable(sym)) { +		printf("%s\n", def); +		line[0] = '\n'; +		line[1] = 0; +		return; +	} + +	switch (input_mode) { +	case ask_new: +	case ask_silent: +		if (sym_has_value(sym)) { +			printf("%s\n", def); +			return; +		} +		check_stdin(); +	case ask_all: +		fflush(stdout); +		fgets(line, 128, stdin); +		return; +	case set_default: +		printf("%s\n", def); +		return; +	default: +		break; +	} + +	switch (type) { +	case S_INT: +	case S_HEX: +	case S_STRING: +		printf("%s\n", def); +		return; +	default: +		; +	} +	switch (input_mode) { +	case set_yes: +		if (sym_tristate_within_range(sym, yes)) { +			line[0] = 'y'; +			line[1] = '\n'; +			line[2] = 0; +			break; +		} +	case set_mod: +		if (type == S_TRISTATE) { +			if (sym_tristate_within_range(sym, mod)) { +				line[0] = 'm'; +				line[1] = '\n'; +				line[2] = 0; +				break; +			} +		} else { +			if (sym_tristate_within_range(sym, yes)) { +				line[0] = 'y'; +				line[1] = '\n'; +				line[2] = 0; +				break; +			} +		} +	case set_no: +		if (sym_tristate_within_range(sym, no)) { +			line[0] = 'n'; +			line[1] = '\n'; +			line[2] = 0; +			break; +		} +	case set_random: +		do { +			val = (tristate)(random() % 3); +		} while (!sym_tristate_within_range(sym, val)); +		switch (val) { +		case no: line[0] = 'n'; break; +		case mod: line[0] = 'm'; break; +		case yes: line[0] = 'y'; break; +		} +		line[1] = '\n'; +		line[2] = 0; +		break; +	default: +		break; +	} +	printf("%s", line); +} + +int conf_string(struct menu *menu) +{ +	struct symbol *sym = menu->sym; +	const char *def, *help; + +	while (1) { +		printf("%*s%s ", indent - 1, "", menu->prompt->text); +		printf("(%s) ", sym->name); +		def = sym_get_string_value(sym); +		if (sym_get_string_value(sym)) +			printf("[%s] ", def); +		conf_askvalue(sym, def); +		switch (line[0]) { +		case '\n': +			break; +		case '?': +			/* print help */ +			if (line[1] == '\n') { +				help = nohelp_text; +				if (menu->sym->help) +					help = menu->sym->help; +				printf("\n%s\n", menu->sym->help); +				def = NULL; +				break; +			} +		default: +			line[strlen(line)-1] = 0; +			def = line; +		} +		if (def && sym_set_string_value(sym, def)) +			return 0; +	} +} + +static int conf_sym(struct menu *menu) +{ +	struct symbol *sym = menu->sym; +	int type; +	tristate oldval, newval; +	const char *help; + +	while (1) { +		printf("%*s%s ", indent - 1, "", menu->prompt->text); +		if (sym->name) +			printf("(%s) ", sym->name); +		type = sym_get_type(sym); +		putchar('['); +		oldval = sym_get_tristate_value(sym); +		switch (oldval) { +		case no: +			putchar('N'); +			break; +		case mod: +			putchar('M'); +			break; +		case yes: +			putchar('Y'); +			break; +		} +		if (oldval != no && sym_tristate_within_range(sym, no)) +			printf("/n"); +		if (oldval != mod && sym_tristate_within_range(sym, mod)) +			printf("/m"); +		if (oldval != yes && sym_tristate_within_range(sym, yes)) +			printf("/y"); +		if (sym->help) +			printf("/?"); +		printf("] "); +		conf_askvalue(sym, sym_get_string_value(sym)); +		strip(line); + +		switch (line[0]) { +		case 'n': +		case 'N': +			newval = no; +			if (!line[1] || !strcmp(&line[1], "o")) +				break; +			continue; +		case 'm': +		case 'M': +			newval = mod; +			if (!line[1]) +				break; +			continue; +		case 'y': +		case 'Y': +			newval = yes; +			if (!line[1] || !strcmp(&line[1], "es")) +				break; +			continue; +		case 0: +			newval = oldval; +			break; +		case '?': +			goto help; +		default: +			continue; +		} +		if (sym_set_tristate_value(sym, newval)) +			return 0; +help: +		help = nohelp_text; +		if (sym->help) +			help = sym->help; +		printf("\n%s\n", help); +	} +} + +static int conf_choice(struct menu *menu) +{ +	struct symbol *sym, *def_sym; +	struct menu *child; +	int type; +	bool is_new; + +	sym = menu->sym; +	type = sym_get_type(sym); +	is_new = !sym_has_value(sym); +	if (sym_is_changable(sym)) { +		conf_sym(menu); +		sym_calc_value(sym); +		switch (sym_get_tristate_value(sym)) { +		case no: +			return 1; +		case mod: +			return 0; +		case yes: +			break; +		} +	} else { +		switch (sym_get_tristate_value(sym)) { +		case no: +			return 1; +		case mod: +			printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); +			return 0; +		case yes: +			break; +		} +	} + +	while (1) { +		int cnt, def; + +		printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); +		def_sym = sym_get_choice_value(sym); +		cnt = def = 0; +		line[0] = '0'; +		line[1] = 0; +		for (child = menu->list; child; child = child->next) { +			if (!menu_is_visible(child)) +				continue; +			if (!child->sym) { +				printf("%*c %s\n", indent, '*', menu_get_prompt(child)); +				continue; +			} +			cnt++; +			if (child->sym == def_sym) { +				def = cnt; +				printf("%*c", indent, '>'); +			} else +				printf("%*c", indent, ' '); +			printf(" %d. %s", cnt, menu_get_prompt(child)); +			if (child->sym->name) +				printf(" (%s)", child->sym->name); +			if (!sym_has_value(child->sym)) +				printf(" (NEW)"); +			printf("\n"); +		} +		printf("%*schoice", indent - 1, ""); +		if (cnt == 1) { +			printf("[1]: 1\n"); +			goto conf_childs; +		} +		printf("[1-%d", cnt); +		if (sym->help) +			printf("?"); +		printf("]: "); +		switch (input_mode) { +		case ask_new: +		case ask_silent: +			if (!is_new) { +				cnt = def; +				printf("%d\n", cnt); +				break; +			} +			check_stdin(); +		case ask_all: +			fflush(stdout); +			fgets(line, 128, stdin); +			strip(line); +			if (line[0] == '?') { +				printf("\n%s\n", menu->sym->help ? +					menu->sym->help : nohelp_text); +				continue; +			} +			if (!line[0]) +				cnt = def; +			else if (isdigit(line[0])) +				cnt = atoi(line); +			else +				continue; +			break; +		case set_random: +			def = (random() % cnt) + 1; +		case set_default: +		case set_yes: +		case set_mod: +		case set_no: +			cnt = def; +			printf("%d\n", cnt); +			break; +		} + +	conf_childs: +		for (child = menu->list; child; child = child->next) { +			if (!child->sym || !menu_is_visible(child)) +				continue; +			if (!--cnt) +				break; +		} +		if (!child) +			continue; +		if (line[strlen(line) - 1] == '?') { +			printf("\n%s\n", child->sym->help ? +				child->sym->help : nohelp_text); +			continue; +		} +		sym_set_choice_value(sym, child->sym); +		if (child->list) { +			indent += 2; +			conf(child->list); +			indent -= 2; +		} +		return 1; +	} +} + +static void conf(struct menu *menu) +{ +	struct symbol *sym; +	struct property *prop; +	struct menu *child; + +	if (!menu_is_visible(menu)) +		return; + +	sym = menu->sym; +	prop = menu->prompt; +	if (prop) { +		const char *prompt; + +		switch (prop->type) { +		case P_MENU: +			if (input_mode == ask_silent && rootEntry != menu) { +				check_conf(menu); +				return; +			} +		case P_COMMENT: +			prompt = menu_get_prompt(menu); +			if (prompt) +				printf("%*c\n%*c %s\n%*c\n", +					indent, '*', +					indent, '*', prompt, +					indent, '*'); +		default: +			; +		} +	} + +	if (!sym) +		goto conf_childs; + +	if (sym_is_choice(sym)) { +		conf_choice(menu); +		if (sym->curr.tri != mod) +			return; +		goto conf_childs; +	} + +	switch (sym->type) { +	case S_INT: +	case S_HEX: +	case S_STRING: +		conf_string(menu); +		break; +	default: +		conf_sym(menu); +		break; +	} + +conf_childs: +	if (sym) +		indent += 2; +	for (child = menu->list; child; child = child->next) +		conf(child); +	if (sym) +		indent -= 2; +} + +static void check_conf(struct menu *menu) +{ +	struct symbol *sym; +	struct menu *child; + +	if (!menu_is_visible(menu)) +		return; + +	sym = menu->sym; +	if (sym) { +		if (sym_is_changable(sym) && !sym_has_value(sym)) { +			if (!conf_cnt++) +				printf("*\n* Restart config...\n*\n"); +			rootEntry = menu_get_parent_menu(menu); +			conf(rootEntry); +		} +		if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod) +			return; +	} + +	for (child = menu->list; child; child = child->next) +		check_conf(child); +} + +int main(int ac, char **av) +{ +	int i = 1; +	const char *name; +	struct stat tmpstat; + +	if (ac > i && av[i][0] == '-') { +		switch (av[i++][1]) { +		case 'o': +			input_mode = ask_new; +			break; +		case 's': +			input_mode = ask_silent; +			valid_stdin = isatty(0) && isatty(1) && isatty(2); +			break; +		case 'd': +			input_mode = set_default; +			break; +		case 'D': +			input_mode = set_default; +			defconfig_file = av[i++]; +			if (!defconfig_file) { +				printf("%s: No default config file specified\n", +					av[0]); +				exit(1); +			} +			break; +		case 'n': +			input_mode = set_no; +			break; +		case 'm': +			input_mode = set_mod; +			break; +		case 'y': +			input_mode = set_yes; +			break; +		case 'r': +			input_mode = set_random; +			srandom(time(NULL)); +			break; +		case 'h': +		case '?': +			printf("%s [-o|-s] config\n", av[0]); +			exit(0); +		} +	} +  	name = av[i]; +	if (!name) { +		printf("%s: Kconfig file missing\n", av[0]); +	} +	conf_parse(name); +	//zconfdump(stdout); +	switch (input_mode) { +	case set_default: +		if (!defconfig_file) +			defconfig_file = conf_get_default_confname(); +		if (conf_read(defconfig_file)) { +			printf("***\n" +				"*** Can't find default configuration \"%s\"!\n" +				"***\n", defconfig_file); +			exit(1); +		} +		break; +	case ask_silent: +		if (stat(".config", &tmpstat)) { +			printf("***\n" +				"*** You have not yet configured your kernel!\n" +				"***\n" +				"*** Please run some configurator (e.g. \"make oldconfig\" or\n" +				"*** \"make menuconfig\" or \"make xconfig\").\n" +				"***\n"); +			exit(1); +		} +	case ask_all: +	case ask_new: +		conf_read(NULL); +		break; +	default: +		break; +	} + +	if (input_mode != ask_silent) { +		rootEntry = &rootmenu; +		conf(&rootmenu); +		if (input_mode == ask_all) { +			input_mode = ask_silent; +			valid_stdin = 1; +		} +	} +	do { +		conf_cnt = 0; +		check_conf(&rootmenu); +	} while (conf_cnt); +	if (conf_write(NULL)) { +		fprintf(stderr, "\n*** Error during writing of the kernel configuration.\n\n"); +		return 1; +	} +	return 0; +} diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c new file mode 100644 index 000000000000..1e82ae390a69 --- /dev/null +++ b/scripts/kconfig/confdata.c @@ -0,0 +1,460 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <sys/stat.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#define LKC_DIRECT_LINK +#include "lkc.h" + +const char conf_def_filename[] = ".config"; + +const char conf_defname[] = "arch/$ARCH/defconfig"; + +const char *conf_confnames[] = { +	".config", +	"/lib/modules/$UNAME_RELEASE/.config", +	"/etc/kernel-config", +	"/boot/config-$UNAME_RELEASE", +	conf_defname, +	NULL, +}; + +static char *conf_expand_value(const signed char *in) +{ +	struct symbol *sym; +	const signed char *src; +	static char res_value[SYMBOL_MAXLENGTH]; +	char *dst, name[SYMBOL_MAXLENGTH]; + +	res_value[0] = 0; +	dst = name; +	while ((src = strchr(in, '$'))) { +		strncat(res_value, in, src - in); +		src++; +		dst = name; +		while (isalnum(*src) || *src == '_') +			*dst++ = *src++; +		*dst = 0; +		sym = sym_lookup(name, 0); +		sym_calc_value(sym); +		strcat(res_value, sym_get_string_value(sym)); +		in = src; +	} +	strcat(res_value, in); + +	return res_value; +} + +char *conf_get_default_confname(void) +{ +	struct stat buf; +	static char fullname[PATH_MAX+1]; +	char *env, *name; + +	name = conf_expand_value(conf_defname); +	env = getenv(SRCTREE); +	if (env) { +		sprintf(fullname, "%s/%s", env, name); +		if (!stat(fullname, &buf)) +			return fullname; +	} +	return name; +} + +int conf_read(const char *name) +{ +	FILE *in = NULL; +	char line[1024]; +	char *p, *p2; +	int lineno = 0; +	struct symbol *sym; +	struct property *prop; +	struct expr *e; +	int i; + +	if (name) { +		in = zconf_fopen(name); +	} else { +		const char **names = conf_confnames; +		while ((name = *names++)) { +			name = conf_expand_value(name); +			in = zconf_fopen(name); +			if (in) { +				printf("#\n" +				       "# using defaults found in %s\n" +				       "#\n", name); +				break; +			} +		} +	} + +	if (!in) +		return 1; + +	for_all_symbols(i, sym) { +		sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; +		sym->flags &= ~SYMBOL_VALID; +		switch (sym->type) { +		case S_INT: +		case S_HEX: +		case S_STRING: +			if (sym->user.val) +				free(sym->user.val); +		default: +			sym->user.val = NULL; +			sym->user.tri = no; +		} +	} + +	while (fgets(line, sizeof(line), in)) { +		lineno++; +		sym = NULL; +		switch (line[0]) { +		case '#': +			if (memcmp(line + 2, "CONFIG_", 7)) +				continue; +			p = strchr(line + 9, ' '); +			if (!p) +				continue; +			*p++ = 0; +			if (strncmp(p, "is not set", 10)) +				continue; +			sym = sym_find(line + 9); +			if (!sym) { +				fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 9); +				break; +			} +			switch (sym->type) { +			case S_BOOLEAN: +			case S_TRISTATE: +				sym->user.tri = no; +				sym->flags &= ~SYMBOL_NEW; +				break; +			default: +				; +			} +			break; +		case 'C': +			if (memcmp(line, "CONFIG_", 7)) +				continue; +			p = strchr(line + 7, '='); +			if (!p) +				continue; +			*p++ = 0; +			p2 = strchr(p, '\n'); +			if (p2) +				*p2 = 0; +			sym = sym_find(line + 7); +			if (!sym) { +				fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 7); +				break; +			} +			switch (sym->type) { +			case S_TRISTATE: +				if (p[0] == 'm') { +					sym->user.tri = mod; +					sym->flags &= ~SYMBOL_NEW; +					break; +				} +			case S_BOOLEAN: +				if (p[0] == 'y') { +					sym->user.tri = yes; +					sym->flags &= ~SYMBOL_NEW; +					break; +				} +				if (p[0] == 'n') { +					sym->user.tri = no; +					sym->flags &= ~SYMBOL_NEW; +					break; +				} +				break; +			case S_STRING: +				if (*p++ != '"') +					break; +				for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { +					if (*p2 == '"') { +						*p2 = 0; +						break; +					} +					memmove(p2, p2 + 1, strlen(p2)); +				} +				if (!p2) { +					fprintf(stderr, "%s:%d: invalid string found\n", name, lineno); +					exit(1); +				} +			case S_INT: +			case S_HEX: +				if (sym_string_valid(sym, p)) { +					sym->user.val = strdup(p); +					sym->flags &= ~SYMBOL_NEW; +				} else { +					fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name); +					exit(1); +				} +				break; +			default: +				; +			} +			break; +		case '\n': +			break; +		default: +			continue; +		} +		if (sym && sym_is_choice_value(sym)) { +			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); +			switch (sym->user.tri) { +			case no: +				break; +			case mod: +				if (cs->user.tri == yes) +					/* warn? */; +				break; +			case yes: +				if (cs->user.tri != no) +					/* warn? */; +				cs->user.val = sym; +				break; +			} +			cs->user.tri = E_OR(cs->user.tri, sym->user.tri); +			cs->flags &= ~SYMBOL_NEW; +		} +	} +	fclose(in); + +	if (modules_sym) +		sym_calc_value(modules_sym); +	for_all_symbols(i, sym) { +		sym_calc_value(sym); +		if (sym_has_value(sym) && !sym_is_choice_value(sym)) { +			if (sym->visible == no) +				sym->flags |= SYMBOL_NEW; +			switch (sym->type) { +			case S_STRING: +			case S_INT: +			case S_HEX: +				if (!sym_string_within_range(sym, sym->user.val)) +					sym->flags |= SYMBOL_NEW; +			default: +				break; +			} +		} +		if (!sym_is_choice(sym)) +			continue; +		prop = sym_get_choice_prop(sym); +		for (e = prop->expr; e; e = e->left.expr) +			if (e->right.sym->visible != no) +				sym->flags |= e->right.sym->flags & SYMBOL_NEW; +	} + +	sym_change_count = 1; + +	return 0; +} + +int conf_write(const char *name) +{ +	FILE *out, *out_h; +	struct symbol *sym; +	struct menu *menu; +	const char *basename; +	char dirname[128], tmpname[128], newname[128]; +	int type, l; +	const char *str; +	time_t now; +	int use_timestamp = 1; +	char *env; + +	dirname[0] = 0; +	if (name && name[0]) { +		struct stat st; +		char *slash; + +		if (!stat(name, &st) && S_ISDIR(st.st_mode)) { +			strcpy(dirname, name); +			strcat(dirname, "/"); +			basename = conf_def_filename; +		} else if ((slash = strrchr(name, '/'))) { +			int size = slash - name + 1; +			memcpy(dirname, name, size); +			dirname[size] = 0; +			if (slash[1]) +				basename = slash + 1; +			else +				basename = conf_def_filename; +		} else +			basename = name; +	} else +		basename = conf_def_filename; + +	sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid()); +	out = fopen(newname, "w"); +	if (!out) +		return 1; +	out_h = NULL; +	if (!name) { +		out_h = fopen(".tmpconfig.h", "w"); +		if (!out_h) +			return 1; +	} +	sym = sym_lookup("KERNELRELEASE", 0); +	sym_calc_value(sym); +	time(&now); +	env = getenv("KCONFIG_NOTIMESTAMP"); +	if (env && *env) +		use_timestamp = 0; + +	fprintf(out, "#\n" +		     "# Automatically generated make config: don't edit\n" +		     "# Linux kernel version: %s\n" +		     "%s%s" +		     "#\n", +		     sym_get_string_value(sym), +		     use_timestamp ? "# " : "", +		     use_timestamp ? ctime(&now) : ""); +	if (out_h) +		fprintf(out_h, "/*\n" +			       " * Automatically generated C config: don't edit\n" +			       " * Linux kernel version: %s\n" +			       "%s%s" +			       " */\n" +			       "#define AUTOCONF_INCLUDED\n", +			       sym_get_string_value(sym), +			       use_timestamp ? " * " : "", +			       use_timestamp ? ctime(&now) : ""); + +	if (!sym_change_count) +		sym_clear_all_valid(); + +	menu = rootmenu.list; +	while (menu) { +		sym = menu->sym; +		if (!sym) { +			if (!menu_is_visible(menu)) +				goto next; +			str = menu_get_prompt(menu); +			fprintf(out, "\n" +				     "#\n" +				     "# %s\n" +				     "#\n", str); +			if (out_h) +				fprintf(out_h, "\n" +					       "/*\n" +					       " * %s\n" +					       " */\n", str); +		} else if (!(sym->flags & SYMBOL_CHOICE)) { +			sym_calc_value(sym); +			if (!(sym->flags & SYMBOL_WRITE)) +				goto next; +			sym->flags &= ~SYMBOL_WRITE; +			type = sym->type; +			if (type == S_TRISTATE) { +				sym_calc_value(modules_sym); +				if (modules_sym->curr.tri == no) +					type = S_BOOLEAN; +			} +			switch (type) { +			case S_BOOLEAN: +			case S_TRISTATE: +				switch (sym_get_tristate_value(sym)) { +				case no: +					fprintf(out, "# CONFIG_%s is not set\n", sym->name); +					if (out_h) +						fprintf(out_h, "#undef CONFIG_%s\n", sym->name); +					break; +				case mod: +					fprintf(out, "CONFIG_%s=m\n", sym->name); +					if (out_h) +						fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); +					break; +				case yes: +					fprintf(out, "CONFIG_%s=y\n", sym->name); +					if (out_h) +						fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); +					break; +				} +				break; +			case S_STRING: +				// fix me +				str = sym_get_string_value(sym); +				fprintf(out, "CONFIG_%s=\"", sym->name); +				if (out_h) +					fprintf(out_h, "#define CONFIG_%s \"", sym->name); +				do { +					l = strcspn(str, "\"\\"); +					if (l) { +						fwrite(str, l, 1, out); +						if (out_h) +							fwrite(str, l, 1, out_h); +					} +					str += l; +					while (*str == '\\' || *str == '"') { +						fprintf(out, "\\%c", *str); +						if (out_h) +							fprintf(out_h, "\\%c", *str); +						str++; +					} +				} while (*str); +				fputs("\"\n", out); +				if (out_h) +					fputs("\"\n", out_h); +				break; +			case S_HEX: +				str = sym_get_string_value(sym); +				if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { +					fprintf(out, "CONFIG_%s=%s\n", sym->name, str); +					if (out_h) +						fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); +					break; +				} +			case S_INT: +				str = sym_get_string_value(sym); +				fprintf(out, "CONFIG_%s=%s\n", sym->name, str); +				if (out_h) +					fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); +				break; +			} +		} + +	next: +		if (menu->list) { +			menu = menu->list; +			continue; +		} +		if (menu->next) +			menu = menu->next; +		else while ((menu = menu->parent)) { +			if (menu->next) { +				menu = menu->next; +				break; +			} +		} +	} +	fclose(out); +	if (out_h) { +		fclose(out_h); +		rename(".tmpconfig.h", "include/linux/autoconf.h"); +		file_write_dep(NULL); +	} +	if (!name || basename != conf_def_filename) { +		if (!name) +			name = conf_def_filename; +		sprintf(tmpname, "%s.old", name); +		rename(name, tmpname); +	} +	sprintf(tmpname, "%s%s", dirname, basename); +	if (rename(newname, tmpname)) +		return 1; + +	sym_change_count = 0; + +	return 0; +} diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c new file mode 100644 index 000000000000..30e4f9d69c2f --- /dev/null +++ b/scripts/kconfig/expr.c @@ -0,0 +1,1099 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define DEBUG_EXPR	0 + +struct expr *expr_alloc_symbol(struct symbol *sym) +{ +	struct expr *e = malloc(sizeof(*e)); +	memset(e, 0, sizeof(*e)); +	e->type = E_SYMBOL; +	e->left.sym = sym; +	return e; +} + +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) +{ +	struct expr *e = malloc(sizeof(*e)); +	memset(e, 0, sizeof(*e)); +	e->type = type; +	e->left.expr = ce; +	return e; +} + +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) +{ +	struct expr *e = malloc(sizeof(*e)); +	memset(e, 0, sizeof(*e)); +	e->type = type; +	e->left.expr = e1; +	e->right.expr = e2; +	return e; +} + +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) +{ +	struct expr *e = malloc(sizeof(*e)); +	memset(e, 0, sizeof(*e)); +	e->type = type; +	e->left.sym = s1; +	e->right.sym = s2; +	return e; +} + +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) +{ +	if (!e1) +		return e2; +	return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; +} + +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) +{ +	if (!e1) +		return e2; +	return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; +} + +struct expr *expr_copy(struct expr *org) +{ +	struct expr *e; + +	if (!org) +		return NULL; + +	e = malloc(sizeof(*org)); +	memcpy(e, org, sizeof(*org)); +	switch (org->type) { +	case E_SYMBOL: +		e->left = org->left; +		break; +	case E_NOT: +		e->left.expr = expr_copy(org->left.expr); +		break; +	case E_EQUAL: +	case E_UNEQUAL: +		e->left.sym = org->left.sym; +		e->right.sym = org->right.sym; +		break; +	case E_AND: +	case E_OR: +	case E_CHOICE: +		e->left.expr = expr_copy(org->left.expr); +		e->right.expr = expr_copy(org->right.expr); +		break; +	default: +		printf("can't copy type %d\n", e->type); +		free(e); +		e = NULL; +		break; +	} + +	return e; +} + +void expr_free(struct expr *e) +{ +	if (!e) +		return; + +	switch (e->type) { +	case E_SYMBOL: +		break; +	case E_NOT: +		expr_free(e->left.expr); +		return; +	case E_EQUAL: +	case E_UNEQUAL: +		break; +	case E_OR: +	case E_AND: +		expr_free(e->left.expr); +		expr_free(e->right.expr); +		break; +	default: +		printf("how to free type %d?\n", e->type); +		break; +	} +	free(e); +} + +static int trans_count; + +#define e1 (*ep1) +#define e2 (*ep2) + +static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +	if (e1->type == type) { +		__expr_eliminate_eq(type, &e1->left.expr, &e2); +		__expr_eliminate_eq(type, &e1->right.expr, &e2); +		return; +	} +	if (e2->type == type) { +		__expr_eliminate_eq(type, &e1, &e2->left.expr); +		__expr_eliminate_eq(type, &e1, &e2->right.expr); +		return; +	} +	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && +	    e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO))) +		return; +	if (!expr_eq(e1, e2)) +		return; +	trans_count++; +	expr_free(e1); expr_free(e2); +	switch (type) { +	case E_OR: +		e1 = expr_alloc_symbol(&symbol_no); +		e2 = expr_alloc_symbol(&symbol_no); +		break; +	case E_AND: +		e1 = expr_alloc_symbol(&symbol_yes); +		e2 = expr_alloc_symbol(&symbol_yes); +		break; +	default: +		; +	} +} + +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) +{ +	if (!e1 || !e2) +		return; +	switch (e1->type) { +	case E_OR: +	case E_AND: +		__expr_eliminate_eq(e1->type, ep1, ep2); +	default: +		; +	} +	if (e1->type != e2->type) switch (e2->type) { +	case E_OR: +	case E_AND: +		__expr_eliminate_eq(e2->type, ep1, ep2); +	default: +		; +	} +	e1 = expr_eliminate_yn(e1); +	e2 = expr_eliminate_yn(e2); +} + +#undef e1 +#undef e2 + +int expr_eq(struct expr *e1, struct expr *e2) +{ +	int res, old_count; + +	if (e1->type != e2->type) +		return 0; +	switch (e1->type) { +	case E_EQUAL: +	case E_UNEQUAL: +		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; +	case E_SYMBOL: +		return e1->left.sym == e2->left.sym; +	case E_NOT: +		return expr_eq(e1->left.expr, e2->left.expr); +	case E_AND: +	case E_OR: +		e1 = expr_copy(e1); +		e2 = expr_copy(e2); +		old_count = trans_count; +		expr_eliminate_eq(&e1, &e2); +		res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && +		       e1->left.sym == e2->left.sym); +		expr_free(e1); +		expr_free(e2); +		trans_count = old_count; +		return res; +	case E_CHOICE: +	case E_RANGE: +	case E_NONE: +		/* panic */; +	} + +	if (DEBUG_EXPR) { +		expr_fprint(e1, stdout); +		printf(" = "); +		expr_fprint(e2, stdout); +		printf(" ?\n"); +	} + +	return 0; +} + +struct expr *expr_eliminate_yn(struct expr *e) +{ +	struct expr *tmp; + +	if (e) switch (e->type) { +	case E_AND: +		e->left.expr = expr_eliminate_yn(e->left.expr); +		e->right.expr = expr_eliminate_yn(e->right.expr); +		if (e->left.expr->type == E_SYMBOL) { +			if (e->left.expr->left.sym == &symbol_no) { +				expr_free(e->left.expr); +				expr_free(e->right.expr); +				e->type = E_SYMBOL; +				e->left.sym = &symbol_no; +				e->right.expr = NULL; +				return e; +			} else if (e->left.expr->left.sym == &symbol_yes) { +				free(e->left.expr); +				tmp = e->right.expr; +				*e = *(e->right.expr); +				free(tmp); +				return e; +			} +		} +		if (e->right.expr->type == E_SYMBOL) { +			if (e->right.expr->left.sym == &symbol_no) { +				expr_free(e->left.expr); +				expr_free(e->right.expr); +				e->type = E_SYMBOL; +				e->left.sym = &symbol_no; +				e->right.expr = NULL; +				return e; +			} else if (e->right.expr->left.sym == &symbol_yes) { +				free(e->right.expr); +				tmp = e->left.expr; +				*e = *(e->left.expr); +				free(tmp); +				return e; +			} +		} +		break; +	case E_OR: +		e->left.expr = expr_eliminate_yn(e->left.expr); +		e->right.expr = expr_eliminate_yn(e->right.expr); +		if (e->left.expr->type == E_SYMBOL) { +			if (e->left.expr->left.sym == &symbol_no) { +				free(e->left.expr); +				tmp = e->right.expr; +				*e = *(e->right.expr); +				free(tmp); +				return e; +			} else if (e->left.expr->left.sym == &symbol_yes) { +				expr_free(e->left.expr); +				expr_free(e->right.expr); +				e->type = E_SYMBOL; +				e->left.sym = &symbol_yes; +				e->right.expr = NULL; +				return e; +			} +		} +		if (e->right.expr->type == E_SYMBOL) { +			if (e->right.expr->left.sym == &symbol_no) { +				free(e->right.expr); +				tmp = e->left.expr; +				*e = *(e->left.expr); +				free(tmp); +				return e; +			} else if (e->right.expr->left.sym == &symbol_yes) { +				expr_free(e->left.expr); +				expr_free(e->right.expr); +				e->type = E_SYMBOL; +				e->left.sym = &symbol_yes; +				e->right.expr = NULL; +				return e; +			} +		} +		break; +	default: +		; +	} +	return e; +} + +/* + * bool FOO!=n => FOO + */ +struct expr *expr_trans_bool(struct expr *e) +{ +	if (!e) +		return NULL; +	switch (e->type) { +	case E_AND: +	case E_OR: +	case E_NOT: +		e->left.expr = expr_trans_bool(e->left.expr); +		e->right.expr = expr_trans_bool(e->right.expr); +		break; +	case E_UNEQUAL: +		// FOO!=n -> FOO +		if (e->left.sym->type == S_TRISTATE) { +			if (e->right.sym == &symbol_no) { +				e->type = E_SYMBOL; +				e->right.sym = NULL; +			} +		} +		break; +	default: +		; +	} +	return e; +} + +/* + * e1 || e2 -> ? + */ +struct expr *expr_join_or(struct expr *e1, struct expr *e2) +{ +	struct expr *tmp; +	struct symbol *sym1, *sym2; + +	if (expr_eq(e1, e2)) +		return expr_copy(e1); +	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) +		return NULL; +	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) +		return NULL; +	if (e1->type == E_NOT) { +		tmp = e1->left.expr; +		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) +			return NULL; +		sym1 = tmp->left.sym; +	} else +		sym1 = e1->left.sym; +	if (e2->type == E_NOT) { +		if (e2->left.expr->type != E_SYMBOL) +			return NULL; +		sym2 = e2->left.expr->left.sym; +	} else +		sym2 = e2->left.sym; +	if (sym1 != sym2) +		return NULL; +	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) +		return NULL; +	if (sym1->type == S_TRISTATE) { +		if (e1->type == E_EQUAL && e2->type == E_EQUAL && +		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || +		     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { +			// (a='y') || (a='m') -> (a!='n') +			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); +		} +		if (e1->type == E_EQUAL && e2->type == E_EQUAL && +		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || +		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { +			// (a='y') || (a='n') -> (a!='m') +			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); +		} +		if (e1->type == E_EQUAL && e2->type == E_EQUAL && +		    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || +		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { +			// (a='m') || (a='n') -> (a!='y') +			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); +		} +	} +	if (sym1->type == S_BOOLEAN && sym1 == sym2) { +		if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || +		    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) +			return expr_alloc_symbol(&symbol_yes); +	} + +	if (DEBUG_EXPR) { +		printf("optimize ("); +		expr_fprint(e1, stdout); +		printf(") || ("); +		expr_fprint(e2, stdout); +		printf(")?\n"); +	} +	return NULL; +} + +struct expr *expr_join_and(struct expr *e1, struct expr *e2) +{ +	struct expr *tmp; +	struct symbol *sym1, *sym2; + +	if (expr_eq(e1, e2)) +		return expr_copy(e1); +	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) +		return NULL; +	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) +		return NULL; +	if (e1->type == E_NOT) { +		tmp = e1->left.expr; +		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) +			return NULL; +		sym1 = tmp->left.sym; +	} else +		sym1 = e1->left.sym; +	if (e2->type == E_NOT) { +		if (e2->left.expr->type != E_SYMBOL) +			return NULL; +		sym2 = e2->left.expr->left.sym; +	} else +		sym2 = e2->left.sym; +	if (sym1 != sym2) +		return NULL; +	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) +		return NULL; + +	if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || +	    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) +		// (a) && (a='y') -> (a='y') +		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + +	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || +	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) +		// (a) && (a!='n') -> (a) +		return expr_alloc_symbol(sym1); + +	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || +	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) +		// (a) && (a!='m') -> (a='y') +		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + +	if (sym1->type == S_TRISTATE) { +		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { +			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' +			sym2 = e1->right.sym; +			if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) +				return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) +							     : expr_alloc_symbol(&symbol_no); +		} +		if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { +			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' +			sym2 = e2->right.sym; +			if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) +				return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) +							     : expr_alloc_symbol(&symbol_no); +		} +		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && +			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || +			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) +			// (a!='y') && (a!='n') -> (a='m') +			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); + +		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && +			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || +			    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) +			// (a!='y') && (a!='m') -> (a='n') +			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); + +		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && +			   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || +			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) +			// (a!='m') && (a!='n') -> (a='m') +			return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + +		if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || +		    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || +		    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || +		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) +			return NULL; +	} + +	if (DEBUG_EXPR) { +		printf("optimize ("); +		expr_fprint(e1, stdout); +		printf(") && ("); +		expr_fprint(e2, stdout); +		printf(")?\n"); +	} +	return NULL; +} + +static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) +	struct expr *tmp; + +	if (e1->type == type) { +		expr_eliminate_dups1(type, &e1->left.expr, &e2); +		expr_eliminate_dups1(type, &e1->right.expr, &e2); +		return; +	} +	if (e2->type == type) { +		expr_eliminate_dups1(type, &e1, &e2->left.expr); +		expr_eliminate_dups1(type, &e1, &e2->right.expr); +		return; +	} +	if (e1 == e2) +		return; + +	switch (e1->type) { +	case E_OR: case E_AND: +		expr_eliminate_dups1(e1->type, &e1, &e1); +	default: +		; +	} + +	switch (type) { +	case E_OR: +		tmp = expr_join_or(e1, e2); +		if (tmp) { +			expr_free(e1); expr_free(e2); +			e1 = expr_alloc_symbol(&symbol_no); +			e2 = tmp; +			trans_count++; +		} +		break; +	case E_AND: +		tmp = expr_join_and(e1, e2); +		if (tmp) { +			expr_free(e1); expr_free(e2); +			e1 = expr_alloc_symbol(&symbol_yes); +			e2 = tmp; +			trans_count++; +		} +		break; +	default: +		; +	} +#undef e1 +#undef e2 +} + +static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) +	struct expr *tmp, *tmp1, *tmp2; + +	if (e1->type == type) { +		expr_eliminate_dups2(type, &e1->left.expr, &e2); +		expr_eliminate_dups2(type, &e1->right.expr, &e2); +		return; +	} +	if (e2->type == type) { +		expr_eliminate_dups2(type, &e1, &e2->left.expr); +		expr_eliminate_dups2(type, &e1, &e2->right.expr); +	} +	if (e1 == e2) +		return; + +	switch (e1->type) { +	case E_OR: +		expr_eliminate_dups2(e1->type, &e1, &e1); +		// (FOO || BAR) && (!FOO && !BAR) -> n +		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); +		tmp2 = expr_copy(e2); +		tmp = expr_extract_eq_and(&tmp1, &tmp2); +		if (expr_is_yes(tmp1)) { +			expr_free(e1); +			e1 = expr_alloc_symbol(&symbol_no); +			trans_count++; +		} +		expr_free(tmp2); +		expr_free(tmp1); +		expr_free(tmp); +		break; +	case E_AND: +		expr_eliminate_dups2(e1->type, &e1, &e1); +		// (FOO && BAR) || (!FOO || !BAR) -> y +		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); +		tmp2 = expr_copy(e2); +		tmp = expr_extract_eq_or(&tmp1, &tmp2); +		if (expr_is_no(tmp1)) { +			expr_free(e1); +			e1 = expr_alloc_symbol(&symbol_yes); +			trans_count++; +		} +		expr_free(tmp2); +		expr_free(tmp1); +		expr_free(tmp); +		break; +	default: +		; +	} +#undef e1 +#undef e2 +} + +struct expr *expr_eliminate_dups(struct expr *e) +{ +	int oldcount; +	if (!e) +		return e; + +	oldcount = trans_count; +	while (1) { +		trans_count = 0; +		switch (e->type) { +		case E_OR: case E_AND: +			expr_eliminate_dups1(e->type, &e, &e); +			expr_eliminate_dups2(e->type, &e, &e); +		default: +			; +		} +		if (!trans_count) +			break; +		e = expr_eliminate_yn(e); +	} +	trans_count = oldcount; +	return e; +} + +struct expr *expr_transform(struct expr *e) +{ +	struct expr *tmp; + +	if (!e) +		return NULL; +	switch (e->type) { +	case E_EQUAL: +	case E_UNEQUAL: +	case E_SYMBOL: +	case E_CHOICE: +		break; +	default: +		e->left.expr = expr_transform(e->left.expr); +		e->right.expr = expr_transform(e->right.expr); +	} + +	switch (e->type) { +	case E_EQUAL: +		if (e->left.sym->type != S_BOOLEAN) +			break; +		if (e->right.sym == &symbol_no) { +			e->type = E_NOT; +			e->left.expr = expr_alloc_symbol(e->left.sym); +			e->right.sym = NULL; +			break; +		} +		if (e->right.sym == &symbol_mod) { +			printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); +			e->type = E_SYMBOL; +			e->left.sym = &symbol_no; +			e->right.sym = NULL; +			break; +		} +		if (e->right.sym == &symbol_yes) { +			e->type = E_SYMBOL; +			e->right.sym = NULL; +			break; +		} +		break; +	case E_UNEQUAL: +		if (e->left.sym->type != S_BOOLEAN) +			break; +		if (e->right.sym == &symbol_no) { +			e->type = E_SYMBOL; +			e->right.sym = NULL; +			break; +		} +		if (e->right.sym == &symbol_mod) { +			printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); +			e->type = E_SYMBOL; +			e->left.sym = &symbol_yes; +			e->right.sym = NULL; +			break; +		} +		if (e->right.sym == &symbol_yes) { +			e->type = E_NOT; +			e->left.expr = expr_alloc_symbol(e->left.sym); +			e->right.sym = NULL; +			break; +		} +		break; +	case E_NOT: +		switch (e->left.expr->type) { +		case E_NOT: +			// !!a -> a +			tmp = e->left.expr->left.expr; +			free(e->left.expr); +			free(e); +			e = tmp; +			e = expr_transform(e); +			break; +		case E_EQUAL: +		case E_UNEQUAL: +			// !a='x' -> a!='x' +			tmp = e->left.expr; +			free(e); +			e = tmp; +			e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; +			break; +		case E_OR: +			// !(a || b) -> !a && !b +			tmp = e->left.expr; +			e->type = E_AND; +			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); +			tmp->type = E_NOT; +			tmp->right.expr = NULL; +			e = expr_transform(e); +			break; +		case E_AND: +			// !(a && b) -> !a || !b +			tmp = e->left.expr; +			e->type = E_OR; +			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); +			tmp->type = E_NOT; +			tmp->right.expr = NULL; +			e = expr_transform(e); +			break; +		case E_SYMBOL: +			if (e->left.expr->left.sym == &symbol_yes) { +				// !'y' -> 'n' +				tmp = e->left.expr; +				free(e); +				e = tmp; +				e->type = E_SYMBOL; +				e->left.sym = &symbol_no; +				break; +			} +			if (e->left.expr->left.sym == &symbol_mod) { +				// !'m' -> 'm' +				tmp = e->left.expr; +				free(e); +				e = tmp; +				e->type = E_SYMBOL; +				e->left.sym = &symbol_mod; +				break; +			} +			if (e->left.expr->left.sym == &symbol_no) { +				// !'n' -> 'y' +				tmp = e->left.expr; +				free(e); +				e = tmp; +				e->type = E_SYMBOL; +				e->left.sym = &symbol_yes; +				break; +			} +			break; +		default: +			; +		} +		break; +	default: +		; +	} +	return e; +} + +int expr_contains_symbol(struct expr *dep, struct symbol *sym) +{ +	if (!dep) +		return 0; + +	switch (dep->type) { +	case E_AND: +	case E_OR: +		return expr_contains_symbol(dep->left.expr, sym) || +		       expr_contains_symbol(dep->right.expr, sym); +	case E_SYMBOL: +		return dep->left.sym == sym; +	case E_EQUAL: +	case E_UNEQUAL: +		return dep->left.sym == sym || +		       dep->right.sym == sym; +	case E_NOT: +		return expr_contains_symbol(dep->left.expr, sym); +	default: +		; +	} +	return 0; +} + +bool expr_depends_symbol(struct expr *dep, struct symbol *sym) +{ +	if (!dep) +		return false; + +	switch (dep->type) { +	case E_AND: +		return expr_depends_symbol(dep->left.expr, sym) || +		       expr_depends_symbol(dep->right.expr, sym); +	case E_SYMBOL: +		return dep->left.sym == sym; +	case E_EQUAL: +		if (dep->left.sym == sym) { +			if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) +				return true; +		} +		break; +	case E_UNEQUAL: +		if (dep->left.sym == sym) { +			if (dep->right.sym == &symbol_no) +				return true; +		} +		break; +	default: +		; +	} + 	return false; +} + +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) +{ +	struct expr *tmp = NULL; +	expr_extract_eq(E_AND, &tmp, ep1, ep2); +	if (tmp) { +		*ep1 = expr_eliminate_yn(*ep1); +		*ep2 = expr_eliminate_yn(*ep2); +	} +	return tmp; +} + +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) +{ +	struct expr *tmp = NULL; +	expr_extract_eq(E_OR, &tmp, ep1, ep2); +	if (tmp) { +		*ep1 = expr_eliminate_yn(*ep1); +		*ep2 = expr_eliminate_yn(*ep2); +	} +	return tmp; +} + +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) +	if (e1->type == type) { +		expr_extract_eq(type, ep, &e1->left.expr, &e2); +		expr_extract_eq(type, ep, &e1->right.expr, &e2); +		return; +	} +	if (e2->type == type) { +		expr_extract_eq(type, ep, ep1, &e2->left.expr); +		expr_extract_eq(type, ep, ep1, &e2->right.expr); +		return; +	} +	if (expr_eq(e1, e2)) { +		*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; +		expr_free(e2); +		if (type == E_AND) { +			e1 = expr_alloc_symbol(&symbol_yes); +			e2 = expr_alloc_symbol(&symbol_yes); +		} else if (type == E_OR) { +			e1 = expr_alloc_symbol(&symbol_no); +			e2 = expr_alloc_symbol(&symbol_no); +		} +	} +#undef e1 +#undef e2 +} + +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) +{ +	struct expr *e1, *e2; + +	if (!e) { +		e = expr_alloc_symbol(sym); +		if (type == E_UNEQUAL) +			e = expr_alloc_one(E_NOT, e); +		return e; +	} +	switch (e->type) { +	case E_AND: +		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); +		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); +		if (sym == &symbol_yes) +			e = expr_alloc_two(E_AND, e1, e2); +		if (sym == &symbol_no) +			e = expr_alloc_two(E_OR, e1, e2); +		if (type == E_UNEQUAL) +			e = expr_alloc_one(E_NOT, e); +		return e; +	case E_OR: +		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); +		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); +		if (sym == &symbol_yes) +			e = expr_alloc_two(E_OR, e1, e2); +		if (sym == &symbol_no) +			e = expr_alloc_two(E_AND, e1, e2); +		if (type == E_UNEQUAL) +			e = expr_alloc_one(E_NOT, e); +		return e; +	case E_NOT: +		return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); +	case E_UNEQUAL: +	case E_EQUAL: +		if (type == E_EQUAL) { +			if (sym == &symbol_yes) +				return expr_copy(e); +			if (sym == &symbol_mod) +				return expr_alloc_symbol(&symbol_no); +			if (sym == &symbol_no) +				return expr_alloc_one(E_NOT, expr_copy(e)); +		} else { +			if (sym == &symbol_yes) +				return expr_alloc_one(E_NOT, expr_copy(e)); +			if (sym == &symbol_mod) +				return expr_alloc_symbol(&symbol_yes); +			if (sym == &symbol_no) +				return expr_copy(e); +		} +		break; +	case E_SYMBOL: +		return expr_alloc_comp(type, e->left.sym, sym); +	case E_CHOICE: +	case E_RANGE: +	case E_NONE: +		/* panic */; +	} +	return NULL; +} + +tristate expr_calc_value(struct expr *e) +{ +	tristate val1, val2; +	const char *str1, *str2; + +	if (!e) +		return yes; + +	switch (e->type) { +	case E_SYMBOL: +		sym_calc_value(e->left.sym); +		return e->left.sym->curr.tri; +	case E_AND: +		val1 = expr_calc_value(e->left.expr); +		val2 = expr_calc_value(e->right.expr); +		return E_AND(val1, val2); +	case E_OR: +		val1 = expr_calc_value(e->left.expr); +		val2 = expr_calc_value(e->right.expr); +		return E_OR(val1, val2); +	case E_NOT: +		val1 = expr_calc_value(e->left.expr); +		return E_NOT(val1); +	case E_EQUAL: +		sym_calc_value(e->left.sym); +		sym_calc_value(e->right.sym); +		str1 = sym_get_string_value(e->left.sym); +		str2 = sym_get_string_value(e->right.sym); +		return !strcmp(str1, str2) ? yes : no; +	case E_UNEQUAL: +		sym_calc_value(e->left.sym); +		sym_calc_value(e->right.sym); +		str1 = sym_get_string_value(e->left.sym); +		str2 = sym_get_string_value(e->right.sym); +		return !strcmp(str1, str2) ? no : yes; +	default: +		printf("expr_calc_value: %d?\n", e->type); +		return no; +	} +} + +int expr_compare_type(enum expr_type t1, enum expr_type t2) +{ +#if 0 +	return 1; +#else +	if (t1 == t2) +		return 0; +	switch (t1) { +	case E_EQUAL: +	case E_UNEQUAL: +		if (t2 == E_NOT) +			return 1; +	case E_NOT: +		if (t2 == E_AND) +			return 1; +	case E_AND: +		if (t2 == E_OR) +			return 1; +	case E_OR: +		if (t2 == E_CHOICE) +			return 1; +	case E_CHOICE: +		if (t2 == 0) +			return 1; +	default: +		return -1; +	} +	printf("[%dgt%d?]", t1, t2); +	return 0; +#endif +} + +void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken) +{ +	if (!e) { +		fn(data, "y"); +		return; +	} + +	if (expr_compare_type(prevtoken, e->type) > 0) +		fn(data, "("); +	switch (e->type) { +	case E_SYMBOL: +		if (e->left.sym->name) +			fn(data, e->left.sym->name); +		else +			fn(data, "<choice>"); +		break; +	case E_NOT: +		fn(data, "!"); +		expr_print(e->left.expr, fn, data, E_NOT); +		break; +	case E_EQUAL: +		fn(data, e->left.sym->name); +		fn(data, "="); +		fn(data, e->right.sym->name); +		break; +	case E_UNEQUAL: +		fn(data, e->left.sym->name); +		fn(data, "!="); +		fn(data, e->right.sym->name); +		break; +	case E_OR: +		expr_print(e->left.expr, fn, data, E_OR); +		fn(data, " || "); +		expr_print(e->right.expr, fn, data, E_OR); +		break; +	case E_AND: +		expr_print(e->left.expr, fn, data, E_AND); +		fn(data, " && "); +		expr_print(e->right.expr, fn, data, E_AND); +		break; +	case E_CHOICE: +		fn(data, e->right.sym->name); +		if (e->left.expr) { +			fn(data, " ^ "); +			expr_print(e->left.expr, fn, data, E_CHOICE); +		} +		break; +	case E_RANGE: +		fn(data, "["); +		fn(data, e->left.sym->name); +		fn(data, " "); +		fn(data, e->right.sym->name); +		fn(data, "]"); +		break; +	default: +	  { +		char buf[32]; +		sprintf(buf, "<unknown type %d>", e->type); +		fn(data, buf); +		break; +	  } +	} +	if (expr_compare_type(prevtoken, e->type) > 0) +		fn(data, ")"); +} + +static void expr_print_file_helper(void *data, const char *str) +{ +	fwrite(str, strlen(str), 1, data); +} + +void expr_fprint(struct expr *e, FILE *out) +{ +	expr_print(e, expr_print_file_helper, out, E_NONE); +} + +static void expr_print_gstr_helper(void *data, const char *str) +{ +	str_append((struct gstr*)data, str); +} + +void expr_gstr_print(struct expr *e, struct gstr *gs) +{ +	expr_print(e, expr_print_gstr_helper, gs, E_NONE); +} diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h new file mode 100644 index 000000000000..7d39ff43e6e1 --- /dev/null +++ b/scripts/kconfig/expr.h @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef EXPR_H +#define EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#ifndef __cplusplus +#include <stdbool.h> +#endif + +struct file { +	struct file *next; +	struct file *parent; +	char *name; +	int lineno; +	int flags; +}; + +#define FILE_BUSY		0x0001 +#define FILE_SCANNED		0x0002 +#define FILE_PRINTED		0x0004 + +typedef enum tristate { +	no, mod, yes +} tristate; + +enum expr_type { +	E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE +}; + +union expr_data { +	struct expr *expr; +	struct symbol *sym; +}; + +struct expr { +	enum expr_type type; +	union expr_data left, right; +}; + +#define E_OR(dep1, dep2)	(((dep1)>(dep2))?(dep1):(dep2)) +#define E_AND(dep1, dep2)	(((dep1)<(dep2))?(dep1):(dep2)) +#define E_NOT(dep)		(2-(dep)) + +struct expr_value { +	struct expr *expr; +	tristate tri; +}; + +struct symbol_value { +	void *val; +	tristate tri; +}; + +enum symbol_type { +	S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER +}; + +struct symbol { +	struct symbol *next; +	char *name; +	char *help; +	enum symbol_type type; +	struct symbol_value curr, user; +	tristate visible; +	int flags; +	struct property *prop; +	struct expr *dep, *dep2; +	struct expr_value rev_dep; +}; + +#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) + +#define SYMBOL_YES		0x0001 +#define SYMBOL_MOD		0x0002 +#define SYMBOL_NO		0x0004 +#define SYMBOL_CONST		0x0007 +#define SYMBOL_CHECK		0x0008 +#define SYMBOL_CHOICE		0x0010 +#define SYMBOL_CHOICEVAL	0x0020 +#define SYMBOL_PRINTED		0x0040 +#define SYMBOL_VALID		0x0080 +#define SYMBOL_OPTIONAL		0x0100 +#define SYMBOL_WRITE		0x0200 +#define SYMBOL_CHANGED		0x0400 +#define SYMBOL_NEW		0x0800 +#define SYMBOL_AUTO		0x1000 +#define SYMBOL_CHECKED		0x2000 +#define SYMBOL_CHECK_DONE	0x4000 +#define SYMBOL_WARNED		0x8000 + +#define SYMBOL_MAXLENGTH	256 +#define SYMBOL_HASHSIZE		257 +#define SYMBOL_HASHMASK		0xff + +enum prop_type { +	P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT, P_RANGE +}; + +struct property { +	struct property *next; +	struct symbol *sym; +	enum prop_type type; +	const char *text; +	struct expr_value visible; +	struct expr *expr; +	struct menu *menu; +	struct file *file; +	int lineno; +}; + +#define for_all_properties(sym, st, tok) \ +	for (st = sym->prop; st; st = st->next) \ +		if (st->type == (tok)) +#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) +#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) +#define for_all_prompts(sym, st) \ +	for (st = sym->prop; st; st = st->next) \ +		if (st->text) + +struct menu { +	struct menu *next; +	struct menu *parent; +	struct menu *list; +	struct symbol *sym; +	struct property *prompt; +	struct expr *dep; +	unsigned int flags; +	//char *help; +	struct file *file; +	int lineno; +	void *data; +}; + +#define MENU_CHANGED		0x0001 +#define MENU_ROOT		0x0002 + +#ifndef SWIG + +extern struct file *file_list; +extern struct file *current_file; +struct file *lookup_file(const char *name); + +extern struct symbol symbol_yes, symbol_no, symbol_mod; +extern struct symbol *modules_sym; +extern int cdebug; +struct expr *expr_alloc_symbol(struct symbol *sym); +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); +struct expr *expr_copy(struct expr *org); +void expr_free(struct expr *e); +int expr_eq(struct expr *e1, struct expr *e2); +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); +tristate expr_calc_value(struct expr *e); +struct expr *expr_eliminate_yn(struct expr *e); +struct expr *expr_trans_bool(struct expr *e); +struct expr *expr_eliminate_dups(struct expr *e); +struct expr *expr_transform(struct expr *e); +int expr_contains_symbol(struct expr *dep, struct symbol *sym); +bool expr_depends_symbol(struct expr *dep, struct symbol *sym); +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); + +void expr_fprint(struct expr *e, FILE *out); +struct gstr; /* forward */ +void expr_gstr_print(struct expr *e, struct gstr *gs); + +static inline int expr_is_yes(struct expr *e) +{ +	return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); +} + +static inline int expr_is_no(struct expr *e) +{ +	return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EXPR_H */ diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c new file mode 100644 index 000000000000..6fdbe6e3ce0d --- /dev/null +++ b/scripts/kconfig/gconf.c @@ -0,0 +1,1639 @@ +/* Hey EMACS -*- linux-c -*- */ +/* + * + * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info> + * Released under the terms of the GNU GPL v2.0. + * + */ + +#ifdef HAVE_CONFIG_H +#  include <config.h> +#endif + +#include "lkc.h" +#include "images.c" + +#include <glade/glade.h> +#include <gtk/gtk.h> +#include <glib.h> +#include <gdk/gdkkeysyms.h> + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <stdlib.h> + +//#define DEBUG + +enum { +	SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW +}; + +static gint view_mode = FULL_VIEW; +static gboolean show_name = TRUE; +static gboolean show_range = TRUE; +static gboolean show_value = TRUE; +static gboolean show_all = FALSE; +static gboolean show_debug = FALSE; +static gboolean resizeable = FALSE; + +static gboolean config_changed = FALSE; + +static char nohelp_text[] = +    "Sorry, no help available for this option yet.\n"; + +GtkWidget *main_wnd = NULL; +GtkWidget *tree1_w = NULL;	// left  frame +GtkWidget *tree2_w = NULL;	// right frame +GtkWidget *text_w = NULL; +GtkWidget *hpaned = NULL; +GtkWidget *vpaned = NULL; +GtkWidget *back_btn = NULL; + +GtkTextTag *tag1, *tag2; +GdkColor color; + +GtkTreeStore *tree1, *tree2, *tree; +GtkTreeModel *model1, *model2; +static GtkTreeIter *parents[256]; +static gint indent; + +static struct menu *current; // current node for SINGLE view +static struct menu *browsed; // browsed node for SPLIT view + +enum { +	COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, +	COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, +	COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, +	COL_NUMBER +}; + +static void display_list(void); +static void display_tree(struct menu *menu); +static void display_tree_part(void); +static void update_tree(struct menu *src, GtkTreeIter * dst); +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); +static gchar **fill_row(struct menu *menu); + + +/* Helping/Debugging Functions */ + + +const char *dbg_print_stype(int val) +{ +	static char buf[256]; + +	bzero(buf, 256); + +	if (val == S_UNKNOWN) +		strcpy(buf, "unknown"); +	if (val == S_BOOLEAN) +		strcpy(buf, "boolean"); +	if (val == S_TRISTATE) +		strcpy(buf, "tristate"); +	if (val == S_INT) +		strcpy(buf, "int"); +	if (val == S_HEX) +		strcpy(buf, "hex"); +	if (val == S_STRING) +		strcpy(buf, "string"); +	if (val == S_OTHER) +		strcpy(buf, "other"); + +#ifdef DEBUG +	printf("%s", buf); +#endif + +	return buf; +} + +const char *dbg_print_flags(int val) +{ +	static char buf[256]; + +	bzero(buf, 256); + +	if (val & SYMBOL_YES) +		strcat(buf, "yes/"); +	if (val & SYMBOL_MOD) +		strcat(buf, "mod/"); +	if (val & SYMBOL_NO) +		strcat(buf, "no/"); +	if (val & SYMBOL_CONST) +		strcat(buf, "const/"); +	if (val & SYMBOL_CHECK) +		strcat(buf, "check/"); +	if (val & SYMBOL_CHOICE) +		strcat(buf, "choice/"); +	if (val & SYMBOL_CHOICEVAL) +		strcat(buf, "choiceval/"); +	if (val & SYMBOL_PRINTED) +		strcat(buf, "printed/"); +	if (val & SYMBOL_VALID) +		strcat(buf, "valid/"); +	if (val & SYMBOL_OPTIONAL) +		strcat(buf, "optional/"); +	if (val & SYMBOL_WRITE) +		strcat(buf, "write/"); +	if (val & SYMBOL_CHANGED) +		strcat(buf, "changed/"); +	if (val & SYMBOL_NEW) +		strcat(buf, "new/"); +	if (val & SYMBOL_AUTO) +		strcat(buf, "auto/"); + +	buf[strlen(buf) - 1] = '\0'; +#ifdef DEBUG +	printf("%s", buf); +#endif + +	return buf; +} + +const char *dbg_print_ptype(int val) +{ +	static char buf[256]; + +	bzero(buf, 256); + +	if (val == P_UNKNOWN) +		strcpy(buf, "unknown"); +	if (val == P_PROMPT) +		strcpy(buf, "prompt"); +	if (val == P_COMMENT) +		strcpy(buf, "comment"); +	if (val == P_MENU) +		strcpy(buf, "menu"); +	if (val == P_DEFAULT) +		strcpy(buf, "default"); +	if (val == P_CHOICE) +		strcpy(buf, "choice"); + +#ifdef DEBUG +	printf("%s", buf); +#endif + +	return buf; +} + + +/* Main Window Initialization */ + + +void init_main_window(const gchar * glade_file) +{ +	GladeXML *xml; +	GtkWidget *widget; +	GtkTextBuffer *txtbuf; +	char title[256]; +	GdkPixmap *pixmap; +	GdkBitmap *mask; +	GtkStyle *style; + +	xml = glade_xml_new(glade_file, "window1", NULL); +	if (!xml) +		g_error("GUI loading failed !\n"); +	glade_xml_signal_autoconnect(xml); + +	main_wnd = glade_xml_get_widget(xml, "window1"); +	hpaned = glade_xml_get_widget(xml, "hpaned1"); +	vpaned = glade_xml_get_widget(xml, "vpaned1"); +	tree1_w = glade_xml_get_widget(xml, "treeview1"); +	tree2_w = glade_xml_get_widget(xml, "treeview2"); +	text_w = glade_xml_get_widget(xml, "textview3"); + +	back_btn = glade_xml_get_widget(xml, "button1"); +	gtk_widget_set_sensitive(back_btn, FALSE); + +	widget = glade_xml_get_widget(xml, "show_name1"); +	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, +				       show_name); + +	widget = glade_xml_get_widget(xml, "show_range1"); +	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, +				       show_range); + +	widget = glade_xml_get_widget(xml, "show_data1"); +	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, +				       show_value); + +	style = gtk_widget_get_style(main_wnd); +	widget = glade_xml_get_widget(xml, "toolbar1"); + +	pixmap = gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, +					      &style->bg[GTK_STATE_NORMAL], +					      (gchar **) xpm_single_view); +	gtk_image_set_from_pixmap(GTK_IMAGE +				  (((GtkToolbarChild +				     *) (g_list_nth(GTK_TOOLBAR(widget)-> +						    children, +						    5)->data))->icon), +				  pixmap, mask); +	pixmap = +	    gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, +					 &style->bg[GTK_STATE_NORMAL], +					 (gchar **) xpm_split_view); +	gtk_image_set_from_pixmap(GTK_IMAGE +				  (((GtkToolbarChild +				     *) (g_list_nth(GTK_TOOLBAR(widget)-> +						    children, +						    6)->data))->icon), +				  pixmap, mask); +	pixmap = +	    gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, +					 &style->bg[GTK_STATE_NORMAL], +					 (gchar **) xpm_tree_view); +	gtk_image_set_from_pixmap(GTK_IMAGE +				  (((GtkToolbarChild +				     *) (g_list_nth(GTK_TOOLBAR(widget)-> +						    children, +						    7)->data))->icon), +				  pixmap, mask); + +	switch (view_mode) { +	case SINGLE_VIEW: +		widget = glade_xml_get_widget(xml, "button4"); +		g_signal_emit_by_name(widget, "clicked"); +		break; +	case SPLIT_VIEW: +		widget = glade_xml_get_widget(xml, "button5"); +		g_signal_emit_by_name(widget, "clicked"); +		break; +	case FULL_VIEW: +		widget = glade_xml_get_widget(xml, "button6"); +		g_signal_emit_by_name(widget, "clicked"); +		break; +	} + +	txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); +	tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", +					  "foreground", "red", +					  "weight", PANGO_WEIGHT_BOLD, +					  NULL); +	tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", +					  /*"style", PANGO_STYLE_OBLIQUE, */ +					  NULL); + +	sprintf(title, "Linux Kernel v%s Configuration", +		getenv("KERNELRELEASE")); +	gtk_window_set_title(GTK_WINDOW(main_wnd), title); + +	gtk_widget_show(main_wnd); +} + +void init_tree_model(void) +{ +	gint i; + +	tree = tree2 = gtk_tree_store_new(COL_NUMBER, +					  G_TYPE_STRING, G_TYPE_STRING, +					  G_TYPE_STRING, G_TYPE_STRING, +					  G_TYPE_STRING, G_TYPE_STRING, +					  G_TYPE_POINTER, GDK_TYPE_COLOR, +					  G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, +					  G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, +					  G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, +					  G_TYPE_BOOLEAN); +	model2 = GTK_TREE_MODEL(tree2); + +	for (parents[0] = NULL, i = 1; i < 256; i++) +		parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); + +	tree1 = gtk_tree_store_new(COL_NUMBER, +				   G_TYPE_STRING, G_TYPE_STRING, +				   G_TYPE_STRING, G_TYPE_STRING, +				   G_TYPE_STRING, G_TYPE_STRING, +				   G_TYPE_POINTER, GDK_TYPE_COLOR, +				   G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, +				   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, +				   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, +				   G_TYPE_BOOLEAN); +	model1 = GTK_TREE_MODEL(tree1); +} + +void init_left_tree(void) +{ +	GtkTreeView *view = GTK_TREE_VIEW(tree1_w); +	GtkCellRenderer *renderer; +	GtkTreeSelection *sel; +	GtkTreeViewColumn *column; + +	gtk_tree_view_set_model(view, model1); +	gtk_tree_view_set_headers_visible(view, TRUE); +	gtk_tree_view_set_rules_hint(view, FALSE); +	 +	column = gtk_tree_view_column_new(); +	gtk_tree_view_append_column(view, column); +	gtk_tree_view_column_set_title(column, "Options"); + +	renderer = gtk_cell_renderer_toggle_new(); +	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), +					renderer, FALSE); +	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), +					    renderer, +					    "active", COL_BTNACT, +					    "inconsistent", COL_BTNINC, +					    "visible", COL_BTNVIS,  +					    "radio", COL_BTNRAD, NULL); +	renderer = gtk_cell_renderer_text_new(); +	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), +					renderer, FALSE);	 +	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), +					    renderer, +					    "text", COL_OPTION, +					    "foreground-gdk", +					    COL_COLOR, NULL); + +	sel = gtk_tree_view_get_selection(view); +	gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); +	gtk_widget_realize(tree1_w); +} + +static void renderer_edited(GtkCellRendererText * cell, +			    const gchar * path_string, +			    const gchar * new_text, gpointer user_data); +static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, +			     gchar * arg1, gpointer user_data); + +void init_right_tree(void) +{ +	GtkTreeView *view = GTK_TREE_VIEW(tree2_w); +	GtkCellRenderer *renderer; +	GtkTreeSelection *sel; +	GtkTreeViewColumn *column; +	gint i; + +	gtk_tree_view_set_model(view, model2); +	gtk_tree_view_set_headers_visible(view, TRUE); +	gtk_tree_view_set_rules_hint(view, FALSE); + +	column = gtk_tree_view_column_new(); +	gtk_tree_view_append_column(view, column); +	gtk_tree_view_column_set_title(column, "Options"); + +	renderer = gtk_cell_renderer_pixbuf_new(); +	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), +					renderer, FALSE); +	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), +					    renderer, +					    "pixbuf", COL_PIXBUF, +					    "visible", COL_PIXVIS, NULL); +	renderer = gtk_cell_renderer_toggle_new(); +	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), +					renderer, FALSE); +	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), +					    renderer, +					    "active", COL_BTNACT, +					    "inconsistent", COL_BTNINC, +					    "visible", COL_BTNVIS,  +					    "radio", COL_BTNRAD, NULL); +	/*g_signal_connect(G_OBJECT(renderer), "toggled", +	   G_CALLBACK(renderer_toggled), NULL); */ +	renderer = gtk_cell_renderer_text_new(); +	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), +					renderer, FALSE); +	gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), +					    renderer, +					    "text", COL_OPTION, +					    "foreground-gdk", +					    COL_COLOR, NULL); + +	renderer = gtk_cell_renderer_text_new(); +	gtk_tree_view_insert_column_with_attributes(view, -1, +						    "Name", renderer, +						    "text", COL_NAME, +						    "foreground-gdk", +						    COL_COLOR, NULL); +	renderer = gtk_cell_renderer_text_new(); +	gtk_tree_view_insert_column_with_attributes(view, -1, +						    "N", renderer, +						    "text", COL_NO, +						    "foreground-gdk", +						    COL_COLOR, NULL); +	renderer = gtk_cell_renderer_text_new(); +	gtk_tree_view_insert_column_with_attributes(view, -1, +						    "M", renderer, +						    "text", COL_MOD, +						    "foreground-gdk", +						    COL_COLOR, NULL); +	renderer = gtk_cell_renderer_text_new(); +	gtk_tree_view_insert_column_with_attributes(view, -1, +						    "Y", renderer, +						    "text", COL_YES, +						    "foreground-gdk", +						    COL_COLOR, NULL); +	renderer = gtk_cell_renderer_text_new(); +	gtk_tree_view_insert_column_with_attributes(view, -1, +						    "Value", renderer, +						    "text", COL_VALUE, +						    "editable", +						    COL_EDIT, +						    "foreground-gdk", +						    COL_COLOR, NULL); +	g_signal_connect(G_OBJECT(renderer), "edited", +			 G_CALLBACK(renderer_edited), NULL); + +	column = gtk_tree_view_get_column(view, COL_NAME); +	gtk_tree_view_column_set_visible(column, show_name); +	column = gtk_tree_view_get_column(view, COL_NO); +	gtk_tree_view_column_set_visible(column, show_range); +	column = gtk_tree_view_get_column(view, COL_MOD); +	gtk_tree_view_column_set_visible(column, show_range); +	column = gtk_tree_view_get_column(view, COL_YES); +	gtk_tree_view_column_set_visible(column, show_range); +	column = gtk_tree_view_get_column(view, COL_VALUE); +	gtk_tree_view_column_set_visible(column, show_value); + +	if (resizeable) { +		for (i = 0; i < COL_VALUE; i++) { +			column = gtk_tree_view_get_column(view, i); +			gtk_tree_view_column_set_resizable(column, TRUE); +		} +	} + +	sel = gtk_tree_view_get_selection(view); +	gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); +} + + +/* Utility Functions */ + + +static void text_insert_help(struct menu *menu) +{ +	GtkTextBuffer *buffer; +	GtkTextIter start, end; +	const char *prompt = menu_get_prompt(menu); +	gchar *name; +	const char *help = nohelp_text; + +	if (!menu->sym) +		help = ""; +	else if (menu->sym->help) +		help = menu->sym->help; + +	if (menu->sym && menu->sym->name) +		name = g_strdup_printf(menu->sym->name); +	else +		name = g_strdup(""); + +	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); +	gtk_text_buffer_get_bounds(buffer, &start, &end); +	gtk_text_buffer_delete(buffer, &start, &end); +	gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + +	gtk_text_buffer_get_end_iter(buffer, &end); +	gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, +					 NULL); +	gtk_text_buffer_insert_at_cursor(buffer, " ", 1); +	gtk_text_buffer_get_end_iter(buffer, &end); +	gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1, +					 NULL); +	gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); +	gtk_text_buffer_get_end_iter(buffer, &end); +	gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2, +					 NULL); +} + + +static void text_insert_msg(const char *title, const char *message) +{ +	GtkTextBuffer *buffer; +	GtkTextIter start, end; +	const char *msg = message; + +	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); +	gtk_text_buffer_get_bounds(buffer, &start, &end); +	gtk_text_buffer_delete(buffer, &start, &end); +	gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + +	gtk_text_buffer_get_end_iter(buffer, &end); +	gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, +					 NULL); +	gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); +	gtk_text_buffer_get_end_iter(buffer, &end); +	gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, +					 NULL); +} + + +/* Main Windows Callbacks */ + +void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data); +gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, +				 gpointer user_data) +{ +	GtkWidget *dialog, *label; +	gint result; + +	if (config_changed == FALSE) +		return FALSE; + +	dialog = gtk_dialog_new_with_buttons("Warning !", +					     GTK_WINDOW(main_wnd), +					     (GtkDialogFlags) +					     (GTK_DIALOG_MODAL | +					      GTK_DIALOG_DESTROY_WITH_PARENT), +					     GTK_STOCK_OK, +					     GTK_RESPONSE_YES, +					     GTK_STOCK_NO, +					     GTK_RESPONSE_NO, +					     GTK_STOCK_CANCEL, +					     GTK_RESPONSE_CANCEL, NULL); +	gtk_dialog_set_default_response(GTK_DIALOG(dialog), +					GTK_RESPONSE_CANCEL); + +	label = gtk_label_new("\nSave configuration ?\n"); +	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); +	gtk_widget_show(label); + +	result = gtk_dialog_run(GTK_DIALOG(dialog)); +	switch (result) { +	case GTK_RESPONSE_YES: +		on_save1_activate(NULL, NULL); +		return FALSE; +	case GTK_RESPONSE_NO: +		return FALSE; +	case GTK_RESPONSE_CANCEL: +	case GTK_RESPONSE_DELETE_EVENT: +	default: +		gtk_widget_destroy(dialog); +		return TRUE; +	} + +	return FALSE; +} + + +void on_window1_destroy(GtkObject * object, gpointer user_data) +{ +	gtk_main_quit(); +} + + +void +on_window1_size_request(GtkWidget * widget, +			GtkRequisition * requisition, gpointer user_data) +{ +	static gint old_h; +	gint w, h; + +	if (widget->window == NULL) +		gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); +	else +		gdk_window_get_size(widget->window, &w, &h); + +	if (h == old_h) +		return; +	old_h = h; + +	gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); +} + + +/* Menu & Toolbar Callbacks */ + + +static void +load_filename(GtkFileSelection * file_selector, gpointer user_data) +{ +	const gchar *fn; + +	fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION +					     (user_data)); + +	if (conf_read(fn)) +		text_insert_msg("Error", "Unable to load configuration !"); +	else +		display_tree(&rootmenu); +} + +void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	GtkWidget *fs; + +	fs = gtk_file_selection_new("Load file..."); +	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), +			 "clicked", +			 G_CALLBACK(load_filename), (gpointer) fs); +	g_signal_connect_swapped(GTK_OBJECT +				 (GTK_FILE_SELECTION(fs)->ok_button), +				 "clicked", G_CALLBACK(gtk_widget_destroy), +				 (gpointer) fs); +	g_signal_connect_swapped(GTK_OBJECT +				 (GTK_FILE_SELECTION(fs)->cancel_button), +				 "clicked", G_CALLBACK(gtk_widget_destroy), +				 (gpointer) fs); +	gtk_widget_show(fs); +} + + +void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	if (conf_write(NULL)) +		text_insert_msg("Error", "Unable to save configuration !"); + +	config_changed = FALSE; +} + + +static void +store_filename(GtkFileSelection * file_selector, gpointer user_data) +{ +	const gchar *fn; + +	fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION +					     (user_data)); + +	if (conf_write(fn)) +		text_insert_msg("Error", "Unable to save configuration !"); + +	gtk_widget_destroy(GTK_WIDGET(user_data)); +} + +void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	GtkWidget *fs; + +	fs = gtk_file_selection_new("Save file as..."); +	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), +			 "clicked", +			 G_CALLBACK(store_filename), (gpointer) fs); +	g_signal_connect_swapped(GTK_OBJECT +				 (GTK_FILE_SELECTION(fs)->ok_button), +				 "clicked", G_CALLBACK(gtk_widget_destroy), +				 (gpointer) fs); +	g_signal_connect_swapped(GTK_OBJECT +				 (GTK_FILE_SELECTION(fs)->cancel_button), +				 "clicked", G_CALLBACK(gtk_widget_destroy), +				 (gpointer) fs); +	gtk_widget_show(fs); +} + + +void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	if (!on_window1_delete_event(NULL, NULL, NULL)) +		gtk_widget_destroy(GTK_WIDGET(main_wnd)); +} + + +void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	GtkTreeViewColumn *col; + +	show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; +	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); +	if (col) +		gtk_tree_view_column_set_visible(col, show_name); +} + + +void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	GtkTreeViewColumn *col; + +	show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; +	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); +	if (col) +		gtk_tree_view_column_set_visible(col, show_range); +	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); +	if (col) +		gtk_tree_view_column_set_visible(col, show_range); +	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); +	if (col) +		gtk_tree_view_column_set_visible(col, show_range); + +} + + +void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	GtkTreeViewColumn *col; + +	show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; +	col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); +	if (col) +		gtk_tree_view_column_set_visible(col, show_value); +} + + +void +on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	show_all = GTK_CHECK_MENU_ITEM(menuitem)->active; + +	gtk_tree_store_clear(tree2); +	display_tree(&rootmenu);	// instead of update_tree to speed-up +} + + +void +on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active; +	update_tree(&rootmenu, NULL); +} + + +void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	GtkWidget *dialog; +	const gchar *intro_text = +	    "Welcome to gkc, the GTK+ graphical kernel configuration tool\n" +	    "for Linux.\n" +	    "For each option, a blank box indicates the feature is disabled, a\n" +	    "check indicates it is enabled, and a dot indicates that it is to\n" +	    "be compiled as a module.  Clicking on the box will cycle through the three states.\n" +	    "\n" +	    "If you do not see an option (e.g., a device driver) that you\n" +	    "believe should be present, try turning on Show All Options\n" +	    "under the Options menu.\n" +	    "Although there is no cross reference yet to help you figure out\n" +	    "what other options must be enabled to support the option you\n" +	    "are interested in, you can still view the help of a grayed-out\n" +	    "option.\n" +	    "\n" +	    "Toggling Show Debug Info under the Options menu will show \n" +	    "the dependencies, which you can then match by examining other options."; + +	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), +					GTK_DIALOG_DESTROY_WITH_PARENT, +					GTK_MESSAGE_INFO, +					GTK_BUTTONS_CLOSE, intro_text); +	g_signal_connect_swapped(GTK_OBJECT(dialog), "response", +				 G_CALLBACK(gtk_widget_destroy), +				 GTK_OBJECT(dialog)); +	gtk_widget_show_all(dialog); +} + + +void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	GtkWidget *dialog; +	const gchar *about_text = +	    "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n" +	    "Based on the source code from Roman Zippel.\n"; + +	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), +					GTK_DIALOG_DESTROY_WITH_PARENT, +					GTK_MESSAGE_INFO, +					GTK_BUTTONS_CLOSE, about_text); +	g_signal_connect_swapped(GTK_OBJECT(dialog), "response", +				 G_CALLBACK(gtk_widget_destroy), +				 GTK_OBJECT(dialog)); +	gtk_widget_show_all(dialog); +} + + +void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ +	GtkWidget *dialog; +	const gchar *license_text = +	    "gkc is released under the terms of the GNU GPL v2.\n" +	    "For more information, please see the source code or\n" +	    "visit http://www.fsf.org/licenses/licenses.html\n"; + +	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), +					GTK_DIALOG_DESTROY_WITH_PARENT, +					GTK_MESSAGE_INFO, +					GTK_BUTTONS_CLOSE, license_text); +	g_signal_connect_swapped(GTK_OBJECT(dialog), "response", +				 G_CALLBACK(gtk_widget_destroy), +				 GTK_OBJECT(dialog)); +	gtk_widget_show_all(dialog); +} + + +void on_back_pressed(GtkButton * button, gpointer user_data) +{ +	enum prop_type ptype; + +	current = current->parent; +	ptype = current->prompt ? current->prompt->type : P_UNKNOWN; +	if (ptype != P_MENU) +		current = current->parent; +	display_tree_part(); + +	if (current == &rootmenu) +		gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_load_pressed(GtkButton * button, gpointer user_data) +{ +	on_load1_activate(NULL, user_data); +} + + +void on_save_pressed(GtkButton * button, gpointer user_data) +{ +	on_save1_activate(NULL, user_data); +} + + +void on_single_clicked(GtkButton * button, gpointer user_data) +{ +	view_mode = SINGLE_VIEW; +	gtk_paned_set_position(GTK_PANED(hpaned), 0); +	gtk_widget_hide(tree1_w); +	current = &rootmenu; +	display_tree_part(); +} + + +void on_split_clicked(GtkButton * button, gpointer user_data) +{ +	gint w, h; +	view_mode = SPLIT_VIEW; +	gtk_widget_show(tree1_w); +	gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); +	gtk_paned_set_position(GTK_PANED(hpaned), w / 2); +	if (tree2)	 +		gtk_tree_store_clear(tree2); +	display_list(); +} + + +void on_full_clicked(GtkButton * button, gpointer user_data) +{ +	view_mode = FULL_VIEW; +	gtk_paned_set_position(GTK_PANED(hpaned), 0); +	gtk_widget_hide(tree1_w); +	if (tree2) +		gtk_tree_store_clear(tree2); +	display_tree(&rootmenu); +	gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_collapse_pressed(GtkButton * button, gpointer user_data) +{ +	gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); +} + + +void on_expand_pressed(GtkButton * button, gpointer user_data) +{ +	gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + + +/* CTree Callbacks */ + +/* Change hex/int/string value in the cell */ +static void renderer_edited(GtkCellRendererText * cell, +			    const gchar * path_string, +			    const gchar * new_text, gpointer user_data) +{ +	GtkTreePath *path = gtk_tree_path_new_from_string(path_string); +	GtkTreeIter iter; +	const char *old_def, *new_def; +	struct menu *menu; +	struct symbol *sym; + +	if (!gtk_tree_model_get_iter(model2, &iter, path)) +		return; + +	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); +	sym = menu->sym; + +	gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); +	new_def = new_text; + +	sym_set_string_value(sym, new_def); + +	config_changed = TRUE; +	update_tree(&rootmenu, NULL); + +	gtk_tree_path_free(path); +} + +/* Change the value of a symbol and update the tree */ +static void change_sym_value(struct menu *menu, gint col) +{ +	struct symbol *sym = menu->sym; +	tristate oldval, newval; + +	if (!sym) +		return; + +	if (col == COL_NO) +		newval = no; +	else if (col == COL_MOD) +		newval = mod; +	else if (col == COL_YES) +		newval = yes; +	else +		return; + +	switch (sym_get_type(sym)) { +	case S_BOOLEAN: +	case S_TRISTATE: +		oldval = sym_get_tristate_value(sym); +		if (!sym_tristate_within_range(sym, newval)) +			newval = yes; +		sym_set_tristate_value(sym, newval); +		config_changed = TRUE; +		if (view_mode == FULL_VIEW) +			update_tree(&rootmenu, NULL); +		else if (view_mode == SPLIT_VIEW) { +			update_tree(browsed, NULL); +			display_list(); +		} +		else if (view_mode == SINGLE_VIEW) +			display_tree_part();	//fixme: keep exp/coll +		break; +	case S_INT: +	case S_HEX: +	case S_STRING: +	default: +		break; +	} +} + +static void toggle_sym_value(struct menu *menu) +{ +	if (!menu->sym) +		return; + +	sym_toggle_tristate_value(menu->sym); +	if (view_mode == FULL_VIEW) +		update_tree(&rootmenu, NULL); +	else if (view_mode == SPLIT_VIEW) { +		update_tree(browsed, NULL); +		display_list(); +	} +	else if (view_mode == SINGLE_VIEW) +		display_tree_part();	//fixme: keep exp/coll +} + +static void renderer_toggled(GtkCellRendererToggle * cell, +			     gchar * path_string, gpointer user_data) +{ +	GtkTreePath *path, *sel_path = NULL; +	GtkTreeIter iter, sel_iter; +	GtkTreeSelection *sel; +	struct menu *menu; + +	path = gtk_tree_path_new_from_string(path_string); +	if (!gtk_tree_model_get_iter(model2, &iter, path)) +		return; + +	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w)); +	if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter)) +		sel_path = gtk_tree_model_get_path(model2, &sel_iter); +	if (!sel_path) +		goto out1; +	if (gtk_tree_path_compare(path, sel_path)) +		goto out2; + +	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); +	toggle_sym_value(menu); + +      out2: +	gtk_tree_path_free(sel_path); +      out1: +	gtk_tree_path_free(path); +} + +static gint column2index(GtkTreeViewColumn * column) +{ +	gint i; + +	for (i = 0; i < COL_NUMBER; i++) { +		GtkTreeViewColumn *col; + +		col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); +		if (col == column) +			return i; +	} + +	return -1; +} + + +/* User click: update choice (full) or goes down (single) */ +gboolean +on_treeview2_button_press_event(GtkWidget * widget, +				GdkEventButton * event, gpointer user_data) +{ +	GtkTreeView *view = GTK_TREE_VIEW(widget); +	GtkTreePath *path; +	GtkTreeViewColumn *column; +	GtkTreeIter iter; +	struct menu *menu; +	gint col; + +#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK +	gint tx = (gint) event->x; +	gint ty = (gint) event->y; +	gint cx, cy; + +	gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, +				      &cy); +#else +	gtk_tree_view_get_cursor(view, &path, &column); +#endif +	if (path == NULL) +		return FALSE; + +	if (!gtk_tree_model_get_iter(model2, &iter, path)) +		return FALSE; +	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + +	col = column2index(column); +	if (event->type == GDK_2BUTTON_PRESS) { +		enum prop_type ptype; +		ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + +		if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { +			// goes down into menu +			current = menu; +			display_tree_part(); +			gtk_widget_set_sensitive(back_btn, TRUE); +		} else if ((col == COL_OPTION)) { +			toggle_sym_value(menu); +			gtk_tree_view_expand_row(view, path, TRUE); +		} +	} else { +		if (col == COL_VALUE) { +			toggle_sym_value(menu); +			gtk_tree_view_expand_row(view, path, TRUE); +		} else if (col == COL_NO || col == COL_MOD +			   || col == COL_YES) { +			change_sym_value(menu, col); +			gtk_tree_view_expand_row(view, path, TRUE); +		} +	} + +	return FALSE; +} + +/* Key pressed: update choice */ +gboolean +on_treeview2_key_press_event(GtkWidget * widget, +			     GdkEventKey * event, gpointer user_data) +{ +	GtkTreeView *view = GTK_TREE_VIEW(widget); +	GtkTreePath *path; +	GtkTreeViewColumn *column; +	GtkTreeIter iter; +	struct menu *menu; +	gint col; + +	gtk_tree_view_get_cursor(view, &path, &column); +	if (path == NULL) +		return FALSE; + +	if (event->keyval == GDK_space) { +		if (gtk_tree_view_row_expanded(view, path)) +			gtk_tree_view_collapse_row(view, path); +		else +			gtk_tree_view_expand_row(view, path, FALSE); +		return TRUE; +	} +	if (event->keyval == GDK_KP_Enter) { +	} +	if (widget == tree1_w) +		return FALSE; + +	gtk_tree_model_get_iter(model2, &iter, path); +	gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + +	if (!strcasecmp(event->string, "n")) +		col = COL_NO; +	else if (!strcasecmp(event->string, "m")) +		col = COL_MOD; +	else if (!strcasecmp(event->string, "y")) +		col = COL_YES; +	else +		col = -1; +	change_sym_value(menu, col); + +	return FALSE; +} + + +/* Row selection changed: update help */ +void +on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) +{ +	GtkTreeSelection *selection; +	GtkTreeIter iter; +	struct menu *menu; + +	selection = gtk_tree_view_get_selection(treeview); +	if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { +		gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); +		text_insert_help(menu); +	} +} + + +/* User click: display sub-tree in the right frame. */ +gboolean +on_treeview1_button_press_event(GtkWidget * widget, +				GdkEventButton * event, gpointer user_data) +{ +	GtkTreeView *view = GTK_TREE_VIEW(widget); +	GtkTreePath *path; +	GtkTreeViewColumn *column; +	GtkTreeIter iter; +	struct menu *menu; + +	gint tx = (gint) event->x; +	gint ty = (gint) event->y; +	gint cx, cy; + +	gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, +				      &cy); +	if (path == NULL) +		return FALSE; + +	gtk_tree_model_get_iter(model1, &iter, path); +	gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); + +	if (event->type == GDK_2BUTTON_PRESS) { +		toggle_sym_value(menu); +		current = menu; +		display_tree_part(); +	} else { +		browsed = menu; +		display_tree_part(); +	} + +	gtk_widget_realize(tree2_w); +	gtk_tree_view_set_cursor(view, path, NULL, FALSE); +	gtk_widget_grab_focus(tree2_w); + +	return FALSE; +} + + +/* Fill a row of strings */ +static gchar **fill_row(struct menu *menu) +{ +	static gchar *row[COL_NUMBER]; +	struct symbol *sym = menu->sym; +	const char *def; +	int stype; +	tristate val; +	enum prop_type ptype; +	int i; + +	for (i = COL_OPTION; i <= COL_COLOR; i++) +		g_free(row[i]); +	bzero(row, sizeof(row)); + +	row[COL_OPTION] = +	    g_strdup_printf("%s %s", menu_get_prompt(menu), +			    sym ? (sym-> +				   flags & SYMBOL_NEW ? "(NEW)" : "") : +			    ""); + +	if (show_all && !menu_is_visible(menu)) +		row[COL_COLOR] = g_strdup("DarkGray"); +	else +		row[COL_COLOR] = g_strdup("Black"); + +	ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; +	switch (ptype) { +	case P_MENU: +		row[COL_PIXBUF] = (gchar *) xpm_menu; +		if (view_mode == SINGLE_VIEW) +			row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); +		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); +		break; +	case P_COMMENT: +		row[COL_PIXBUF] = (gchar *) xpm_void; +		row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); +		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); +		break; +	default: +		row[COL_PIXBUF] = (gchar *) xpm_void; +		row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); +		row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); +		break; +	} + +	if (!sym) +		return row; +	row[COL_NAME] = g_strdup(sym->name); + +	sym_calc_value(sym); +	sym->flags &= ~SYMBOL_CHANGED; + +	if (sym_is_choice(sym)) {	// parse childs for getting final value +		struct menu *child; +		struct symbol *def_sym = sym_get_choice_value(sym); +		struct menu *def_menu = NULL; + +		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + +		for (child = menu->list; child; child = child->next) { +			if (menu_is_visible(child) +			    && child->sym == def_sym) +				def_menu = child; +		} + +		if (def_menu) +			row[COL_VALUE] = +			    g_strdup(menu_get_prompt(def_menu)); +	} +	if(sym->flags & SYMBOL_CHOICEVAL) +		row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); + +	stype = sym_get_type(sym); +	switch (stype) { +	case S_BOOLEAN: +		if(GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) +			row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); +		if (sym_is_choice(sym)) +			break; +	case S_TRISTATE: +		val = sym_get_tristate_value(sym); +		switch (val) { +		case no: +			row[COL_NO] = g_strdup("N"); +			row[COL_VALUE] = g_strdup("N"); +			row[COL_BTNACT] = GINT_TO_POINTER(FALSE); +			row[COL_BTNINC] = GINT_TO_POINTER(FALSE); +			break; +		case mod: +			row[COL_MOD] = g_strdup("M"); +			row[COL_VALUE] = g_strdup("M"); +			row[COL_BTNINC] = GINT_TO_POINTER(TRUE); +			break; +		case yes: +			row[COL_YES] = g_strdup("Y"); +			row[COL_VALUE] = g_strdup("Y"); +			row[COL_BTNACT] = GINT_TO_POINTER(TRUE); +			row[COL_BTNINC] = GINT_TO_POINTER(FALSE); +			break; +		} + +		if (val != no && sym_tristate_within_range(sym, no)) +			row[COL_NO] = g_strdup("_"); +		if (val != mod && sym_tristate_within_range(sym, mod)) +			row[COL_MOD] = g_strdup("_"); +		if (val != yes && sym_tristate_within_range(sym, yes)) +			row[COL_YES] = g_strdup("_"); +		break; +	case S_INT: +	case S_HEX: +	case S_STRING: +		def = sym_get_string_value(sym); +		row[COL_VALUE] = g_strdup(def); +		row[COL_EDIT] = GINT_TO_POINTER(TRUE); +		row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); +		break; +	} + +	return row; +} + + +/* Set the node content with a row of strings */ +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) +{ +	GdkColor color; +	gboolean success; +	GdkPixbuf *pix; + +	pix = gdk_pixbuf_new_from_xpm_data((const char **) +					   row[COL_PIXBUF]); + +	gdk_color_parse(row[COL_COLOR], &color); +	gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, +				  FALSE, FALSE, &success); + +	gtk_tree_store_set(tree, node, +			   COL_OPTION, row[COL_OPTION], +			   COL_NAME, row[COL_NAME], +			   COL_NO, row[COL_NO], +			   COL_MOD, row[COL_MOD], +			   COL_YES, row[COL_YES], +			   COL_VALUE, row[COL_VALUE], +			   COL_MENU, (gpointer) menu, +			   COL_COLOR, &color, +			   COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), +			   COL_PIXBUF, pix, +			   COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), +			   COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), +			   COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), +			   COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), +			   COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), +			   -1); + +	g_object_unref(pix); +} + + +/* Add a node to the tree */ +static void place_node(struct menu *menu, char **row) +{ +	GtkTreeIter *parent = parents[indent - 1]; +	GtkTreeIter *node = parents[indent]; + +	gtk_tree_store_append(tree, node, parent); +	set_node(node, menu, row); +} + + +/* Find a node in the GTK+ tree */ +static GtkTreeIter found; + +/* + * Find a menu in the GtkTree starting at parent. + */ +GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, +				    struct menu *tofind) +{ +	GtkTreeIter iter; +	GtkTreeIter *child = &iter; +	gboolean valid; +	GtkTreeIter *ret; + +	valid = gtk_tree_model_iter_children(model2, child, parent); +	while (valid) { +		struct menu *menu; + +		gtk_tree_model_get(model2, child, 6, &menu, -1); + +		if (menu == tofind) { +			memcpy(&found, child, sizeof(GtkTreeIter)); +			return &found; +		} + +		ret = gtktree_iter_find_node(child, tofind); +		if (ret) +			return ret; + +		valid = gtk_tree_model_iter_next(model2, child); +	} + +	return NULL; +} + + +/* + * Update the tree by adding/removing entries + * Does not change other nodes + */ +static void update_tree(struct menu *src, GtkTreeIter * dst) +{ +	struct menu *child1; +	GtkTreeIter iter, tmp; +	GtkTreeIter *child2 = &iter; +	gboolean valid; +	GtkTreeIter *sibling; +	struct symbol *sym; +	struct property *prop; +	struct menu *menu1, *menu2; + +	if (src == &rootmenu) +		indent = 1; + +	valid = gtk_tree_model_iter_children(model2, child2, dst); +	for (child1 = src->list; child1; child1 = child1->next) { + +		prop = child1->prompt; +		sym = child1->sym; + +	      reparse: +		menu1 = child1; +		if (valid) +			gtk_tree_model_get(model2, child2, COL_MENU, +					   &menu2, -1); +		else +			menu2 = NULL;	// force adding of a first child + +#ifdef DEBUG +		printf("%*c%s | %s\n", indent, ' ', +		       menu1 ? menu_get_prompt(menu1) : "nil", +		       menu2 ? menu_get_prompt(menu2) : "nil"); +#endif + +		if (!menu_is_visible(child1) && !show_all) {	// remove node +			if (gtktree_iter_find_node(dst, menu1) != NULL) { +				memcpy(&tmp, child2, sizeof(GtkTreeIter)); +				valid = gtk_tree_model_iter_next(model2, +								 child2); +				gtk_tree_store_remove(tree2, &tmp); +				if (!valid) +					return;	// next parent  +				else +					goto reparse;	// next child +			} else +				continue; +		} + +		if (menu1 != menu2) { +			if (gtktree_iter_find_node(dst, menu1) == NULL) {	// add node +				if (!valid && !menu2) +					sibling = NULL; +				else +					sibling = child2; +				gtk_tree_store_insert_before(tree2, +							     child2, +							     dst, sibling); +				set_node(child2, menu1, fill_row(menu1)); +				if (menu2 == NULL) +					valid = TRUE; +			} else {	// remove node +				memcpy(&tmp, child2, sizeof(GtkTreeIter)); +				valid = gtk_tree_model_iter_next(model2, +								 child2); +				gtk_tree_store_remove(tree2, &tmp); +				if (!valid) +					return;	// next parent  +				else +					goto reparse;	// next child +			} +		} else if (sym && (sym->flags & SYMBOL_CHANGED)) { +			set_node(child2, menu1, fill_row(menu1)); +		} + +		indent++; +		update_tree(child1, child2); +		indent--; + +		valid = gtk_tree_model_iter_next(model2, child2); +	} +} + + +/* Display the whole tree (single/split/full view) */ +static void display_tree(struct menu *menu) +{ +	struct symbol *sym; +	struct property *prop; +	struct menu *child; +	enum prop_type ptype; + +	if (menu == &rootmenu) { +		indent = 1; +		current = &rootmenu; +	} + +	for (child = menu->list; child; child = child->next) { +		prop = child->prompt; +		sym = child->sym; +		ptype = prop ? prop->type : P_UNKNOWN; + +		if (sym) +			sym->flags &= ~SYMBOL_CHANGED; + +		if ((view_mode == SPLIT_VIEW) && !(child->flags & MENU_ROOT) && +		    (tree == tree1)) +			continue; + +		if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) && +		    (tree == tree2)) +			continue; + +		if (menu_is_visible(child) || show_all) +			place_node(child, fill_row(child)); +#ifdef DEBUG +		printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); +		printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); +		dbg_print_ptype(ptype); +		printf(" | "); +		if (sym) { +			dbg_print_stype(sym->type); +			printf(" | "); +			dbg_print_flags(sym->flags); +			printf("\n"); +		} else +			printf("\n"); +#endif +		if ((view_mode != FULL_VIEW) && (ptype == P_MENU) +		    && (tree == tree2)) +			continue; +/* +		if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) || +		    (view_mode == FULL_VIEW) +		    || (view_mode == SPLIT_VIEW))*/ +		if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) +		    || (view_mode == FULL_VIEW) || (view_mode == SPLIT_VIEW)) { +			indent++; +			display_tree(child); +			indent--; +		} +	} +} + +/* Display a part of the tree starting at current node (single/split view) */ +static void display_tree_part(void) +{ +	if (tree2) +		gtk_tree_store_clear(tree2); +	if(view_mode == SINGLE_VIEW) +		display_tree(current); + 	else if(view_mode == SPLIT_VIEW) +		display_tree(browsed); +	gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + +/* Display the list in the left frame (split view) */ +static void display_list(void) +{ +	if (tree1) +		gtk_tree_store_clear(tree1); + +	tree = tree1; +	display_tree(&rootmenu); +	gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); +	tree = tree2; +} + +void fixup_rootmenu(struct menu *menu) +{ +        struct menu *child; +        static int menu_cnt = 0; + +        menu->flags |= MENU_ROOT; +        for (child = menu->list; child; child = child->next) { +                if (child->prompt && child->prompt->type == P_MENU) { +                        menu_cnt++; +                        fixup_rootmenu(child); +                        menu_cnt--; +                } else if (!menu_cnt) +                        fixup_rootmenu(child); +        } +} + + +/* Main */ + + +int main(int ac, char *av[]) +{ +	const char *name; +	char *env; +	gchar *glade_file; + +#ifndef LKC_DIRECT_LINK +	kconfig_load(); +#endif + +	/* GTK stuffs */ +	gtk_set_locale(); +	gtk_init(&ac, &av); +	glade_init(); + +	//add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); +	//add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); + +	/* Determine GUI path */ +	env = getenv(SRCTREE); +	if (env) +		glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL); +	else if (av[0][0] == '/') +		glade_file = g_strconcat(av[0], ".glade", NULL); +	else +		glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL); + +	/* Load the interface and connect signals */ +	init_main_window(glade_file); +	init_tree_model(); +	init_left_tree(); +	init_right_tree(); + +	/* Conf stuffs */ +	if (ac > 1 && av[1][0] == '-') { +		switch (av[1][1]) { +		case 'a': +			//showAll = 1; +			break; +		case 'h': +		case '?': +			printf("%s <config>\n", av[0]); +			exit(0); +		} +		name = av[2]; +	} else +		name = av[1]; + +	conf_parse(name); +	fixup_rootmenu(&rootmenu); +	conf_read(NULL); + +	switch (view_mode) { +	case SINGLE_VIEW: +		display_tree_part(); +		break; +	case SPLIT_VIEW: +		display_list(); +		break; +	case FULL_VIEW: +		display_tree(&rootmenu); +		break; +	} + +	gtk_main(); + +	return 0; +} diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade new file mode 100644 index 000000000000..1e1736d81ee9 --- /dev/null +++ b/scripts/kconfig/gconf.glade @@ -0,0 +1,543 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="window1"> +  <property name="visible">True</property> +  <property name="title" translatable="yes">Gtk Kernel Configurator</property> +  <property name="type">GTK_WINDOW_TOPLEVEL</property> +  <property name="window_position">GTK_WIN_POS_NONE</property> +  <property name="modal">False</property> +  <property name="default_width">640</property> +  <property name="default_height">480</property> +  <property name="resizable">True</property> +  <property name="destroy_with_parent">False</property> +  <signal name="destroy" handler="on_window1_destroy" object="window1"/> +  <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/> +  <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/> + +  <child> +    <widget class="GtkVBox" id="vbox1"> +      <property name="visible">True</property> +      <property name="homogeneous">False</property> +      <property name="spacing">0</property> + +      <child> +	<widget class="GtkMenuBar" id="menubar1"> +	  <property name="visible">True</property> + +	  <child> +	    <widget class="GtkMenuItem" id="file1"> +	      <property name="visible">True</property> +	      <property name="label" translatable="yes">_File</property> +	      <property name="use_underline">True</property> + +	      <child> +		<widget class="GtkMenu" id="file1_menu"> + +		  <child> +		    <widget class="GtkImageMenuItem" id="load1"> +		      <property name="visible">True</property> +		      <property name="tooltip" translatable="yes">Load a config file</property> +		      <property name="label" translatable="yes">_Load</property> +		      <property name="use_underline">True</property> +		      <signal name="activate" handler="on_load1_activate"/> +		      <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/> + +		      <child internal-child="image"> +			<widget class="GtkImage" id="image27"> +			  <property name="visible">True</property> +			  <property name="stock">gtk-open</property> +			  <property name="icon_size">1</property> +			  <property name="xalign">0.5</property> +			  <property name="yalign">0.5</property> +			  <property name="xpad">0</property> +			  <property name="ypad">0</property> +			</widget> +		      </child> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkImageMenuItem" id="save1"> +		      <property name="visible">True</property> +		      <property name="tooltip" translatable="yes">Save the config in .config</property> +		      <property name="label" translatable="yes">_Save</property> +		      <property name="use_underline">True</property> +		      <signal name="activate" handler="on_save1_activate"/> +		      <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/> + +		      <child internal-child="image"> +			<widget class="GtkImage" id="image28"> +			  <property name="visible">True</property> +			  <property name="stock">gtk-save</property> +			  <property name="icon_size">1</property> +			  <property name="xalign">0.5</property> +			  <property name="yalign">0.5</property> +			  <property name="xpad">0</property> +			  <property name="ypad">0</property> +			</widget> +		      </child> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkImageMenuItem" id="save_as1"> +		      <property name="visible">True</property> +		      <property name="tooltip" translatable="yes">Save the config in a file</property> +		      <property name="label" translatable="yes">Save _as</property> +		      <property name="use_underline">True</property> +		      <signal name="activate" handler="on_save_as1_activate"/> + +		      <child internal-child="image"> +			<widget class="GtkImage" id="image29"> +			  <property name="visible">True</property> +			  <property name="stock">gtk-save-as</property> +			  <property name="icon_size">1</property> +			  <property name="xalign">0.5</property> +			  <property name="yalign">0.5</property> +			  <property name="xpad">0</property> +			  <property name="ypad">0</property> +			</widget> +		      </child> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkMenuItem" id="separator1"> +		      <property name="visible">True</property> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkImageMenuItem" id="quit1"> +		      <property name="visible">True</property> +		      <property name="label" translatable="yes">_Quit</property> +		      <property name="use_underline">True</property> +		      <signal name="activate" handler="on_quit1_activate"/> +		      <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/> + +		      <child internal-child="image"> +			<widget class="GtkImage" id="image30"> +			  <property name="visible">True</property> +			  <property name="stock">gtk-quit</property> +			  <property name="icon_size">1</property> +			  <property name="xalign">0.5</property> +			  <property name="yalign">0.5</property> +			  <property name="xpad">0</property> +			  <property name="ypad">0</property> +			</widget> +		      </child> +		    </widget> +		  </child> +		</widget> +	      </child> +	    </widget> +	  </child> + +	  <child> +	    <widget class="GtkMenuItem" id="options1"> +	      <property name="visible">True</property> +	      <property name="label" translatable="yes">_Options</property> +	      <property name="use_underline">True</property> + +	      <child> +		<widget class="GtkMenu" id="options1_menu"> + +		  <child> +		    <widget class="GtkCheckMenuItem" id="show_name1"> +		      <property name="visible">True</property> +		      <property name="tooltip" translatable="yes">Show name</property> +		      <property name="label" translatable="yes">Show _name</property> +		      <property name="use_underline">True</property> +		      <property name="active">False</property> +		      <signal name="activate" handler="on_show_name1_activate"/> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkCheckMenuItem" id="show_range1"> +		      <property name="visible">True</property> +		      <property name="tooltip" translatable="yes">Show range (Y/M/N)</property> +		      <property name="label" translatable="yes">Show _range</property> +		      <property name="use_underline">True</property> +		      <property name="active">False</property> +		      <signal name="activate" handler="on_show_range1_activate"/> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkCheckMenuItem" id="show_data1"> +		      <property name="visible">True</property> +		      <property name="tooltip" translatable="yes">Show value of the option</property> +		      <property name="label" translatable="yes">Show _data</property> +		      <property name="use_underline">True</property> +		      <property name="active">False</property> +		      <signal name="activate" handler="on_show_data1_activate"/> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkMenuItem" id="separator2"> +		      <property name="visible">True</property> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkCheckMenuItem" id="show_all_options1"> +		      <property name="visible">True</property> +		      <property name="tooltip" translatable="yes">Show all options</property> +		      <property name="label" translatable="yes">Show all _options</property> +		      <property name="use_underline">True</property> +		      <property name="active">False</property> +		      <signal name="activate" handler="on_show_all_options1_activate"/> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkCheckMenuItem" id="show_debug_info1"> +		      <property name="visible">True</property> +		      <property name="tooltip" translatable="yes">Show masked options</property> +		      <property name="label" translatable="yes">Show _debug info</property> +		      <property name="use_underline">True</property> +		      <property name="active">False</property> +		      <signal name="activate" handler="on_show_debug_info1_activate"/> +		    </widget> +		  </child> +		</widget> +	      </child> +	    </widget> +	  </child> + +	  <child> +	    <widget class="GtkMenuItem" id="help1"> +	      <property name="visible">True</property> +	      <property name="label" translatable="yes">_Help</property> +	      <property name="use_underline">True</property> + +	      <child> +		<widget class="GtkMenu" id="help1_menu"> + +		  <child> +		    <widget class="GtkImageMenuItem" id="introduction1"> +		      <property name="visible">True</property> +		      <property name="label" translatable="yes">_Introduction</property> +		      <property name="use_underline">True</property> +		      <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/> +		      <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/> + +		      <child internal-child="image"> +			<widget class="GtkImage" id="image31"> +			  <property name="visible">True</property> +			  <property name="stock">gtk-dialog-question</property> +			  <property name="icon_size">1</property> +			  <property name="xalign">0.5</property> +			  <property name="yalign">0.5</property> +			  <property name="xpad">0</property> +			  <property name="ypad">0</property> +			</widget> +		      </child> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkImageMenuItem" id="about1"> +		      <property name="visible">True</property> +		      <property name="label" translatable="yes">_About</property> +		      <property name="use_underline">True</property> +		      <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/> +		      <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/> + +		      <child internal-child="image"> +			<widget class="GtkImage" id="image32"> +			  <property name="visible">True</property> +			  <property name="stock">gtk-properties</property> +			  <property name="icon_size">1</property> +			  <property name="xalign">0.5</property> +			  <property name="yalign">0.5</property> +			  <property name="xpad">0</property> +			  <property name="ypad">0</property> +			</widget> +		      </child> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkImageMenuItem" id="license1"> +		      <property name="visible">True</property> +		      <property name="label" translatable="yes">_License</property> +		      <property name="use_underline">True</property> +		      <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/> + +		      <child internal-child="image"> +			<widget class="GtkImage" id="image33"> +			  <property name="visible">True</property> +			  <property name="stock">gtk-justify-fill</property> +			  <property name="icon_size">1</property> +			  <property name="xalign">0.5</property> +			  <property name="yalign">0.5</property> +			  <property name="xpad">0</property> +			  <property name="ypad">0</property> +			</widget> +		      </child> +		    </widget> +		  </child> +		</widget> +	      </child> +	    </widget> +	  </child> +	</widget> +	<packing> +	  <property name="padding">0</property> +	  <property name="expand">False</property> +	  <property name="fill">False</property> +	</packing> +      </child> + +      <child> +	<widget class="GtkHandleBox" id="handlebox1"> +	  <property name="visible">True</property> +	  <property name="shadow_type">GTK_SHADOW_OUT</property> +	  <property name="handle_position">GTK_POS_LEFT</property> +	  <property name="snap_edge">GTK_POS_TOP</property> + +	  <child> +	    <widget class="GtkToolbar" id="toolbar1"> +	      <property name="visible">True</property> +	      <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property> +	      <property name="toolbar_style">GTK_TOOLBAR_BOTH</property> +	      <property name="tooltips">True</property> + +	      <child> +		<widget class="button" id="button1"> +		  <property name="visible">True</property> +		  <property name="tooltip" translatable="yes">Goes up of one level (single view)</property> +		  <property name="label" translatable="yes">Back</property> +		  <property name="use_underline">True</property> +		  <property name="stock_pixmap">gtk-undo</property> +		  <signal name="pressed" handler="on_back_pressed"/> +		</widget> +	      </child> + +	      <child> +		<widget class="GtkVSeparator" id="vseparator1"> +		  <property name="visible">True</property> +		</widget> +	      </child> + +	      <child> +		<widget class="button" id="button2"> +		  <property name="visible">True</property> +		  <property name="tooltip" translatable="yes">Load a config file</property> +		  <property name="label" translatable="yes">Load</property> +		  <property name="use_underline">True</property> +		  <property name="stock_pixmap">gtk-open</property> +		  <signal name="pressed" handler="on_load_pressed"/> +		</widget> +	      </child> + +	      <child> +		<widget class="button" id="button3"> +		  <property name="visible">True</property> +		  <property name="tooltip" translatable="yes">Save a config file</property> +		  <property name="label" translatable="yes">Save</property> +		  <property name="use_underline">True</property> +		  <property name="stock_pixmap">gtk-save</property> +		  <signal name="pressed" handler="on_save_pressed"/> +		</widget> +	      </child> + +	      <child> +		<widget class="GtkVSeparator" id="vseparator2"> +		  <property name="visible">True</property> +		</widget> +	      </child> + +	      <child> +		<widget class="button" id="button4"> +		  <property name="visible">True</property> +		  <property name="tooltip" translatable="yes">Single view</property> +		  <property name="label" translatable="yes">Single</property> +		  <property name="use_underline">True</property> +		  <property name="stock_pixmap">gtk-missing-image</property> +		  <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/> +		</widget> +	      </child> + +	      <child> +		<widget class="button" id="button5"> +		  <property name="visible">True</property> +		  <property name="tooltip" translatable="yes">Split view</property> +		  <property name="label" translatable="yes">Split</property> +		  <property name="use_underline">True</property> +		  <property name="stock_pixmap">gtk-missing-image</property> +		  <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/> +		</widget> +	      </child> + +	      <child> +		<widget class="button" id="button6"> +		  <property name="visible">True</property> +		  <property name="tooltip" translatable="yes">Full view</property> +		  <property name="label" translatable="yes">Full</property> +		  <property name="use_underline">True</property> +		  <property name="stock_pixmap">gtk-missing-image</property> +		  <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/> +		</widget> +	      </child> + +	      <child> +		<widget class="GtkVSeparator" id="vseparator3"> +		  <property name="visible">True</property> +		</widget> +	      </child> + +	      <child> +		<widget class="button" id="button7"> +		  <property name="visible">True</property> +		  <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property> +		  <property name="label" translatable="yes">Collapse</property> +		  <property name="use_underline">True</property> +		  <signal name="pressed" handler="on_collapse_pressed"/> +		</widget> +	      </child> + +	      <child> +		<widget class="button" id="button8"> +		  <property name="visible">True</property> +		  <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property> +		  <property name="label" translatable="yes">Expand</property> +		  <property name="use_underline">True</property> +		  <signal name="pressed" handler="on_expand_pressed"/> +		</widget> +	      </child> +	    </widget> +	  </child> +	</widget> +	<packing> +	  <property name="padding">0</property> +	  <property name="expand">False</property> +	  <property name="fill">False</property> +	</packing> +      </child> + +      <child> +	<widget class="GtkHPaned" id="hpaned1"> +	  <property name="width_request">1</property> +	  <property name="visible">True</property> +	  <property name="can_focus">True</property> +	  <property name="position">0</property> + +	  <child> +	    <widget class="GtkScrolledWindow" id="scrolledwindow1"> +	      <property name="visible">True</property> +	      <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> +	      <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> +	      <property name="shadow_type">GTK_SHADOW_IN</property> +	      <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + +	      <child> +		<widget class="GtkTreeView" id="treeview1"> +		  <property name="visible">True</property> +		  <property name="can_focus">True</property> +		  <property name="headers_visible">True</property> +		  <property name="rules_hint">False</property> +		  <property name="reorderable">False</property> +		  <property name="enable_search">True</property> +		  <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/> +		  <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/> +		  <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/> +		</widget> +	      </child> +	    </widget> +	    <packing> +	      <property name="shrink">True</property> +	      <property name="resize">False</property> +	    </packing> +	  </child> + +	  <child> +	    <widget class="GtkVPaned" id="vpaned1"> +	      <property name="visible">True</property> +	      <property name="can_focus">True</property> +	      <property name="position">0</property> + +	      <child> +		<widget class="GtkScrolledWindow" id="scrolledwindow2"> +		  <property name="visible">True</property> +		  <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> +		  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> +		  <property name="shadow_type">GTK_SHADOW_IN</property> +		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + +		  <child> +		    <widget class="GtkTreeView" id="treeview2"> +		      <property name="visible">True</property> +		      <property name="can_focus">True</property> +		      <property name="has_focus">True</property> +		      <property name="headers_visible">True</property> +		      <property name="rules_hint">False</property> +		      <property name="reorderable">False</property> +		      <property name="enable_search">True</property> +		      <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/> +		      <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/> +		      <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/> +		    </widget> +		  </child> +		</widget> +		<packing> +		  <property name="shrink">True</property> +		  <property name="resize">False</property> +		</packing> +	      </child> + +	      <child> +		<widget class="GtkScrolledWindow" id="scrolledwindow3"> +		  <property name="visible">True</property> +		  <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> +		  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> +		  <property name="shadow_type">GTK_SHADOW_IN</property> +		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + +		  <child> +		    <widget class="GtkTextView" id="textview3"> +		      <property name="visible">True</property> +		      <property name="can_focus">True</property> +		      <property name="editable">False</property> +		      <property name="justification">GTK_JUSTIFY_LEFT</property> +		      <property name="wrap_mode">GTK_WRAP_WORD</property> +		      <property name="cursor_visible">True</property> +		      <property name="pixels_above_lines">0</property> +		      <property name="pixels_below_lines">0</property> +		      <property name="pixels_inside_wrap">0</property> +		      <property name="left_margin">0</property> +		      <property name="right_margin">0</property> +		      <property name="indent">0</property> +		      <property name="text" translatable="yes">Sorry, no help available for this option yet.</property> +		    </widget> +		  </child> +		</widget> +		<packing> +		  <property name="shrink">True</property> +		  <property name="resize">True</property> +		</packing> +	      </child> +	    </widget> +	    <packing> +	      <property name="shrink">True</property> +	      <property name="resize">True</property> +	    </packing> +	  </child> +	</widget> +	<packing> +	  <property name="padding">0</property> +	  <property name="expand">True</property> +	  <property name="fill">True</property> +	</packing> +      </child> +    </widget> +  </child> +</widget> + +</glade-interface> diff --git a/scripts/kconfig/images.c b/scripts/kconfig/images.c new file mode 100644 index 000000000000..d4f84bd4a96b --- /dev/null +++ b/scripts/kconfig/images.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +static const char *xpm_load[] = { +"22 22 5 1", +". c None", +"# c #000000", +"c c #838100", +"a c #ffff00", +"b c #ffffff", +"......................", +"......................", +"......................", +"............####....#.", +"...........#....##.##.", +"..................###.", +".................####.", +".####...........#####.", +"#abab##########.......", +"#babababababab#.......", +"#ababababababa#.......", +"#babababababab#.......", +"#ababab###############", +"#babab##cccccccccccc##", +"#abab##cccccccccccc##.", +"#bab##cccccccccccc##..", +"#ab##cccccccccccc##...", +"#b##cccccccccccc##....", +"###cccccccccccc##.....", +"##cccccccccccc##......", +"###############.......", +"......................"}; + +static const char *xpm_save[] = { +"22 22 5 1", +". c None", +"# c #000000", +"a c #838100", +"b c #c5c2c5", +"c c #cdb6d5", +"......................", +".####################.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbcbb####.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aaa############aaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaa#############aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +"..##################..", +"......................"}; + +static const char *xpm_back[] = { +"22 22 3 1", +". c None", +"# c #000083", +"a c #838183", +"......................", +"......................", +"......................", +"......................", +"......................", +"...........######a....", +"..#......##########...", +"..##...####......##a..", +"..###.###.........##..", +"..######..........##..", +"..#####...........##..", +"..######..........##..", +"..#######.........##..", +"..########.......##a..", +"...............a###...", +"...............###....", +"......................", +"......................", +"......................", +"......................", +"......................", +"......................"}; + +static const char *xpm_tree_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......................", +"......................"}; + +static const char *xpm_single_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"......................", +"......................"}; + +static const char *xpm_split_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......................", +"......................"}; + +static const char *xpm_symbol_no[] = { +"12 12 2 1", +"  c white", +". c black", +"            ", +" .......... ", +" .        . ", +" .        . ", +" .        . ", +" .        . ", +" .        . ", +" .        . ", +" .        . ", +" .        . ", +" .......... ", +"            "}; + +static const char *xpm_symbol_mod[] = { +"12 12 2 1", +"  c white", +". c black", +"            ", +" .......... ", +" .        . ", +" .        . ", +" .   ..   . ", +" .  ....  . ", +" .  ....  . ", +" .   ..   . ", +" .        . ", +" .        . ", +" .......... ", +"            "}; + +static const char *xpm_symbol_yes[] = { +"12 12 2 1", +"  c white", +". c black", +"            ", +" .......... ", +" .        . ", +" .        . ", +" .      . . ", +" .     .. . ", +" . .  ..  . ", +" . ....   . ", +" .  ..    . ", +" .        . ", +" .......... ", +"            "}; + +static const char *xpm_choice_no[] = { +"12 12 2 1", +"  c white", +". c black", +"            ", +"    ....    ", +"  ..    ..  ", +"  .      .  ", +" .        . ", +" .        . ", +" .        . ", +" .        . ", +"  .      .  ", +"  ..    ..  ", +"    ....    ", +"            "}; + +static const char *xpm_choice_yes[] = { +"12 12 2 1", +"  c white", +". c black", +"            ", +"    ....    ", +"  ..    ..  ", +"  .      .  ", +" .   ..   . ", +" .  ....  . ", +" .  ....  . ", +" .   ..   . ", +"  .      .  ", +"  ..    ..  ", +"    ....    ", +"            "}; + +static const char *xpm_menu[] = { +"12 12 2 1", +"  c white", +". c black", +"            ", +" .......... ", +" .        . ", +" . ..     . ", +" . ....   . ", +" . ...... . ", +" . ...... . ", +" . ....   . ", +" . ..     . ", +" .        . ", +" .......... ", +"            "}; + +static const char *xpm_menu_inv[] = { +"12 12 2 1", +"  c white", +". c black", +"            ", +" .......... ", +" .......... ", +" ..  ...... ", +" ..    .... ", +" ..      .. ", +" ..      .. ", +" ..    .... ", +" ..  ...... ", +" .......... ", +" .......... ", +"            "}; + +static const char *xpm_menuback[] = { +"12 12 2 1", +"  c white", +". c black", +"            ", +" .......... ", +" .        . ", +" .     .. . ", +" .   .... . ", +" . ...... . ", +" . ...... . ", +" .   .... . ", +" .     .. . ", +" .        . ", +" .......... ", +"            "}; + +static const char *xpm_void[] = { +"12 12 2 1", +"  c white", +". c black", +"            ", +"            ", +"            ", +"            ", +"            ", +"            ", +"            ", +"            ", +"            ", +"            ", +"            ", +"            "}; diff --git a/scripts/kconfig/kconfig_load.c b/scripts/kconfig/kconfig_load.c new file mode 100644 index 000000000000..dbdcaad82325 --- /dev/null +++ b/scripts/kconfig/kconfig_load.c @@ -0,0 +1,35 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +#include "lkc.h" + +#define P(name,type,arg)	type (*name ## _p) arg +#include "lkc_proto.h" +#undef P + +void kconfig_load(void) +{ +	void *handle; +	char *error; + +	handle = dlopen("./libkconfig.so", RTLD_LAZY); +	if (!handle) { +		handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY); +		if (!handle) { +			fprintf(stderr, "%s\n", dlerror()); +			exit(1); +		} +	} + +#define P(name,type,arg)			\ +{						\ +	name ## _p = dlsym(handle, #name);	\ +        if ((error = dlerror()))  {		\ +                fprintf(stderr, "%s\n", error);	\ +		exit(1);			\ +	}					\ +} +#include "lkc_proto.h" +#undef P +} diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped new file mode 100644 index 000000000000..22dda11f758b --- /dev/null +++ b/scripts/kconfig/lex.zconf.c_shipped @@ -0,0 +1,3688 @@ + +#line 3 "lex.zconf.c" + +#define  YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 31 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with  platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t;  +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN               (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN              (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN              (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX               (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX              (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX              (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX              (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX             (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX             (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else	/* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_CONST + +#endif	/* __STDC__ */ +#endif	/* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index.  If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition.  This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state.  The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE zconfrestart(zconfin  ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int zconfleng; + +extern FILE *zconfin, *zconfout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +    #define YY_LESS_LINENO(n) +     +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ +	do \ +		{ \ +		/* Undo effects of setting up zconftext. */ \ +        int yyless_macro_arg = (n); \ +        YY_LESS_LINENO(yyless_macro_arg);\ +		*yy_cp = (yy_hold_char); \ +		YY_RESTORE_YY_MORE_OFFSET \ +		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ +		YY_DO_BEFORE_ACTION; /* set up zconftext again */ \ +		} \ +	while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr)  ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state +	{ +	FILE *yy_input_file; + +	char *yy_ch_buf;		/* input buffer */ +	char *yy_buf_pos;		/* current position in input buffer */ + +	/* Size of input buffer in bytes, not including room for EOB +	 * characters. +	 */ +	yy_size_t yy_buf_size; + +	/* Number of characters read into yy_ch_buf, not including EOB +	 * characters. +	 */ +	int yy_n_chars; + +	/* Whether we "own" the buffer - i.e., we know we created it, +	 * and can realloc() it to grow it, and should free() it to +	 * delete it. +	 */ +	int yy_is_our_buffer; + +	/* Whether this is an "interactive" input source; if so, and +	 * if we're using stdio for input, then we want to use getc() +	 * instead of fread(), to make sure we stop fetching input after +	 * each newline. +	 */ +	int yy_is_interactive; + +	/* Whether we're considered to be at the beginning of a line. +	 * If so, '^' rules will be active on the next match, otherwise +	 * not. +	 */ +	int yy_at_bol; + +    int yy_bs_lineno; /**< The line count. */ +    int yy_bs_column; /**< The column count. */ +     +	/* Whether to try to fill the input buffer when we reach the +	 * end of it. +	 */ +	int yy_fill_buffer; + +	int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 +	/* When an EOF's been seen but there's still some text to process +	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we +	 * shouldn't try reading from the input source any more.  We might +	 * still have a bunch of tokens to match, though, because of +	 * possible backing-up. +	 * +	 * When we actually see the EOF, we change the status to "new" +	 * (via zconfrestart()), so that the user can continue scanning by +	 * just pointing zconfin at a new input file. +	 */ +#define YY_BUFFER_EOF_PENDING 2 + +	}; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ +                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ +                          : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when zconftext is formed. */ +static char yy_hold_char; +static int yy_n_chars;		/* number of characters read into yy_ch_buf */ +int zconfleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1;		/* whether we need to initialize */ +static int yy_start = 0;	/* start state number */ + +/* Flag which is used to allow zconfwrap()'s to do buffer switches + * instead of setting up a fresh zconfin.  A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void zconfrestart (FILE *input_file  ); +void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer  ); +YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size  ); +void zconf_delete_buffer (YY_BUFFER_STATE b  ); +void zconf_flush_buffer (YY_BUFFER_STATE b  ); +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer  ); +void zconfpop_buffer_state (void ); + +static void zconfensure_buffer_stack (void ); +static void zconf_load_buffer_state (void ); +static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file  ); + +#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size  ); +YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str  ); +YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len  ); + +void *zconfalloc (yy_size_t  ); +void *zconfrealloc (void *,yy_size_t  ); +void zconffree (void *  ); + +#define yy_new_buffer zconf_create_buffer + +#define yy_set_interactive(is_interactive) \ +	{ \ +	if ( ! YY_CURRENT_BUFFER ){ \ +        zconfensure_buffer_stack (); \ +		YY_CURRENT_BUFFER_LVALUE =    \ +            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ +	} \ +	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ +	} + +#define yy_set_bol(at_bol) \ +	{ \ +	if ( ! YY_CURRENT_BUFFER ){\ +        zconfensure_buffer_stack (); \ +		YY_CURRENT_BUFFER_LVALUE =    \ +            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ +	} \ +	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ +	} + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define zconfwrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0; + +typedef int yy_state_type; + +extern int zconflineno; + +int zconflineno = 1; + +extern char *zconftext; +#define yytext_ptr zconftext +static yyconst flex_int16_t yy_nxt[][38] = +    { +    { +        0,    0,    0,    0,    0,    0,    0,    0,    0,    0, +        0,    0,    0,    0,    0,    0,    0,    0,    0,    0, +        0,    0,    0,    0,    0,    0,    0,    0,    0,    0, +        0,    0,    0,    0,    0,    0,    0,    0 +    }, + +    { +       11,   12,   13,   14,   12,   12,   15,   12,   12,   12, +       12,   12,   12,   12,   12,   12,   12,   12,   12,   12, +       12,   12,   12,   12,   12,   12,   12,   12,   12,   12, +       12,   12,   12,   12,   12,   12,   12,   12 +    }, + +    { +       11,   12,   13,   14,   12,   12,   15,   12,   12,   12, +       12,   12,   12,   12,   12,   12,   12,   12,   12,   12, + +       12,   12,   12,   12,   12,   12,   12,   12,   12,   12, +       12,   12,   12,   12,   12,   12,   12,   12 +    }, + +    { +       11,   16,   16,   17,   16,   16,   16,   16,   16,   16, +       16,   16,   16,   18,   16,   16,   18,   18,   19,   20, +       21,   22,   18,   18,   23,   24,   18,   25,   18,   26, +       27,   18,   28,   29,   30,   18,   18,   16 +    }, + +    { +       11,   16,   16,   17,   16,   16,   16,   16,   16,   16, +       16,   16,   16,   18,   16,   16,   18,   18,   19,   20, +       21,   22,   18,   18,   23,   24,   18,   25,   18,   26, +       27,   18,   28,   29,   30,   18,   18,   16 + +    }, + +    { +       11,   31,   32,   33,   31,   31,   31,   31,   31,   31, +       31,   31,   31,   31,   31,   31,   31,   31,   31,   31, +       31,   31,   31,   31,   31,   31,   31,   31,   31,   31, +       31,   31,   31,   31,   31,   31,   31,   31 +    }, + +    { +       11,   31,   32,   33,   31,   31,   31,   31,   31,   31, +       31,   31,   31,   31,   31,   31,   31,   31,   31,   31, +       31,   31,   31,   31,   31,   31,   31,   31,   31,   31, +       31,   31,   31,   31,   31,   31,   31,   31 +    }, + +    { +       11,   34,   34,   35,   34,   36,   34,   34,   36,   34, +       34,   34,   34,   34,   34,   37,   34,   34,   34,   34, + +       34,   34,   34,   34,   34,   34,   34,   34,   34,   34, +       34,   34,   34,   34,   34,   34,   34,   34 +    }, + +    { +       11,   34,   34,   35,   34,   36,   34,   34,   36,   34, +       34,   34,   34,   34,   34,   37,   34,   34,   34,   34, +       34,   34,   34,   34,   34,   34,   34,   34,   34,   34, +       34,   34,   34,   34,   34,   34,   34,   34 +    }, + +    { +       11,   38,   38,   39,   40,   41,   42,   43,   41,   44, +       45,   46,   47,   47,   48,   49,   47,   47,   47,   47, +       47,   47,   47,   47,   47,   50,   47,   47,   47,   51, +       47,   47,   47,   47,   47,   47,   47,   52 + +    }, + +    { +       11,   38,   38,   39,   40,   41,   42,   43,   41,   44, +       45,   46,   47,   47,   48,   49,   47,   47,   47,   47, +       47,   47,   47,   47,   47,   50,   47,   47,   47,   51, +       47,   47,   47,   47,   47,   47,   47,   52 +    }, + +    { +      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11, +      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11, +      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11, +      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11 +    }, + +    { +       11,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12, +      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12, + +      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12, +      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12 +    }, + +    { +       11,  -13,   53,   54,  -13,  -13,   55,  -13,  -13,  -13, +      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13, +      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13, +      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13 +    }, + +    { +       11,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14, +      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14, +      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14, +      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14 + +    }, + +    { +       11,   56,   56,   57,   56,   56,   56,   56,   56,   56, +       56,   56,   56,   56,   56,   56,   56,   56,   56,   56, +       56,   56,   56,   56,   56,   56,   56,   56,   56,   56, +       56,   56,   56,   56,   56,   56,   56,   56 +    }, + +    { +       11,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16, +      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16, +      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16, +      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16 +    }, + +    { +       11,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17, +      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17, + +      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17, +      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17 +    }, + +    { +       11,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18, +      -18,  -18,  -18,   58,  -18,  -18,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -18 +    }, + +    { +       11,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19, +      -19,  -19,  -19,   58,  -19,  -19,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   59, +       58,   58,   58,   58,   58,   58,   58,  -19 + +    }, + +    { +       11,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20, +      -20,  -20,  -20,   58,  -20,  -20,   58,   58,   58,   58, +       58,   58,   58,   58,   60,   58,   58,   58,   58,   61, +       58,   58,   58,   58,   58,   58,   58,  -20 +    }, + +    { +       11,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21, +      -21,  -21,  -21,   58,  -21,  -21,   58,   58,   58,   58, +       58,   62,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -21 +    }, + +    { +       11,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22, +      -22,  -22,  -22,   58,  -22,  -22,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   63,   58, +       58,   58,   58,   58,   58,   58,   58,  -22 +    }, + +    { +       11,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23, +      -23,  -23,  -23,   58,  -23,  -23,   58,   58,   58,   58, +       58,   64,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -23 +    }, + +    { +       11,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24, +      -24,  -24,  -24,   58,  -24,  -24,   58,   58,   58,   58, +       58,   58,   65,   58,   58,   58,   58,   58,   66,   58, +       58,   58,   58,   58,   58,   58,   58,  -24 + +    }, + +    { +       11,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25, +      -25,  -25,  -25,   58,  -25,  -25,   58,   67,   58,   58, +       58,   68,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -25 +    }, + +    { +       11,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26, +      -26,  -26,  -26,   58,  -26,  -26,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       69,   58,   58,   58,   58,   58,   58,  -26 +    }, + +    { +       11,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27, +      -27,  -27,  -27,   58,  -27,  -27,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   70,   58,   58,   58,   58,  -27 +    }, + +    { +       11,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28, +      -28,  -28,  -28,   58,  -28,  -28,   58,   71,   58,   58, +       58,   72,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -28 +    }, + +    { +       11,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29, +      -29,  -29,  -29,   58,  -29,  -29,   58,   58,   58,   58, +       58,   73,   58,   58,   58,   58,   58,   58,   58,   74, +       58,   58,   58,   58,   75,   58,   58,  -29 + +    }, + +    { +       11,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30, +      -30,  -30,  -30,   58,  -30,  -30,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   76,   58,   58,   58,   58,  -30 +    }, + +    { +       11,   77,   77,  -31,   77,   77,   77,   77,   77,   77, +       77,   77,   77,   77,   77,   77,   77,   77,   77,   77, +       77,   77,   77,   77,   77,   77,   77,   77,   77,   77, +       77,   77,   77,   77,   77,   77,   77,   77 +    }, + +    { +       11,  -32,   78,   79,  -32,  -32,  -32,  -32,  -32,  -32, +      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32, + +      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32, +      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32 +    }, + +    { +       11,   80,  -33,  -33,   80,   80,   80,   80,   80,   80, +       80,   80,   80,   80,   80,   80,   80,   80,   80,   80, +       80,   80,   80,   80,   80,   80,   80,   80,   80,   80, +       80,   80,   80,   80,   80,   80,   80,   80 +    }, + +    { +       11,   81,   81,   82,   81,  -34,   81,   81,  -34,   81, +       81,   81,   81,   81,   81,  -34,   81,   81,   81,   81, +       81,   81,   81,   81,   81,   81,   81,   81,   81,   81, +       81,   81,   81,   81,   81,   81,   81,   81 + +    }, + +    { +       11,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35, +      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35, +      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35, +      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35 +    }, + +    { +       11,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36, +      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36, +      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36, +      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36 +    }, + +    { +       11,   83,   83,   84,   83,   83,   83,   83,   83,   83, +       83,   83,   83,   83,   83,   83,   83,   83,   83,   83, + +       83,   83,   83,   83,   83,   83,   83,   83,   83,   83, +       83,   83,   83,   83,   83,   83,   83,   83 +    }, + +    { +       11,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38, +      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38, +      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38, +      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38 +    }, + +    { +       11,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39, +      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39, +      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39, +      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39 + +    }, + +    { +       11,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40, +      -40,  -40,  -40,  -40,   85,  -40,  -40,  -40,  -40,  -40, +      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40, +      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40 +    }, + +    { +       11,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41, +      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41, +      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41, +      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41 +    }, + +    { +       11,   86,   86,  -42,   86,   86,   86,   86,   86,   86, +       86,   86,   86,   86,   86,   86,   86,   86,   86,   86, + +       86,   86,   86,   86,   86,   86,   86,   86,   86,   86, +       86,   86,   86,   86,   86,   86,   86,   86 +    }, + +    { +       11,  -43,  -43,  -43,  -43,  -43,  -43,   87,  -43,  -43, +      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43, +      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43, +      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43 +    }, + +    { +       11,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44, +      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44, +      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44, +      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44 + +    }, + +    { +       11,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45, +      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45, +      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45, +      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45 +    }, + +    { +       11,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46, +      -46,   88,   89,   89,  -46,  -46,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,  -46 +    }, + +    { +       11,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47, +      -47,   89,   89,   89,  -47,  -47,   89,   89,   89,   89, + +       89,   89,   89,   89,   89,   89,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,  -47 +    }, + +    { +       11,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48, +      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48, +      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48, +      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48 +    }, + +    { +       11,  -49,  -49,   90,  -49,  -49,  -49,  -49,  -49,  -49, +      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49, +      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49, +      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49 + +    }, + +    { +       11,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50, +      -50,   89,   89,   89,  -50,  -50,   89,   89,   89,   89, +       89,   89,   91,   89,   89,   89,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,  -50 +    }, + +    { +       11,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51, +      -51,   89,   89,   89,  -51,  -51,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,   89,   92,   89, +       89,   89,   89,   89,   89,   89,   89,  -51 +    }, + +    { +       11,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52, +      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52, + +      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52, +      -52,  -52,  -52,  -52,  -52,  -52,  -52,   93 +    }, + +    { +       11,  -53,   53,   54,  -53,  -53,   55,  -53,  -53,  -53, +      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53, +      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53, +      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53 +    }, + +    { +       11,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54, +      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54, +      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54, +      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54 + +    }, + +    { +       11,   56,   56,   57,   56,   56,   56,   56,   56,   56, +       56,   56,   56,   56,   56,   56,   56,   56,   56,   56, +       56,   56,   56,   56,   56,   56,   56,   56,   56,   56, +       56,   56,   56,   56,   56,   56,   56,   56 +    }, + +    { +       11,   56,   56,   57,   56,   56,   56,   56,   56,   56, +       56,   56,   56,   56,   56,   56,   56,   56,   56,   56, +       56,   56,   56,   56,   56,   56,   56,   56,   56,   56, +       56,   56,   56,   56,   56,   56,   56,   56 +    }, + +    { +       11,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57, +      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57, + +      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57, +      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57 +    }, + +    { +       11,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58, +      -58,  -58,  -58,   58,  -58,  -58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -58 +    }, + +    { +       11,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59, +      -59,  -59,  -59,   58,  -59,  -59,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   94, +       58,   58,   58,   58,   58,   58,   58,  -59 + +    }, + +    { +       11,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60, +      -60,  -60,  -60,   58,  -60,  -60,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   95, +       58,   58,   58,   58,   58,   58,   58,  -60 +    }, + +    { +       11,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61, +      -61,  -61,  -61,   58,  -61,  -61,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   96,   97,   58, +       58,   58,   58,   58,   58,   58,   58,  -61 +    }, + +    { +       11,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62, +      -62,  -62,  -62,   58,  -62,  -62,   58,   58,   58,   58, + +       58,   58,   98,   58,   58,   58,   58,   58,   58,   58, +       99,   58,   58,   58,   58,   58,   58,  -62 +    }, + +    { +       11,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63, +      -63,  -63,  -63,   58,  -63,  -63,   58,  100,   58,   58, +      101,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -63 +    }, + +    { +       11,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64, +      -64,  -64,  -64,   58,  -64,  -64,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,  102,   58,   58,   58, +       58,   58,   58,   58,   58,   58,  103,  -64 + +    }, + +    { +       11,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65, +      -65,  -65,  -65,   58,  -65,  -65,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -65 +    }, + +    { +       11,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66, +      -66,  -66,  -66,   58,  -66,  -66,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  104,   58,   58,  -66 +    }, + +    { +       11,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67, +      -67,  -67,  -67,   58,  -67,  -67,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,  105,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -67 +    }, + +    { +       11,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68, +      -68,  -68,  -68,   58,  -68,  -68,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,  106,   58, +       58,   58,   58,   58,   58,   58,   58,  -68 +    }, + +    { +       11,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69, +      -69,  -69,  -69,   58,  -69,  -69,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  107,   58,   58,  -69 + +    }, + +    { +       11,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70, +      -70,  -70,  -70,   58,  -70,  -70,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,  108, +       58,   58,   58,   58,   58,   58,   58,  -70 +    }, + +    { +       11,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71, +      -71,  -71,  -71,   58,  -71,  -71,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,  109,   58, +       58,   58,   58,   58,   58,   58,   58,  -71 +    }, + +    { +       11,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72, +      -72,  -72,  -72,   58,  -72,  -72,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,  110,   58,   58,   58,   58,   58,  -72 +    }, + +    { +       11,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73, +      -73,  -73,  -73,   58,  -73,  -73,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,  111,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -73 +    }, + +    { +       11,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74, +      -74,  -74,  -74,   58,  -74,  -74,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  112,   58,  -74 + +    }, + +    { +       11,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75, +      -75,  -75,  -75,   58,  -75,  -75,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,  113,   58,   58,   58,   58,  -75 +    }, + +    { +       11,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76, +      -76,  -76,  -76,   58,  -76,  -76,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  114,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -76 +    }, + +    { +       11,   77,   77,  -77,   77,   77,   77,   77,   77,   77, +       77,   77,   77,   77,   77,   77,   77,   77,   77,   77, + +       77,   77,   77,   77,   77,   77,   77,   77,   77,   77, +       77,   77,   77,   77,   77,   77,   77,   77 +    }, + +    { +       11,  -78,   78,   79,  -78,  -78,  -78,  -78,  -78,  -78, +      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78, +      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78, +      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78 +    }, + +    { +       11,   80,  -79,  -79,   80,   80,   80,   80,   80,   80, +       80,   80,   80,   80,   80,   80,   80,   80,   80,   80, +       80,   80,   80,   80,   80,   80,   80,   80,   80,   80, +       80,   80,   80,   80,   80,   80,   80,   80 + +    }, + +    { +       11,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80, +      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80, +      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80, +      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80 +    }, + +    { +       11,   81,   81,   82,   81,  -81,   81,   81,  -81,   81, +       81,   81,   81,   81,   81,  -81,   81,   81,   81,   81, +       81,   81,   81,   81,   81,   81,   81,   81,   81,   81, +       81,   81,   81,   81,   81,   81,   81,   81 +    }, + +    { +       11,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82, +      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82, + +      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82, +      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82 +    }, + +    { +       11,  -83,  -83,   84,  -83,  -83,  -83,  -83,  -83,  -83, +      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83, +      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83, +      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83 +    }, + +    { +       11,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84, +      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84, +      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84, +      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84 + +    }, + +    { +       11,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85, +      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85, +      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85, +      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85 +    }, + +    { +       11,   86,   86,  -86,   86,   86,   86,   86,   86,   86, +       86,   86,   86,   86,   86,   86,   86,   86,   86,   86, +       86,   86,   86,   86,   86,   86,   86,   86,   86,   86, +       86,   86,   86,   86,   86,   86,   86,   86 +    }, + +    { +       11,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87, +      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87, + +      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87, +      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87 +    }, + +    { +       11,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88, +      -88,  115,   89,   89,  -88,  -88,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,  -88 +    }, + +    { +       11,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89, +      -89,   89,   89,   89,  -89,  -89,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,  -89 + +    }, + +    { +       11,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90, +      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90, +      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90, +      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90 +    }, + +    { +       11,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91, +      -91,   89,   89,   89,  -91,  -91,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,  -91 +    }, + +    { +       11,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92, +      -92,   89,   89,   89,  -92,  -92,   89,   89,   89,   89, + +       89,   89,   89,   89,   89,   89,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,  -92 +    }, + +    { +       11,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93, +      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93, +      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93, +      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93 +    }, + +    { +       11,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94, +      -94,  -94,  -94,   58,  -94,  -94,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,  116,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -94 + +    }, + +    { +       11,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95, +      -95,  -95,  -95,   58,  -95,  -95,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  117,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -95 +    }, + +    { +       11,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96, +      -96,  -96,  -96,   58,  -96,  -96,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  118,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -96 +    }, + +    { +       11,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97, +      -97,  -97,  -97,   58,  -97,  -97,   58,   58,   58,   58, + +       58,   58,  119,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -97 +    }, + +    { +       11,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98, +      -98,  -98,  -98,   58,  -98,  -98,  120,  121,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -98 +    }, + +    { +       11,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99, +      -99,  -99,  -99,   58,  -99,  -99,   58,   58,   58,   58, +       58,  122,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  -99 + +    }, + +    { +       11, -100, -100, -100, -100, -100, -100, -100, -100, -100, +     -100, -100, -100,   58, -100, -100,   58,   58,  123,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -100 +    }, + +    { +       11, -101, -101, -101, -101, -101, -101, -101, -101, -101, +     -101, -101, -101,   58, -101, -101,   58,   58,   58,  124, +       58,   58,   58,   58,   58,  125,   58,  126,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -101 +    }, + +    { +       11, -102, -102, -102, -102, -102, -102, -102, -102, -102, +     -102, -102, -102,   58, -102, -102,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +      127,   58,   58,   58,   58,   58,   58, -102 +    }, + +    { +       11, -103, -103, -103, -103, -103, -103, -103, -103, -103, +     -103, -103, -103,   58, -103, -103,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -103 +    }, + +    { +       11, -104, -104, -104, -104, -104, -104, -104, -104, -104, +     -104, -104, -104,   58, -104, -104,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -104 + +    }, + +    { +       11, -105, -105, -105, -105, -105, -105, -105, -105, -105, +     -105, -105, -105,   58, -105, -105,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,  128,   58, +       58,   58,   58,   58,   58,   58,   58, -105 +    }, + +    { +       11, -106, -106, -106, -106, -106, -106, -106, -106, -106, +     -106, -106, -106,   58, -106, -106,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  129,   58, -106 +    }, + +    { +       11, -107, -107, -107, -107, -107, -107, -107, -107, -107, +     -107, -107, -107,   58, -107, -107,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,  130,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -107 +    }, + +    { +       11, -108, -108, -108, -108, -108, -108, -108, -108, -108, +     -108, -108, -108,   58, -108, -108,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  131,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -108 +    }, + +    { +       11, -109, -109, -109, -109, -109, -109, -109, -109, -109, +     -109, -109, -109,   58, -109, -109,   58,   58,   58,   58, +       58,   58,   58,  132,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -109 + +    }, + +    { +       11, -110, -110, -110, -110, -110, -110, -110, -110, -110, +     -110, -110, -110,   58, -110, -110,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  133,   58, -110 +    }, + +    { +       11, -111, -111, -111, -111, -111, -111, -111, -111, -111, +     -111, -111, -111,   58, -111, -111,   58,   58,   58,   58, +       58,  134,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -111 +    }, + +    { +       11, -112, -112, -112, -112, -112, -112, -112, -112, -112, +     -112, -112, -112,   58, -112, -112,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,  135,   58,   58,   58,   58, -112 +    }, + +    { +       11, -113, -113, -113, -113, -113, -113, -113, -113, -113, +     -113, -113, -113,   58, -113, -113,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  136,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -113 +    }, + +    { +       11, -114, -114, -114, -114, -114, -114, -114, -114, -114, +     -114, -114, -114,   58, -114, -114,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,  137,   58,   58,   58, -114 + +    }, + +    { +       11, -115, -115, -115, -115, -115, -115, -115, -115, -115, +     -115,   89,   89,   89, -115, -115,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89,   89,   89,   89, +       89,   89,   89,   89,   89,   89,   89, -115 +    }, + +    { +       11, -116, -116, -116, -116, -116, -116, -116, -116, -116, +     -116, -116, -116,   58, -116, -116,   58,   58,   58,   58, +       58,  138,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -116 +    }, + +    { +       11, -117, -117, -117, -117, -117, -117, -117, -117, -117, +     -117, -117, -117,   58, -117, -117,   58,   58,   58,  139, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -117 +    }, + +    { +       11, -118, -118, -118, -118, -118, -118, -118, -118, -118, +     -118, -118, -118,   58, -118, -118,   58,   58,   58,   58, +       58,  140,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -118 +    }, + +    { +       11, -119, -119, -119, -119, -119, -119, -119, -119, -119, +     -119, -119, -119,   58, -119, -119,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  141,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -119 + +    }, + +    { +       11, -120, -120, -120, -120, -120, -120, -120, -120, -120, +     -120, -120, -120,   58, -120, -120,   58,   58,  142,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  143,   58,   58, -120 +    }, + +    { +       11, -121, -121, -121, -121, -121, -121, -121, -121, -121, +     -121, -121, -121,   58, -121, -121,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  144,   58, -121 +    }, + +    { +       11, -122, -122, -122, -122, -122, -122, -122, -122, -122, +     -122, -122, -122,   58, -122, -122,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,  145,   58, +       58,   58,   58,   58,   58,   58,   58, -122 +    }, + +    { +       11, -123, -123, -123, -123, -123, -123, -123, -123, -123, +     -123, -123, -123,   58, -123, -123,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,  146,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -123 +    }, + +    { +       11, -124, -124, -124, -124, -124, -124, -124, -124, -124, +     -124, -124, -124,   58, -124, -124,   58,   58,   58,   58, +       58,   58,   58,   58,  147,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -124 + +    }, + +    { +       11, -125, -125, -125, -125, -125, -125, -125, -125, -125, +     -125, -125, -125,   58, -125, -125,   58,   58,   58,   58, +       58,   58,  148,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -125 +    }, + +    { +       11, -126, -126, -126, -126, -126, -126, -126, -126, -126, +     -126, -126, -126,   58, -126, -126,   58,   58,   58,   58, +       58,  149,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -126 +    }, + +    { +       11, -127, -127, -127, -127, -127, -127, -127, -127, -127, +     -127, -127, -127,   58, -127, -127,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -127 +    }, + +    { +       11, -128, -128, -128, -128, -128, -128, -128, -128, -128, +     -128, -128, -128,   58, -128, -128,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,  150,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -128 +    }, + +    { +       11, -129, -129, -129, -129, -129, -129, -129, -129, -129, +     -129, -129, -129,   58, -129, -129,   58,   58,   58,  151, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -129 + +    }, + +    { +       11, -130, -130, -130, -130, -130, -130, -130, -130, -130, +     -130, -130, -130,   58, -130, -130,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,  152, +       58,   58,   58,   58,   58,   58,   58, -130 +    }, + +    { +       11, -131, -131, -131, -131, -131, -131, -131, -131, -131, +     -131, -131, -131,   58, -131, -131,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +      153,   58,   58,   58,   58,   58,   58, -131 +    }, + +    { +       11, -132, -132, -132, -132, -132, -132, -132, -132, -132, +     -132, -132, -132,   58, -132, -132,   58,   58,   58,   58, + +       58,  154,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -132 +    }, + +    { +       11, -133, -133, -133, -133, -133, -133, -133, -133, -133, +     -133, -133, -133,   58, -133, -133,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  155,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -133 +    }, + +    { +       11, -134, -134, -134, -134, -134, -134, -134, -134, -134, +     -134, -134, -134,   58, -134, -134,   58,   58,   58,  156, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -134 + +    }, + +    { +       11, -135, -135, -135, -135, -135, -135, -135, -135, -135, +     -135, -135, -135,   58, -135, -135,   58,   58,   58,  157, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -135 +    }, + +    { +       11, -136, -136, -136, -136, -136, -136, -136, -136, -136, +     -136, -136, -136,   58, -136, -136,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,  158,   58, +       58,   58,   58,   58,   58,   58,   58, -136 +    }, + +    { +       11, -137, -137, -137, -137, -137, -137, -137, -137, -137, +     -137, -137, -137,   58, -137, -137,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  159,   58,   58, -137 +    }, + +    { +       11, -138, -138, -138, -138, -138, -138, -138, -138, -138, +     -138, -138, -138,   58, -138, -138,   58,  160,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -138 +    }, + +    { +       11, -139, -139, -139, -139, -139, -139, -139, -139, -139, +     -139, -139, -139,   58, -139, -139,   58,   58,   58,   58, +       58,  161,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -139 + +    }, + +    { +       11, -140, -140, -140, -140, -140, -140, -140, -140, -140, +     -140, -140, -140,   58, -140, -140,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,  162,   58, +       58,   58,   58,   58,   58,   58,   58, -140 +    }, + +    { +       11, -141, -141, -141, -141, -141, -141, -141, -141, -141, +     -141, -141, -141,   58, -141, -141,   58,   58,   58,   58, +       58,   58,   58,  163,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -141 +    }, + +    { +       11, -142, -142, -142, -142, -142, -142, -142, -142, -142, +     -142, -142, -142,   58, -142, -142,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,  164, +       58,   58,   58,   58,   58,   58,   58, -142 +    }, + +    { +       11, -143, -143, -143, -143, -143, -143, -143, -143, -143, +     -143, -143, -143,   58, -143, -143,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,  165,   58,   58,   58,   58, -143 +    }, + +    { +       11, -144, -144, -144, -144, -144, -144, -144, -144, -144, +     -144, -144, -144,   58, -144, -144,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,  166,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -144 + +    }, + +    { +       11, -145, -145, -145, -145, -145, -145, -145, -145, -145, +     -145, -145, -145,   58, -145, -145,   58,   58,   58,   58, +      167,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -145 +    }, + +    { +       11, -146, -146, -146, -146, -146, -146, -146, -146, -146, +     -146, -146, -146,   58, -146, -146,   58,   58,   58,   58, +       58,  168,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -146 +    }, + +    { +       11, -147, -147, -147, -147, -147, -147, -147, -147, -147, +     -147, -147, -147,   58, -147, -147,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,  169, +       58,   58,   58,   58,   58,   58,   58, -147 +    }, + +    { +       11, -148, -148, -148, -148, -148, -148, -148, -148, -148, +     -148, -148, -148,   58, -148, -148,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -148 +    }, + +    { +       11, -149, -149, -149, -149, -149, -149, -149, -149, -149, +     -149, -149, -149,   58, -149, -149,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,  170,   58, +       58,   58,   58,   58,   58,   58,   58, -149 + +    }, + +    { +       11, -150, -150, -150, -150, -150, -150, -150, -150, -150, +     -150, -150, -150,   58, -150, -150,   58,   58,   58,   58, +       58,  171,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -150 +    }, + +    { +       11, -151, -151, -151, -151, -151, -151, -151, -151, -151, +     -151, -151, -151,   58, -151, -151,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,  172, +       58,   58,   58,   58,   58,   58,   58, -151 +    }, + +    { +       11, -152, -152, -152, -152, -152, -152, -152, -152, -152, +     -152, -152, -152,   58, -152, -152,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,  173,   58, +       58,   58,   58,   58,   58,   58,   58, -152 +    }, + +    { +       11, -153, -153, -153, -153, -153, -153, -153, -153, -153, +     -153, -153, -153,   58, -153, -153,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  174,   58,   58, -153 +    }, + +    { +       11, -154, -154, -154, -154, -154, -154, -154, -154, -154, +     -154, -154, -154,   58, -154, -154,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -154 + +    }, + +    { +       11, -155, -155, -155, -155, -155, -155, -155, -155, -155, +     -155, -155, -155,   58, -155, -155,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,  175,   58,   58,   58,   58, -155 +    }, + +    { +       11, -156, -156, -156, -156, -156, -156, -156, -156, -156, +     -156, -156, -156,   58, -156, -156,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  176,   58,   58, -156 +    }, + +    { +       11, -157, -157, -157, -157, -157, -157, -157, -157, -157, +     -157, -157, -157,   58, -157, -157,   58,   58,   58,   58, + +       58,  177,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -157 +    }, + +    { +       11, -158, -158, -158, -158, -158, -158, -158, -158, -158, +     -158, -158, -158,   58, -158, -158,   58,   58,   58,   58, +       58,   58,   58,  178,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -158 +    }, + +    { +       11, -159, -159, -159, -159, -159, -159, -159, -159, -159, +     -159, -159, -159,   58, -159, -159,   58,  179,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -159 + +    }, + +    { +       11, -160, -160, -160, -160, -160, -160, -160, -160, -160, +     -160, -160, -160,   58, -160, -160,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,  180,   58, +       58,   58,   58,   58,   58,   58,   58, -160 +    }, + +    { +       11, -161, -161, -161, -161, -161, -161, -161, -161, -161, +     -161, -161, -161,   58, -161, -161,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -161 +    }, + +    { +       11, -162, -162, -162, -162, -162, -162, -162, -162, -162, +     -162, -162, -162,   58, -162, -162,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  181,   58,   58, -162 +    }, + +    { +       11, -163, -163, -163, -163, -163, -163, -163, -163, -163, +     -163, -163, -163,   58, -163, -163,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -163 +    }, + +    { +       11, -164, -164, -164, -164, -164, -164, -164, -164, -164, +     -164, -164, -164,   58, -164, -164,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,  182, +       58,   58,   58,   58,   58,   58,   58, -164 + +    }, + +    { +       11, -165, -165, -165, -165, -165, -165, -165, -165, -165, +     -165, -165, -165,   58, -165, -165,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  183,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -165 +    }, + +    { +       11, -166, -166, -166, -166, -166, -166, -166, -166, -166, +     -166, -166, -166,   58, -166, -166,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  184,   58,   58, -166 +    }, + +    { +       11, -167, -167, -167, -167, -167, -167, -167, -167, -167, +     -167, -167, -167,   58, -167, -167,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,  185,   58,   58,   58, -167 +    }, + +    { +       11, -168, -168, -168, -168, -168, -168, -168, -168, -168, +     -168, -168, -168,   58, -168, -168,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -168 +    }, + +    { +       11, -169, -169, -169, -169, -169, -169, -169, -169, -169, +     -169, -169, -169,   58, -169, -169,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  186,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -169 + +    }, + +    { +       11, -170, -170, -170, -170, -170, -170, -170, -170, -170, +     -170, -170, -170,   58, -170, -170,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  187,   58, -170 +    }, + +    { +       11, -171, -171, -171, -171, -171, -171, -171, -171, -171, +     -171, -171, -171,   58, -171, -171,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,  188,   58, +       58,   58,   58,   58,   58,   58,   58, -171 +    }, + +    { +       11, -172, -172, -172, -172, -172, -172, -172, -172, -172, +     -172, -172, -172,   58, -172, -172,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,  189,   58, +       58,   58,   58,   58,   58,   58,   58, -172 +    }, + +    { +       11, -173, -173, -173, -173, -173, -173, -173, -173, -173, +     -173, -173, -173,   58, -173, -173,   58,  190,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -173 +    }, + +    { +       11, -174, -174, -174, -174, -174, -174, -174, -174, -174, +     -174, -174, -174,   58, -174, -174,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -174 + +    }, + +    { +       11, -175, -175, -175, -175, -175, -175, -175, -175, -175, +     -175, -175, -175,   58, -175, -175,   58,   58,   58,   58, +       58,  191,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -175 +    }, + +    { +       11, -176, -176, -176, -176, -176, -176, -176, -176, -176, +     -176, -176, -176,   58, -176, -176,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -176 +    }, + +    { +       11, -177, -177, -177, -177, -177, -177, -177, -177, -177, +     -177, -177, -177,   58, -177, -177,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -177 +    }, + +    { +       11, -178, -178, -178, -178, -178, -178, -178, -178, -178, +     -178, -178, -178,   58, -178, -178,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -178 +    }, + +    { +       11, -179, -179, -179, -179, -179, -179, -179, -179, -179, +     -179, -179, -179,   58, -179, -179,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  192,   58,   58, -179 + +    }, + +    { +       11, -180, -180, -180, -180, -180, -180, -180, -180, -180, +     -180, -180, -180,   58, -180, -180,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -180 +    }, + +    { +       11, -181, -181, -181, -181, -181, -181, -181, -181, -181, +     -181, -181, -181,   58, -181, -181,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -181 +    }, + +    { +       11, -182, -182, -182, -182, -182, -182, -182, -182, -182, +     -182, -182, -182,   58, -182, -182,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,  193,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -182 +    }, + +    { +       11, -183, -183, -183, -183, -183, -183, -183, -183, -183, +     -183, -183, -183,   58, -183, -183,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,  194,   58,   58,   58, -183 +    }, + +    { +       11, -184, -184, -184, -184, -184, -184, -184, -184, -184, +     -184, -184, -184,   58, -184, -184,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -184 + +    }, + +    { +       11, -185, -185, -185, -185, -185, -185, -185, -185, -185, +     -185, -185, -185,   58, -185, -185,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -185 +    }, + +    { +       11, -186, -186, -186, -186, -186, -186, -186, -186, -186, +     -186, -186, -186,   58, -186, -186,   58,   58,   58,  195, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -186 +    }, + +    { +       11, -187, -187, -187, -187, -187, -187, -187, -187, -187, +     -187, -187, -187,   58, -187, -187,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -187 +    }, + +    { +       11, -188, -188, -188, -188, -188, -188, -188, -188, -188, +     -188, -188, -188,   58, -188, -188,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,  196,   58, -188 +    }, + +    { +       11, -189, -189, -189, -189, -189, -189, -189, -189, -189, +     -189, -189, -189,   58, -189, -189,   58,   58,   58,   58, +       58,   58,  197,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -189 + +    }, + +    { +       11, -190, -190, -190, -190, -190, -190, -190, -190, -190, +     -190, -190, -190,   58, -190, -190,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,  198,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -190 +    }, + +    { +       11, -191, -191, -191, -191, -191, -191, -191, -191, -191, +     -191, -191, -191,   58, -191, -191,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,  199,   58,   58,   58, -191 +    }, + +    { +       11, -192, -192, -192, -192, -192, -192, -192, -192, -192, +     -192, -192, -192,   58, -192, -192,   58,   58,   58,   58, + +       58,  200,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -192 +    }, + +    { +       11, -193, -193, -193, -193, -193, -193, -193, -193, -193, +     -193, -193, -193,   58, -193, -193,   58,   58,   58,   58, +       58,  201,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -193 +    }, + +    { +       11, -194, -194, -194, -194, -194, -194, -194, -194, -194, +     -194, -194, -194,   58, -194, -194,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  202,   58,   58, -194 + +    }, + +    { +       11, -195, -195, -195, -195, -195, -195, -195, -195, -195, +     -195, -195, -195,   58, -195, -195,   58,   58,   58,   58, +       58,  203,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -195 +    }, + +    { +       11, -196, -196, -196, -196, -196, -196, -196, -196, -196, +     -196, -196, -196,   58, -196, -196,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -196 +    }, + +    { +       11, -197, -197, -197, -197, -197, -197, -197, -197, -197, +     -197, -197, -197,   58, -197, -197,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,  204,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -197 +    }, + +    { +       11, -198, -198, -198, -198, -198, -198, -198, -198, -198, +     -198, -198, -198,   58, -198, -198,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -198 +    }, + +    { +       11, -199, -199, -199, -199, -199, -199, -199, -199, -199, +     -199, -199, -199,   58, -199, -199,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -199 + +    }, + +    { +       11, -200, -200, -200, -200, -200, -200, -200, -200, -200, +     -200, -200, -200,   58, -200, -200,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -200 +    }, + +    { +       11, -201, -201, -201, -201, -201, -201, -201, -201, -201, +     -201, -201, -201,   58, -201, -201,   58,  205,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -201 +    }, + +    { +       11, -202, -202, -202, -202, -202, -202, -202, -202, -202, +     -202, -202, -202,   58, -202, -202,   58,  206,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -202 +    }, + +    { +       11, -203, -203, -203, -203, -203, -203, -203, -203, -203, +     -203, -203, -203,   58, -203, -203,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -203 +    }, + +    { +       11, -204, -204, -204, -204, -204, -204, -204, -204, -204, +     -204, -204, -204,   58, -204, -204,   58,   58,   58,   58, +       58,   58,   58,  207,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -204 + +    }, + +    { +       11, -205, -205, -205, -205, -205, -205, -205, -205, -205, +     -205, -205, -205,   58, -205, -205,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,  208,   58, +       58,   58,   58,   58,   58,   58,   58, -205 +    }, + +    { +       11, -206, -206, -206, -206, -206, -206, -206, -206, -206, +     -206, -206, -206,   58, -206, -206,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,  209,   58,   58, -206 +    }, + +    { +       11, -207, -207, -207, -207, -207, -207, -207, -207, -207, +     -207, -207, -207,   58, -207, -207,   58,   58,   58,   58, + +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -207 +    }, + +    { +       11, -208, -208, -208, -208, -208, -208, -208, -208, -208, +     -208, -208, -208,   58, -208, -208,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -208 +    }, + +    { +       11, -209, -209, -209, -209, -209, -209, -209, -209, -209, +     -209, -209, -209,   58, -209, -209,   58,   58,   58,   58, +       58,  210,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -209 + +    }, + +    { +       11, -210, -210, -210, -210, -210, -210, -210, -210, -210, +     -210, -210, -210,   58, -210, -210,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58,   58,   58,   58, +       58,   58,   58,   58,   58,   58,   58, -210 +    }, + +    } ; + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[]  ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up zconftext. + */ +#define YY_DO_BEFORE_ACTION \ +	(yytext_ptr) = yy_bp; \ +	zconfleng = (size_t) (yy_cp - yy_bp); \ +	(yy_hold_char) = *yy_cp; \ +	*yy_cp = '\0'; \ +	(yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 64 +#define YY_END_OF_BUFFER 65 +/* This struct is not used in this scanner, +   but its presence is necessary. */ +struct yy_trans_info +	{ +	flex_int32_t yy_verify; +	flex_int32_t yy_nxt; +	}; +static yyconst flex_int16_t yy_accept[211] = +    {   0, +        0,    0,    0,    0,    0,    0,    0,    0,    0,    0, +       65,    5,    4,    3,    2,   36,   37,   35,   35,   35, +       35,   35,   35,   35,   35,   35,   35,   35,   35,   35, +       63,   60,   62,   55,   59,   58,   57,   53,   48,   42, +       47,   51,   53,   40,   41,   50,   50,   43,   53,   50, +       50,   53,    4,    3,    2,    2,    1,   35,   35,   35, +       35,   35,   35,   35,   16,   35,   35,   35,   35,   35, +       35,   35,   35,   35,   35,   35,   63,   60,   62,   61, +       55,   54,   57,   56,   44,   51,   38,   50,   50,   52, +       45,   46,   39,   35,   35,   35,   35,   35,   35,   35, + +       35,   35,   30,   29,   35,   35,   35,   35,   35,   35, +       35,   35,   35,   35,   49,   25,   35,   35,   35,   35, +       35,   35,   35,   35,   35,   35,   15,   35,    7,   35, +       35,   35,   35,   35,   35,   35,   35,   35,   35,   35, +       35,   35,   35,   35,   35,   35,   35,   17,   35,   35, +       35,   35,   35,   34,   35,   35,   35,   35,   35,   35, +       10,   35,   13,   35,   35,   35,   35,   33,   35,   35, +       35,   35,   35,   22,   35,   32,    9,   31,   35,   26, +       12,   35,   35,   21,   18,   35,    8,   35,   35,   35, +       35,   35,   27,   35,   35,    6,   35,   20,   19,   23, + +       35,   35,   11,   35,   35,   35,   14,   28,   35,   24 +    } ; + +static yyconst flex_int32_t yy_ec[256] = +    {   0, +        1,    1,    1,    1,    1,    1,    1,    1,    2,    3, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    2,    4,    5,    6,    1,    1,    7,    8,    9, +       10,    1,    1,    1,   11,   12,   12,   13,   13,   13, +       13,   13,   13,   13,   13,   13,   13,    1,    1,    1, +       14,    1,    1,    1,   13,   13,   13,   13,   13,   13, +       13,   13,   13,   13,   13,   13,   13,   13,   13,   13, +       13,   13,   13,   13,   13,   13,   13,   13,   13,   13, +        1,   15,    1,    1,   16,    1,   17,   18,   19,   20, + +       21,   22,   23,   24,   25,   13,   13,   26,   27,   28, +       29,   30,   31,   32,   33,   34,   35,   13,   13,   36, +       13,   13,    1,   37,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, + +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1 +    } ; + +extern int zconf_flex_debug; +int zconf_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *zconftext; + +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define START_STRSIZE	16 + +char *text; +static char *text_ptr; +static int text_size, text_asize; + +struct buffer { +        struct buffer *parent; +        YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static struct buffer *zconf_endfile(void); + +void new_string(void) +{ +	text = malloc(START_STRSIZE); +	text_asize = START_STRSIZE; +	text_ptr = text; +	text_size = 0; +	*text_ptr = 0; +} + +void append_string(const char *str, int size) +{ +	int new_size = text_size + size + 1; +	if (new_size > text_asize) { +		text = realloc(text, new_size); +		text_asize = new_size; +		text_ptr = text + text_size; +	} +	memcpy(text_ptr, str, size); +	text_ptr += size; +	text_size += size; +	*text_ptr = 0; +} + +void alloc_string(const char *str, int size) +{ +	text = malloc(size + 1); +	memcpy(text, str, size); +	text[size] = 0; +} + +#define INITIAL 0 +#define COMMAND 1 +#define HELP 2 +#define STRING 3 +#define PARAM 4 + +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int zconfwrap (void ); +#else +extern int zconfwrap (void ); +#endif +#endif + +    static void yyunput (int c,char *buf_ptr  ); +     +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( zconftext, zconfleng, 1, zconfout ) +#endif + +/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +	errno=0; \ +	while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \ +	{ \ +		if( errno != EINTR) \ +		{ \ +			YY_FATAL_ERROR( "input in flex scanner failed" ); \ +			break; \ +		} \ +		errno=0; \ +		clearerr(zconfin); \ +	}\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int zconflex (void); + +#define YY_DECL int zconflex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after zconftext and zconfleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ +	YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ +	register yy_state_type yy_current_state; +	register char *yy_cp, *yy_bp; +	register int yy_act; +     +	int str = 0; +	int ts, i; + +	if ( (yy_init) ) +		{ +		(yy_init) = 0; + +#ifdef YY_USER_INIT +		YY_USER_INIT; +#endif + +		if ( ! (yy_start) ) +			(yy_start) = 1;	/* first start state */ + +		if ( ! zconfin ) +			zconfin = stdin; + +		if ( ! zconfout ) +			zconfout = stdout; + +		if ( ! YY_CURRENT_BUFFER ) { +			zconfensure_buffer_stack (); +			YY_CURRENT_BUFFER_LVALUE = +				zconf_create_buffer(zconfin,YY_BUF_SIZE ); +		} + +		zconf_load_buffer_state( ); +		} + +	while ( 1 )		/* loops until end-of-file is reached */ +		{ +		yy_cp = (yy_c_buf_p); + +		/* Support of zconftext. */ +		*yy_cp = (yy_hold_char); + +		/* yy_bp points to the position in yy_ch_buf of the start of +		 * the current run. +		 */ +		yy_bp = yy_cp; + +		yy_current_state = (yy_start); +yy_match: +		while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)]  ]) > 0 ) +			++yy_cp; + +		yy_current_state = -yy_current_state; + +yy_find_action: +		yy_act = yy_accept[yy_current_state]; + +		YY_DO_BEFORE_ACTION; + +do_action:	/* This label is used only to access EOF actions. */ + +		switch ( yy_act ) +	{ /* beginning of action switch */ +case 1: +/* rule 1 can match eol */ +YY_RULE_SETUP +current_file->lineno++; +	YY_BREAK +case 2: +YY_RULE_SETUP + +	YY_BREAK +case 3: +/* rule 3 can match eol */ +YY_RULE_SETUP +current_file->lineno++; return T_EOL; +	YY_BREAK +case 4: +YY_RULE_SETUP +{ +	BEGIN(COMMAND); +} +	YY_BREAK +case 5: +YY_RULE_SETUP +{ +	unput(zconftext[0]); +	BEGIN(COMMAND); +} +	YY_BREAK + +case 6: +YY_RULE_SETUP +BEGIN(PARAM); return T_MAINMENU; +	YY_BREAK +case 7: +YY_RULE_SETUP +BEGIN(PARAM); return T_MENU; +	YY_BREAK +case 8: +YY_RULE_SETUP +BEGIN(PARAM); return T_ENDMENU; +	YY_BREAK +case 9: +YY_RULE_SETUP +BEGIN(PARAM); return T_SOURCE; +	YY_BREAK +case 10: +YY_RULE_SETUP +BEGIN(PARAM); return T_CHOICE; +	YY_BREAK +case 11: +YY_RULE_SETUP +BEGIN(PARAM); return T_ENDCHOICE; +	YY_BREAK +case 12: +YY_RULE_SETUP +BEGIN(PARAM); return T_COMMENT; +	YY_BREAK +case 13: +YY_RULE_SETUP +BEGIN(PARAM); return T_CONFIG; +	YY_BREAK +case 14: +YY_RULE_SETUP +BEGIN(PARAM); return T_MENUCONFIG; +	YY_BREAK +case 15: +YY_RULE_SETUP +BEGIN(PARAM); return T_HELP; +	YY_BREAK +case 16: +YY_RULE_SETUP +BEGIN(PARAM); return T_IF; +	YY_BREAK +case 17: +YY_RULE_SETUP +BEGIN(PARAM); return T_ENDIF; +	YY_BREAK +case 18: +YY_RULE_SETUP +BEGIN(PARAM); return T_DEPENDS; +	YY_BREAK +case 19: +YY_RULE_SETUP +BEGIN(PARAM); return T_REQUIRES; +	YY_BREAK +case 20: +YY_RULE_SETUP +BEGIN(PARAM); return T_OPTIONAL; +	YY_BREAK +case 21: +YY_RULE_SETUP +BEGIN(PARAM); return T_DEFAULT; +	YY_BREAK +case 22: +YY_RULE_SETUP +BEGIN(PARAM); return T_PROMPT; +	YY_BREAK +case 23: +YY_RULE_SETUP +BEGIN(PARAM); return T_TRISTATE; +	YY_BREAK +case 24: +YY_RULE_SETUP +BEGIN(PARAM); return T_DEF_TRISTATE; +	YY_BREAK +case 25: +YY_RULE_SETUP +BEGIN(PARAM); return T_BOOLEAN; +	YY_BREAK +case 26: +YY_RULE_SETUP +BEGIN(PARAM); return T_BOOLEAN; +	YY_BREAK +case 27: +YY_RULE_SETUP +BEGIN(PARAM); return T_DEF_BOOLEAN; +	YY_BREAK +case 28: +YY_RULE_SETUP +BEGIN(PARAM); return T_DEF_BOOLEAN; +	YY_BREAK +case 29: +YY_RULE_SETUP +BEGIN(PARAM); return T_INT; +	YY_BREAK +case 30: +YY_RULE_SETUP +BEGIN(PARAM); return T_HEX; +	YY_BREAK +case 31: +YY_RULE_SETUP +BEGIN(PARAM); return T_STRING; +	YY_BREAK +case 32: +YY_RULE_SETUP +BEGIN(PARAM); return T_SELECT; +	YY_BREAK +case 33: +YY_RULE_SETUP +BEGIN(PARAM); return T_SELECT; +	YY_BREAK +case 34: +YY_RULE_SETUP +BEGIN(PARAM); return T_RANGE; +	YY_BREAK +case 35: +YY_RULE_SETUP +{ +		alloc_string(zconftext, zconfleng); +		zconflval.string = text; +		return T_WORD; +	} +	YY_BREAK +case 36: +YY_RULE_SETUP + +	YY_BREAK +case 37: +/* rule 37 can match eol */ +YY_RULE_SETUP +current_file->lineno++; BEGIN(INITIAL); +	YY_BREAK + +case 38: +YY_RULE_SETUP +return T_AND; +	YY_BREAK +case 39: +YY_RULE_SETUP +return T_OR; +	YY_BREAK +case 40: +YY_RULE_SETUP +return T_OPEN_PAREN; +	YY_BREAK +case 41: +YY_RULE_SETUP +return T_CLOSE_PAREN; +	YY_BREAK +case 42: +YY_RULE_SETUP +return T_NOT; +	YY_BREAK +case 43: +YY_RULE_SETUP +return T_EQUAL; +	YY_BREAK +case 44: +YY_RULE_SETUP +return T_UNEQUAL; +	YY_BREAK +case 45: +YY_RULE_SETUP +return T_IF; +	YY_BREAK +case 46: +YY_RULE_SETUP +return T_ON; +	YY_BREAK +case 47: +YY_RULE_SETUP +{ +		str = zconftext[0]; +		new_string(); +		BEGIN(STRING); +	} +	YY_BREAK +case 48: +/* rule 48 can match eol */ +YY_RULE_SETUP +BEGIN(INITIAL); current_file->lineno++; return T_EOL; +	YY_BREAK +case 49: +YY_RULE_SETUP +/* ignore */ +	YY_BREAK +case 50: +YY_RULE_SETUP +{ +		alloc_string(zconftext, zconfleng); +		zconflval.string = text; +		return T_WORD; +	} +	YY_BREAK +case 51: +YY_RULE_SETUP +/* comment */ +	YY_BREAK +case 52: +/* rule 52 can match eol */ +YY_RULE_SETUP +current_file->lineno++; +	YY_BREAK +case 53: +YY_RULE_SETUP + +	YY_BREAK +case YY_STATE_EOF(PARAM): +{ +		BEGIN(INITIAL); +	} +	YY_BREAK + +case 54: +/* rule 54 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ +		append_string(zconftext, zconfleng); +		zconflval.string = text; +		return T_WORD_QUOTE; +	} +	YY_BREAK +case 55: +YY_RULE_SETUP +{ +		append_string(zconftext, zconfleng); +	} +	YY_BREAK +case 56: +/* rule 56 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ +		append_string(zconftext + 1, zconfleng - 1); +		zconflval.string = text; +		return T_WORD_QUOTE; +	} +	YY_BREAK +case 57: +YY_RULE_SETUP +{ +		append_string(zconftext + 1, zconfleng - 1); +	} +	YY_BREAK +case 58: +YY_RULE_SETUP +{ +		if (str == zconftext[0]) { +			BEGIN(PARAM); +			zconflval.string = text; +			return T_WORD_QUOTE; +		} else +			append_string(zconftext, 1); +	} +	YY_BREAK +case 59: +/* rule 59 can match eol */ +YY_RULE_SETUP +{ +		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); +		current_file->lineno++; +		BEGIN(INITIAL); +		return T_EOL; +	} +	YY_BREAK +case YY_STATE_EOF(STRING): +{ +		BEGIN(INITIAL); +	} +	YY_BREAK + +case 60: +YY_RULE_SETUP +{ +		ts = 0; +		for (i = 0; i < zconfleng; i++) { +			if (zconftext[i] == '\t') +				ts = (ts & ~7) + 8; +			else +				ts++; +		} +		last_ts = ts; +		if (first_ts) { +			if (ts < first_ts) { +				zconf_endhelp(); +				return T_HELPTEXT; +			} +			ts -= first_ts; +			while (ts > 8) { +				append_string("        ", 8); +				ts -= 8; +			} +			append_string("        ", ts); +		} +	} +	YY_BREAK +case 61: +/* rule 61 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ +		current_file->lineno++; +		zconf_endhelp(); +		return T_HELPTEXT; +	} +	YY_BREAK +case 62: +/* rule 62 can match eol */ +YY_RULE_SETUP +{ +		current_file->lineno++; +		append_string("\n", 1); +	} +	YY_BREAK +case 63: +YY_RULE_SETUP +{ +		append_string(zconftext, zconfleng); +		if (!first_ts) +			first_ts = last_ts; +	} +	YY_BREAK +case YY_STATE_EOF(HELP): +{ +		zconf_endhelp(); +		return T_HELPTEXT; +	} +	YY_BREAK + +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMAND): +{ +	if (current_buf) { +		zconf_endfile(); +		return T_EOF; +	} +	fclose(zconfin); +	yyterminate(); +} +	YY_BREAK +case 64: +YY_RULE_SETUP +YY_FATAL_ERROR( "flex scanner jammed" ); +	YY_BREAK + +	case YY_END_OF_BUFFER: +		{ +		/* Amount of text matched not including the EOB char. */ +		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + +		/* Undo the effects of YY_DO_BEFORE_ACTION. */ +		*yy_cp = (yy_hold_char); +		YY_RESTORE_YY_MORE_OFFSET + +		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) +			{ +			/* We're scanning a new file or input source.  It's +			 * possible that this happened because the user +			 * just pointed zconfin at a new source and called +			 * zconflex().  If so, then we have to assure +			 * consistency between YY_CURRENT_BUFFER and our +			 * globals.  Here is the right place to do so, because +			 * this is the first action (other than possibly a +			 * back-up) that will match for the new input source. +			 */ +			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; +			YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin; +			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; +			} + +		/* Note that here we test for yy_c_buf_p "<=" to the position +		 * of the first EOB in the buffer, since yy_c_buf_p will +		 * already have been incremented past the NUL character +		 * (since all states make transitions on EOB to the +		 * end-of-buffer state).  Contrast this with the test +		 * in input(). +		 */ +		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) +			{ /* This was really a NUL. */ +			yy_state_type yy_next_state; + +			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + +			yy_current_state = yy_get_previous_state(  ); + +			/* Okay, we're now positioned to make the NUL +			 * transition.  We couldn't have +			 * yy_get_previous_state() go ahead and do it +			 * for us because it doesn't know how to deal +			 * with the possibility of jamming (and we don't +			 * want to build jamming into it because then it +			 * will run more slowly). +			 */ + +			yy_next_state = yy_try_NUL_trans( yy_current_state ); + +			yy_bp = (yytext_ptr) + YY_MORE_ADJ; + +			if ( yy_next_state ) +				{ +				/* Consume the NUL. */ +				yy_cp = ++(yy_c_buf_p); +				yy_current_state = yy_next_state; +				goto yy_match; +				} + +			else +				{ +				yy_cp = (yy_c_buf_p); +				goto yy_find_action; +				} +			} + +		else switch ( yy_get_next_buffer(  ) ) +			{ +			case EOB_ACT_END_OF_FILE: +				{ +				(yy_did_buffer_switch_on_eof) = 0; + +				if ( zconfwrap( ) ) +					{ +					/* Note: because we've taken care in +					 * yy_get_next_buffer() to have set up +					 * zconftext, we can now set up +					 * yy_c_buf_p so that if some total +					 * hoser (like flex itself) wants to +					 * call the scanner after we return the +					 * YY_NULL, it'll still work - another +					 * YY_NULL will get returned. +					 */ +					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + +					yy_act = YY_STATE_EOF(YY_START); +					goto do_action; +					} + +				else +					{ +					if ( ! (yy_did_buffer_switch_on_eof) ) +						YY_NEW_FILE; +					} +				break; +				} + +			case EOB_ACT_CONTINUE_SCAN: +				(yy_c_buf_p) = +					(yytext_ptr) + yy_amount_of_matched_text; + +				yy_current_state = yy_get_previous_state(  ); + +				yy_cp = (yy_c_buf_p); +				yy_bp = (yytext_ptr) + YY_MORE_ADJ; +				goto yy_match; + +			case EOB_ACT_LAST_MATCH: +				(yy_c_buf_p) = +				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + +				yy_current_state = yy_get_previous_state(  ); + +				yy_cp = (yy_c_buf_p); +				yy_bp = (yytext_ptr) + YY_MORE_ADJ; +				goto yy_find_action; +			} +		break; +		} + +	default: +		YY_FATAL_ERROR( +			"fatal flex scanner internal error--no action found" ); +	} /* end of action switch */ +		} /* end of scanning one token */ +} /* end of zconflex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + *	EOB_ACT_LAST_MATCH - + *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position + *	EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ +    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; +	register char *source = (yytext_ptr); +	register int number_to_move, i; +	int ret_val; + +	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) +		YY_FATAL_ERROR( +		"fatal flex scanner internal error--end of buffer missed" ); + +	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) +		{ /* Don't try to fill the buffer, so this is an EOF. */ +		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) +			{ +			/* We matched a single character, the EOB, so +			 * treat this as a final EOF. +			 */ +			return EOB_ACT_END_OF_FILE; +			} + +		else +			{ +			/* We matched some text prior to the EOB, first +			 * process it. +			 */ +			return EOB_ACT_LAST_MATCH; +			} +		} + +	/* Try to read more data. */ + +	/* First move last chars to start of buffer. */ +	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + +	for ( i = 0; i < number_to_move; ++i ) +		*(dest++) = *(source++); + +	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) +		/* don't do the read, it's not guaranteed to return an EOF, +		 * just force an EOF +		 */ +		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + +	else +		{ +			size_t num_to_read = +			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + +		while ( num_to_read <= 0 ) +			{ /* Not enough room in the buffer - grow it. */ + +			/* just a shorter name for the current buffer */ +			YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + +			int yy_c_buf_p_offset = +				(int) ((yy_c_buf_p) - b->yy_ch_buf); + +			if ( b->yy_is_our_buffer ) +				{ +				int new_size = b->yy_buf_size * 2; + +				if ( new_size <= 0 ) +					b->yy_buf_size += b->yy_buf_size / 8; +				else +					b->yy_buf_size *= 2; + +				b->yy_ch_buf = (char *) +					/* Include room in for 2 EOB chars. */ +					zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  ); +				} +			else +				/* Can't grow it, we don't own it. */ +				b->yy_ch_buf = 0; + +			if ( ! b->yy_ch_buf ) +				YY_FATAL_ERROR( +				"fatal error - scanner input buffer overflow" ); + +			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + +			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - +						number_to_move - 1; + +			} + +		if ( num_to_read > YY_READ_BUF_SIZE ) +			num_to_read = YY_READ_BUF_SIZE; + +		/* Read in more data. */ +		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), +			(yy_n_chars), num_to_read ); + +		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); +		} + +	if ( (yy_n_chars) == 0 ) +		{ +		if ( number_to_move == YY_MORE_ADJ ) +			{ +			ret_val = EOB_ACT_END_OF_FILE; +			zconfrestart(zconfin  ); +			} + +		else +			{ +			ret_val = EOB_ACT_LAST_MATCH; +			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = +				YY_BUFFER_EOF_PENDING; +			} +		} + +	else +		ret_val = EOB_ACT_CONTINUE_SCAN; + +	(yy_n_chars) += number_to_move; +	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; +	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + +	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + +	return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +    static yy_state_type yy_get_previous_state (void) +{ +	register yy_state_type yy_current_state; +	register char *yy_cp; +     +	yy_current_state = (yy_start); + +	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) +		{ +		yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; +		} + +	return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + *	next_state = yy_try_NUL_trans( current_state ); + */ +    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state ) +{ +	register int yy_is_jam; +     +	yy_current_state = yy_nxt[yy_current_state][1]; +	yy_is_jam = (yy_current_state <= 0); + +	return yy_is_jam ? 0 : yy_current_state; +} + +    static void yyunput (int c, register char * yy_bp ) +{ +	register char *yy_cp; +     +    yy_cp = (yy_c_buf_p); + +	/* undo effects of setting up zconftext */ +	*yy_cp = (yy_hold_char); + +	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) +		{ /* need to shift things up to make room */ +		/* +2 for EOB chars. */ +		register int number_to_move = (yy_n_chars) + 2; +		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ +					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; +		register char *source = +				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + +		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) +			*--dest = *--source; + +		yy_cp += (int) (dest - source); +		yy_bp += (int) (dest - source); +		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = +			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + +		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) +			YY_FATAL_ERROR( "flex scanner push-back overflow" ); +		} + +	*--yy_cp = (char) c; + +	(yytext_ptr) = yy_bp; +	(yy_hold_char) = *yy_cp; +	(yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +    static int yyinput (void) +#else +    static int input  (void) +#endif + +{ +	int c; +     +	*(yy_c_buf_p) = (yy_hold_char); + +	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) +		{ +		/* yy_c_buf_p now points to the character we want to return. +		 * If this occurs *before* the EOB characters, then it's a +		 * valid NUL; if not, then we've hit the end of the buffer. +		 */ +		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) +			/* This was really a NUL. */ +			*(yy_c_buf_p) = '\0'; + +		else +			{ /* need more input */ +			int offset = (yy_c_buf_p) - (yytext_ptr); +			++(yy_c_buf_p); + +			switch ( yy_get_next_buffer(  ) ) +				{ +				case EOB_ACT_LAST_MATCH: +					/* This happens because yy_g_n_b() +					 * sees that we've accumulated a +					 * token and flags that we need to +					 * try matching the token before +					 * proceeding.  But for input(), +					 * there's no matching to consider. +					 * So convert the EOB_ACT_LAST_MATCH +					 * to EOB_ACT_END_OF_FILE. +					 */ + +					/* Reset buffer status. */ +					zconfrestart(zconfin ); + +					/*FALLTHROUGH*/ + +				case EOB_ACT_END_OF_FILE: +					{ +					if ( zconfwrap( ) ) +						return EOF; + +					if ( ! (yy_did_buffer_switch_on_eof) ) +						YY_NEW_FILE; +#ifdef __cplusplus +					return yyinput(); +#else +					return input(); +#endif +					} + +				case EOB_ACT_CONTINUE_SCAN: +					(yy_c_buf_p) = (yytext_ptr) + offset; +					break; +				} +			} +		} + +	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */ +	*(yy_c_buf_p) = '\0';	/* preserve zconftext */ +	(yy_hold_char) = *++(yy_c_buf_p); + +	return c; +} +#endif	/* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + *  + * @note This function does not reset the start condition to @c INITIAL . + */ +    void zconfrestart  (FILE * input_file ) +{ +     +	if ( ! YY_CURRENT_BUFFER ){ +        zconfensure_buffer_stack (); +		YY_CURRENT_BUFFER_LVALUE = +            zconf_create_buffer(zconfin,YY_BUF_SIZE ); +	} + +	zconf_init_buffer(YY_CURRENT_BUFFER,input_file ); +	zconf_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + *  + */ +    void zconf_switch_to_buffer  (YY_BUFFER_STATE  new_buffer ) +{ +     +	/* TODO. We should be able to replace this entire function body +	 * with +	 *		zconfpop_buffer_state(); +	 *		zconfpush_buffer_state(new_buffer); +     */ +	zconfensure_buffer_stack (); +	if ( YY_CURRENT_BUFFER == new_buffer ) +		return; + +	if ( YY_CURRENT_BUFFER ) +		{ +		/* Flush out information for old buffer. */ +		*(yy_c_buf_p) = (yy_hold_char); +		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); +		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); +		} + +	YY_CURRENT_BUFFER_LVALUE = new_buffer; +	zconf_load_buffer_state( ); + +	/* We don't actually know whether we did this switch during +	 * EOF (zconfwrap()) processing, but the only time this flag +	 * is looked at is after zconfwrap() is called, so it's safe +	 * to go ahead and always set it. +	 */ +	(yy_did_buffer_switch_on_eof) = 1; +} + +static void zconf_load_buffer_state  (void) +{ +    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; +	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; +	zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; +	(yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + *  + * @return the allocated buffer state. + */ +    YY_BUFFER_STATE zconf_create_buffer  (FILE * file, int  size ) +{ +	YY_BUFFER_STATE b; +     +	b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  ); +	if ( ! b ) +		YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + +	b->yy_buf_size = size; + +	/* yy_ch_buf has to be 2 characters longer than the size given because +	 * we need to put in 2 end-of-buffer characters. +	 */ +	b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2  ); +	if ( ! b->yy_ch_buf ) +		YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + +	b->yy_is_our_buffer = 1; + +	zconf_init_buffer(b,file ); + +	return b; +} + +/** Destroy the buffer. + * @param b a buffer created with zconf_create_buffer() + *  + */ +    void zconf_delete_buffer (YY_BUFFER_STATE  b ) +{ +     +	if ( ! b ) +		return; + +	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ +		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + +	if ( b->yy_is_our_buffer ) +		zconffree((void *) b->yy_ch_buf  ); + +	zconffree((void *) b  ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a zconfrestart() or at EOF. + */ +    static void zconf_init_buffer  (YY_BUFFER_STATE  b, FILE * file ) + +{ +	int oerrno = errno; +     +	zconf_flush_buffer(b ); + +	b->yy_input_file = file; +	b->yy_fill_buffer = 1; + +    /* If b is the current buffer, then zconf_init_buffer was _probably_ +     * called from zconfrestart() or through yy_get_next_buffer. +     * In that case, we don't want to reset the lineno or column. +     */ +    if (b != YY_CURRENT_BUFFER){ +        b->yy_bs_lineno = 1; +        b->yy_bs_column = 0; +    } + +        b->yy_is_interactive = 0; +     +	errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + *  + */ +    void zconf_flush_buffer (YY_BUFFER_STATE  b ) +{ +    	if ( ! b ) +		return; + +	b->yy_n_chars = 0; + +	/* We always need two end-of-buffer characters.  The first causes +	 * a transition to the end-of-buffer state.  The second causes +	 * a jam in that state. +	 */ +	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; +	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + +	b->yy_buf_pos = &b->yy_ch_buf[0]; + +	b->yy_at_bol = 1; +	b->yy_buffer_status = YY_BUFFER_NEW; + +	if ( b == YY_CURRENT_BUFFER ) +		zconf_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + *  the current state. This function will allocate the stack + *  if necessary. + *  @param new_buffer The new state. + *   + */ +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ +    	if (new_buffer == NULL) +		return; + +	zconfensure_buffer_stack(); + +	/* This block is copied from zconf_switch_to_buffer. */ +	if ( YY_CURRENT_BUFFER ) +		{ +		/* Flush out information for old buffer. */ +		*(yy_c_buf_p) = (yy_hold_char); +		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); +		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); +		} + +	/* Only push if top exists. Otherwise, replace top. */ +	if (YY_CURRENT_BUFFER) +		(yy_buffer_stack_top)++; +	YY_CURRENT_BUFFER_LVALUE = new_buffer; + +	/* copied from zconf_switch_to_buffer. */ +	zconf_load_buffer_state( ); +	(yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + *  The next element becomes the new top. + *   + */ +void zconfpop_buffer_state (void) +{ +    	if (!YY_CURRENT_BUFFER) +		return; + +	zconf_delete_buffer(YY_CURRENT_BUFFER ); +	YY_CURRENT_BUFFER_LVALUE = NULL; +	if ((yy_buffer_stack_top) > 0) +		--(yy_buffer_stack_top); + +	if (YY_CURRENT_BUFFER) { +		zconf_load_buffer_state( ); +		(yy_did_buffer_switch_on_eof) = 1; +	} +} + +/* Allocates the stack if it does not exist. + *  Guarantees space for at least one push. + */ +static void zconfensure_buffer_stack (void) +{ +	int num_to_alloc; +     +	if (!(yy_buffer_stack)) { + +		/* First allocation is just for 2 elements, since we don't know if this +		 * scanner will even need a stack. We use 2 instead of 1 to avoid an +		 * immediate realloc on the next call. +         */ +		num_to_alloc = 1; +		(yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc +								(num_to_alloc * sizeof(struct yy_buffer_state*) +								); +		 +		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); +				 +		(yy_buffer_stack_max) = num_to_alloc; +		(yy_buffer_stack_top) = 0; +		return; +	} + +	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + +		/* Increase the buffer to prepare for a possible push. */ +		int grow_size = 8 /* arbitrary grow size */; + +		num_to_alloc = (yy_buffer_stack_max) + grow_size; +		(yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc +								((yy_buffer_stack), +								num_to_alloc * sizeof(struct yy_buffer_state*) +								); + +		/* zero only the new slots.*/ +		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); +		(yy_buffer_stack_max) = num_to_alloc; +	} +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + *  + * @return the newly allocated buffer state object.  + */ +YY_BUFFER_STATE zconf_scan_buffer  (char * base, yy_size_t  size ) +{ +	YY_BUFFER_STATE b; +     +	if ( size < 2 || +	     base[size-2] != YY_END_OF_BUFFER_CHAR || +	     base[size-1] != YY_END_OF_BUFFER_CHAR ) +		/* They forgot to leave room for the EOB's. */ +		return 0; + +	b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  ); +	if ( ! b ) +		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" ); + +	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */ +	b->yy_buf_pos = b->yy_ch_buf = base; +	b->yy_is_our_buffer = 0; +	b->yy_input_file = 0; +	b->yy_n_chars = b->yy_buf_size; +	b->yy_is_interactive = 0; +	b->yy_at_bol = 1; +	b->yy_fill_buffer = 0; +	b->yy_buffer_status = YY_BUFFER_NEW; + +	zconf_switch_to_buffer(b  ); + +	return b; +} + +/** Setup the input buffer state to scan a string. The next call to zconflex() will + * scan from a @e copy of @a str. + * @param str a NUL-terminated string to scan + *  + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + *       zconf_scan_bytes() instead. + */ +YY_BUFFER_STATE zconf_scan_string (yyconst char * str ) +{ +     +	return zconf_scan_bytes(str,strlen(str) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + *  + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * bytes, int  len ) +{ +	YY_BUFFER_STATE b; +	char *buf; +	yy_size_t n; +	int i; +     +	/* Get memory for full buffer, including space for trailing EOB's. */ +	n = len + 2; +	buf = (char *) zconfalloc(n  ); +	if ( ! buf ) +		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); + +	for ( i = 0; i < len; ++i ) +		buf[i] = bytes[i]; + +	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + +	b = zconf_scan_buffer(buf,n ); +	if ( ! b ) +		YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" ); + +	/* It's okay to grow etc. this buffer, and we should throw it +	 * away when we're done. +	 */ +	b->yy_is_our_buffer = 1; + +	return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ +    	(void) fprintf( stderr, "%s\n", msg ); +	exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ +	do \ +		{ \ +		/* Undo effects of setting up zconftext. */ \ +        int yyless_macro_arg = (n); \ +        YY_LESS_LINENO(yyless_macro_arg);\ +		zconftext[zconfleng] = (yy_hold_char); \ +		(yy_c_buf_p) = zconftext + yyless_macro_arg; \ +		(yy_hold_char) = *(yy_c_buf_p); \ +		*(yy_c_buf_p) = '\0'; \ +		zconfleng = yyless_macro_arg; \ +		} \ +	while ( 0 ) + +/* Accessor  methods (get/set functions) to struct members. */ + +/** Get the current line number. + *  + */ +int zconfget_lineno  (void) +{ +         +    return zconflineno; +} + +/** Get the input stream. + *  + */ +FILE *zconfget_in  (void) +{ +        return zconfin; +} + +/** Get the output stream. + *  + */ +FILE *zconfget_out  (void) +{ +        return zconfout; +} + +/** Get the length of the current token. + *  + */ +int zconfget_leng  (void) +{ +        return zconfleng; +} + +/** Get the current token. + *  + */ + +char *zconfget_text  (void) +{ +        return zconftext; +} + +/** Set the current line number. + * @param line_number + *  + */ +void zconfset_lineno (int  line_number ) +{ +     +    zconflineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + *  + * @see zconf_switch_to_buffer + */ +void zconfset_in (FILE *  in_str ) +{ +        zconfin = in_str ; +} + +void zconfset_out (FILE *  out_str ) +{ +        zconfout = out_str ; +} + +int zconfget_debug  (void) +{ +        return zconf_flex_debug; +} + +void zconfset_debug (int  bdebug ) +{ +        zconf_flex_debug = bdebug ; +} + +/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ +int zconflex_destroy  (void) +{ +     +    /* Pop the buffer stack, destroying each element. */ +	while(YY_CURRENT_BUFFER){ +		zconf_delete_buffer(YY_CURRENT_BUFFER  ); +		YY_CURRENT_BUFFER_LVALUE = NULL; +		zconfpop_buffer_state(); +	} + +	/* Destroy the stack itself. */ +	zconffree((yy_buffer_stack) ); +	(yy_buffer_stack) = NULL; + +    return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ +	register int i; +    	for ( i = 0; i < n; ++i ) +		s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ +	register int n; +    	for ( n = 0; s[n]; ++n ) +		; + +	return n; +} +#endif + +void *zconfalloc (yy_size_t  size ) +{ +	return (void *) malloc( size ); +} + +void *zconfrealloc  (void * ptr, yy_size_t  size ) +{ +	/* The cast to (char *) in the following accommodates both +	 * implementations that use char* generic pointers, and those +	 * that use void* generic pointers.  It works with the latter +	 * because both ANSI C and C++ allow castless assignment from +	 * any pointer type to void*, and deal with argument conversions +	 * as though doing an assignment. +	 */ +	return (void *) realloc( (char *) ptr, size ); +} + +void zconffree (void * ptr ) +{ +	free( (char *) ptr );	/* see zconfrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef yytext_ptr +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +void zconf_starthelp(void) +{ +	new_string(); +	last_ts = first_ts = 0; +	BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ +	zconflval.string = text; +	BEGIN(INITIAL); +} + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ +	char *env, fullname[PATH_MAX+1]; +	FILE *f; + +	f = fopen(name, "r"); +	if (!f && name[0] != '/') { +		env = getenv(SRCTREE); +		if (env) { +			sprintf(fullname, "%s/%s", env, name); +			f = fopen(fullname, "r"); +		} +	} +	return f; +} + +void zconf_initscan(const char *name) +{ +	zconfin = zconf_fopen(name); +	if (!zconfin) { +		printf("can't find file %s\n", name); +		exit(1); +	} + +	current_buf = malloc(sizeof(*current_buf)); +	memset(current_buf, 0, sizeof(*current_buf)); + +	current_file = file_lookup(name); +	current_file->lineno = 1; +	current_file->flags = FILE_BUSY; +} + +void zconf_nextfile(const char *name) +{ +	struct file *file = file_lookup(name); +	struct buffer *buf = malloc(sizeof(*buf)); +	memset(buf, 0, sizeof(*buf)); + +	current_buf->state = YY_CURRENT_BUFFER; +	zconfin = zconf_fopen(name); +	if (!zconfin) { +		printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name); +		exit(1); +	} +	zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE)); +	buf->parent = current_buf; +	current_buf = buf; + +	if (file->flags & FILE_BUSY) { +		printf("recursive scan (%s)?\n", name); +		exit(1); +	} +	if (file->flags & FILE_SCANNED) { +		printf("file %s already scanned?\n", name); +		exit(1); +	} +	file->flags |= FILE_BUSY; +	file->lineno = 1; +	file->parent = current_file; +	current_file = file; +} + +static struct buffer *zconf_endfile(void) +{ +	struct buffer *parent; + +	current_file->flags |= FILE_SCANNED; +	current_file->flags &= ~FILE_BUSY; +	current_file = current_file->parent; + +	parent = current_buf->parent; +	if (parent) { +		fclose(zconfin); +		zconf_delete_buffer(YY_CURRENT_BUFFER); +		zconf_switch_to_buffer(parent->state); +	} +	free(current_buf); +	current_buf = parent; + +	return parent; +} + +int zconf_lineno(void) +{ +	if (current_buf) +		return current_file->lineno - 1; +	else +		return 0; +} + +char *zconf_curname(void) +{ +	if (current_buf) +		return current_file->name; +	else +		return "<none>"; +} + diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h new file mode 100644 index 000000000000..b8a67fc9d647 --- /dev/null +++ b/scripts/kconfig/lkc.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef LKC_H +#define LKC_H + +#include "expr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LKC_DIRECT_LINK +#define P(name,type,arg)	extern type name arg +#else +#include "lkc_defs.h" +#define P(name,type,arg)	extern type (*name ## _p) arg +#endif +#include "lkc_proto.h" +#undef P + +#define SRCTREE "srctree" + +int zconfparse(void); +void zconfdump(FILE *out); + +extern int zconfdebug; +void zconf_starthelp(void); +FILE *zconf_fopen(const char *name); +void zconf_initscan(const char *name); +void zconf_nextfile(const char *name); +int zconf_lineno(void); +char *zconf_curname(void); + +/* confdata.c */ +extern const char conf_def_filename[]; +extern char conf_filename[]; + +char *conf_get_default_confname(void); + +/* kconfig_load.c */ +void kconfig_load(void); + +/* menu.c */ +void menu_init(void); +void menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_end_entry(void); +void menu_add_dep(struct expr *dep); +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); +void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +/* util.c */ +struct file *file_lookup(const char *name); +int file_write_dep(const char *name); + +struct gstr { +	size_t len; +	char  *s; +}; +struct gstr str_new(void); +struct gstr str_assign(const char *s); +void str_free(struct gstr *gs); +void str_append(struct gstr *gs, const char *s); +void str_printf(struct gstr *gs, const char *fmt, ...); +const char *str_get(struct gstr *gs); + +/* symbol.c */ +void sym_init(void); +void sym_clear_all_valid(void); +void sym_set_changed(struct symbol *sym); +struct symbol *sym_check_deps(struct symbol *sym); +struct property *prop_alloc(enum prop_type type, struct symbol *sym); +struct symbol *prop_get_symbol(struct property *prop); + +static inline tristate sym_get_tristate_value(struct symbol *sym) +{ +	return sym->curr.tri; +} + + +static inline struct symbol *sym_get_choice_value(struct symbol *sym) +{ +	return (struct symbol *)sym->curr.val; +} + +static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) +{ +	return sym_set_tristate_value(chval, yes); +} + +static inline bool sym_is_choice(struct symbol *sym) +{ +	return sym->flags & SYMBOL_CHOICE ? true : false; +} + +static inline bool sym_is_choice_value(struct symbol *sym) +{ +	return sym->flags & SYMBOL_CHOICEVAL ? true : false; +} + +static inline bool sym_is_optional(struct symbol *sym) +{ +	return sym->flags & SYMBOL_OPTIONAL ? true : false; +} + +static inline bool sym_has_value(struct symbol *sym) +{ +	return sym->flags & SYMBOL_NEW ? false : true; +} + +#ifdef __cplusplus +} +#endif + +#endif /* LKC_H */ diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h new file mode 100644 index 000000000000..6dc6d0c48e7a --- /dev/null +++ b/scripts/kconfig/lkc_proto.h @@ -0,0 +1,40 @@ + +/* confdata.c */ +P(conf_parse,void,(const char *name)); +P(conf_read,int,(const char *name)); +P(conf_write,int,(const char *name)); + +/* menu.c */ +P(rootmenu,struct menu,); + +P(menu_is_visible,bool,(struct menu *menu)); +P(menu_get_prompt,const char *,(struct menu *menu)); +P(menu_get_root_menu,struct menu *,(struct menu *menu)); +P(menu_get_parent_menu,struct menu *,(struct menu *menu)); + +/* symbol.c */ +P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); +P(sym_change_count,int,); + +P(sym_lookup,struct symbol *,(const char *name, int isconst)); +P(sym_find,struct symbol *,(const char *name)); +P(sym_re_search,struct symbol **,(const char *pattern)); +P(sym_type_name,const char *,(enum symbol_type type)); +P(sym_calc_value,void,(struct symbol *sym)); +P(sym_get_type,enum symbol_type,(struct symbol *sym)); +P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); +P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); +P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); +P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); +P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); +P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); +P(sym_is_changable,bool,(struct symbol *sym)); +P(sym_get_choice_prop,struct property *,(struct symbol *sym)); +P(sym_get_default_prop,struct property *,(struct symbol *sym)); +P(sym_get_string_value,const char *,(struct symbol *sym)); + +P(prop_get_type_name,const char *,(enum prop_type type)); + +/* expr.c */ +P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); +P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken)); diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c new file mode 100644 index 000000000000..730d316fe7fe --- /dev/null +++ b/scripts/kconfig/mconf.c @@ -0,0 +1,1090 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + * + * Introduced single menu mode (show all sub-menus in one large tree). + * 2002-11-06 Petr Baudis <pasky@ucw.cz> + */ + +#include <sys/ioctl.h> +#include <sys/wait.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <signal.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + +#define LKC_DIRECT_LINK +#include "lkc.h" + +static char menu_backtitle[128]; +static const char mconf_readme[] = +"Overview\n" +"--------\n" +"Some kernel features may be built directly into the kernel.\n" +"Some may be made into loadable runtime modules.  Some features\n" +"may be completely removed altogether.  There are also certain\n" +"kernel parameters which are not really features, but must be\n" +"entered in as decimal or hexadecimal numbers or possibly text.\n" +"\n" +"Menu items beginning with [*], <M> or [ ] represent features\n" +"configured to be built in, modularized or removed respectively.\n" +"Pointed brackets <> represent module capable features.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press <Y> to build it in, <M> to make it a module or\n" +"<N> to removed it.  You may also press the <Space Bar> to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o  Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +"   you wish to change or submenu wish to select and press <Enter>.\n" +"   Submenus are designated by \"--->\".\n" +"\n" +"   Shortcut: Press the option's highlighted letter (hotkey).\n" +"             Pressing a hotkey more than once will sequence\n" +"             through all visible items which use that hotkey.\n" +"\n" +"   You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n" +"   unseen options into view.\n" +"\n" +"o  To exit a menu use the cursor keys to highlight the <Exit> button\n" +"   and press <ENTER>.\n" +"\n" +"   Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n" +"             using those letters.  You may press a single <ESC>, but\n" +"             there is a delayed response which you may find annoying.\n" +"\n" +"   Also, the <TAB> and cursor keys will cycle between <Select>,\n" +"   <Exit> and <Help>\n" +"\n" +"o  To get help with an item, use the cursor keys to highlight <Help>\n" +"   and Press <ENTER>.\n" +"\n" +"   Shortcut: Press <H> or <?>.\n" +"\n" +"\n" +"Radiolists  (Choice lists)\n" +"-----------\n" +"o  Use the cursor keys to select the option you wish to set and press\n" +"   <S> or the <SPACE BAR>.\n" +"\n" +"   Shortcut: Press the first letter of the option you wish to set then\n" +"             press <S> or <SPACE BAR>.\n" +"\n" +"o  To see available help for the item, use the cursor keys to highlight\n" +"   <Help> and Press <ENTER>.\n" +"\n" +"   Shortcut: Press <H> or <?>.\n" +"\n" +"   Also, the <TAB> and cursor keys will cycle between <Select> and\n" +"   <Help>\n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o  Enter the requested information and press <ENTER>\n" +"   If you are entering hexadecimal values, it is not necessary to\n" +"   add the '0x' prefix to the entry.\n" +"\n" +"o  For help, use the <TAB> or cursor keys to highlight the help option\n" +"   and press <ENTER>.  You can try <TAB><H> as well.\n" +"\n" +"\n" +"Text Box    (Help Window)\n" +"--------\n" +"o  Use the cursor keys to scroll up/down/left/right.  The VI editor\n" +"   keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n" +"   who are familiar with less and lynx.\n" +"\n" +"o  Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"Menuconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different kernel configurations.\n" +"\n" +"At the end of the main menu you will find two options.  One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a Menuconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting Menuconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use Menuconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, Menuconfig will look rather bad.  Menuconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"Menuconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry.  I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment.  Some distributions\n" +"export those variables via /etc/profile.  Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the kernel options listed in a single\n" +"menu, rather than the default multimenu hierarchy, run the menuconfig\n" +"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make MENUCONFIG_MODE=single_menu menuconfig\n" +"\n" +"<Enter> will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n", +menu_instructions[] = +	"Arrow keys navigate the menu.  " +	"<Enter> selects submenus --->.  " +	"Highlighted letters are hotkeys.  " +	"Pressing <Y> includes, <N> excludes, <M> modularizes features.  " +	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  " +	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable", +radiolist_instructions[] = +	"Use the arrow keys to navigate this window or " +	"press the hotkey of the item you wish to select " +	"followed by the <SPACE BAR>. " +	"Press <?> for additional information about this option.", +inputbox_instructions_int[] = +	"Please enter a decimal value. " +	"Fractions will not be accepted.  " +	"Use the <TAB> key to move from the input field to the buttons below it.", +inputbox_instructions_hex[] = +	"Please enter a hexadecimal value. " +	"Use the <TAB> key to move from the input field to the buttons below it.", +inputbox_instructions_string[] = +	"Please enter a string value. " +	"Use the <TAB> key to move from the input field to the buttons below it.", +setmod_text[] = +	"This feature depends on another which has been configured as a module.\n" +	"As a result, this feature will be built as a module.", +nohelp_text[] = +	"There is no help available for this kernel option.\n", +load_config_text[] = +	"Enter the name of the configuration file you wish to load.  " +	"Accept the name shown to restore the configuration you " +	"last retrieved.  Leave blank to abort.", +load_config_help[] = +	"\n" +	"For various reasons, one may wish to keep several different kernel\n" +	"configurations available on a single machine.\n" +	"\n" +	"If you have saved a previous configuration in a file other than the\n" +	"kernel's default, entering the name of the file here will allow you\n" +	"to modify that configuration.\n" +	"\n" +	"If you are uncertain, then you have probably never used alternate\n" +	"configuration files.  You should therefor leave this blank to abort.\n", +save_config_text[] = +	"Enter a filename to which this configuration should be saved " +	"as an alternate.  Leave blank to abort.", +save_config_help[] = +	"\n" +	"For various reasons, one may wish to keep different kernel\n" +	"configurations available on a single machine.\n" +	"\n" +	"Entering a file name here will allow you to later retrieve, modify\n" +	"and use the current configuration as an alternate to whatever\n" +	"configuration options you have selected at that time.\n" +	"\n" +	"If you are uncertain what all this means then you should probably\n" +	"leave this blank.\n", +search_help[] = +	"\n" +	"Search for CONFIG_ symbols and display their relations.\n" +	"Example: search for \"^FOO\"\n" +	"Result:\n" +	"-----------------------------------------------------------------\n" +	"Symbol: FOO [=m]\n" +	"Prompt: Foo bus is used to drive the bar HW\n" +	"Defined at drivers/pci/Kconfig:47\n" +	"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" +	"Location:\n" +	"  -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" +	"    -> PCI support (PCI [=y])\n" +	"      -> PCI access mode (<choice> [=y])\n" +	"Selects: LIBCRC32\n" +	"Selected by: BAR\n" +	"-----------------------------------------------------------------\n" +	"o The line 'Prompt:' shows the text used in the menu structure for\n" +	"  this CONFIG_ symbol\n" +	"o The 'Defined at' line tell at what file / line number the symbol\n" +	"  is defined\n" +	"o The 'Depends on:' line tell what symbols needs to be defined for\n" +	"  this symbol to be visible in the menu (selectable)\n" +	"o The 'Location:' lines tell where in the menu structure this symbol\n" +	"  is located\n" +	"    A location followed by a [=y] indicate that this is a selectable\n" +	"    menu item - and current value is displayed inside brackets.\n" +	"o The 'Selects:' line tell what symbol will be automatically\n" +	"  selected if this symbol is selected (y or m)\n" +	"o The 'Selected by' line tell what symbol has selected this symbol\n" +	"\n" +	"Only relevant lines are shown.\n" +	"\n\n" +	"Search examples:\n" +	"Examples: USB	=> find all CONFIG_ symbols containing USB\n" +	"          ^USB => find all CONFIG_ symbols starting with USB\n" +	"          USB$ => find all CONFIG_ symbols ending with USB\n" +	"\n"; + +static signed char buf[4096], *bufptr = buf; +static signed char input_buf[4096]; +static char filename[PATH_MAX+1] = ".config"; +static char *args[1024], **argptr = args; +static int indent; +static struct termios ios_org; +static int rows = 0, cols = 0; +static struct menu *current_menu; +static int child_count; +static int do_resize; +static int single_menu_mode; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_textbox(const char *title, const char *text, int r, int c); +static void show_helptext(const char *title, const char *text); +static void show_help(struct menu *menu); +static void show_file(const char *filename, const char *title, int r, int c); + +static void cprint_init(void); +static int cprint1(const char *fmt, ...); +static void cprint_done(void); +static int cprint(const char *fmt, ...); + +static void init_wsize(void) +{ +	struct winsize ws; +	char *env; + +	if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) { +		rows = ws.ws_row; +		cols = ws.ws_col; +	} + +	if (!rows) { +		env = getenv("LINES"); +		if (env) +			rows = atoi(env); +		if (!rows) +			rows = 24; +	} +	if (!cols) { +		env = getenv("COLUMNS"); +		if (env) +			cols = atoi(env); +		if (!cols) +			cols = 80; +	} + +	if (rows < 19 || cols < 80) { +		fprintf(stderr, "Your display is too small to run Menuconfig!\n"); +		fprintf(stderr, "It must be at least 19 lines by 80 columns.\n"); +		exit(1); +	} + +	rows -= 4; +	cols -= 5; +} + +static void cprint_init(void) +{ +	bufptr = buf; +	argptr = args; +	memset(args, 0, sizeof(args)); +	indent = 0; +	child_count = 0; +	cprint("./scripts/lxdialog/lxdialog"); +	cprint("--backtitle"); +	cprint(menu_backtitle); +} + +static int cprint1(const char *fmt, ...) +{ +	va_list ap; +	int res; + +	if (!*argptr) +		*argptr = bufptr; +	va_start(ap, fmt); +	res = vsprintf(bufptr, fmt, ap); +	va_end(ap); +	bufptr += res; + +	return res; +} + +static void cprint_done(void) +{ +	*bufptr++ = 0; +	argptr++; +} + +static int cprint(const char *fmt, ...) +{ +	va_list ap; +	int res; + +	*argptr++ = bufptr; +	va_start(ap, fmt); +	res = vsprintf(bufptr, fmt, ap); +	va_end(ap); +	bufptr += res; +	*bufptr++ = 0; + +	return res; +} + +static void get_prompt_str(struct gstr *r, struct property *prop) +{ +	int i, j; +	struct menu *submenu[8], *menu; + +	str_printf(r, "Prompt: %s\n", prop->text); +	str_printf(r, "  Defined at %s:%d\n", prop->menu->file->name, +		prop->menu->lineno); +	if (!expr_is_yes(prop->visible.expr)) { +		str_append(r, "  Depends on: "); +		expr_gstr_print(prop->visible.expr, r); +		str_append(r, "\n"); +	} +	menu = prop->menu->parent; +	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) +		submenu[i++] = menu; +	if (i > 0) { +		str_printf(r, "  Location:\n"); +		for (j = 4; --i >= 0; j += 2) { +			menu = submenu[i]; +			str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu)); +			if (menu->sym) { +				str_printf(r, " (%s [=%s])", menu->sym->name ? +					menu->sym->name : "<choice>", +					sym_get_string_value(menu->sym)); +			} +			str_append(r, "\n"); +		} +	} +} + +static void get_symbol_str(struct gstr *r, struct symbol *sym) +{ +	bool hit; +	struct property *prop; + +	str_printf(r, "Symbol: %s [=%s]\n", sym->name, +	                               sym_get_string_value(sym)); +	for_all_prompts(sym, prop) +		get_prompt_str(r, prop); +	hit = false; +	for_all_properties(sym, prop, P_SELECT) { +		if (!hit) { +			str_append(r, "  Selects: "); +			hit = true; +		} else +			str_printf(r, " && "); +		expr_gstr_print(prop->expr, r); +	} +	if (hit) +		str_append(r, "\n"); +	if (sym->rev_dep.expr) { +		str_append(r, "  Selected by: "); +		expr_gstr_print(sym->rev_dep.expr, r); +		str_append(r, "\n"); +	} +	str_append(r, "\n\n"); +} + +static struct gstr get_relations_str(struct symbol **sym_arr) +{ +	struct symbol *sym; +	struct gstr res = str_new(); +	int i; + +	for (i = 0; sym_arr && (sym = sym_arr[i]); i++) +		get_symbol_str(&res, sym); +	if (!i) +		str_append(&res, "No matches found.\n"); +	return res; +} + +pid_t pid; + +static void winch_handler(int sig) +{ +	if (!do_resize) { +		kill(pid, SIGINT); +		do_resize = 1; +	} +} + +static int exec_conf(void) +{ +	int pipefd[2], stat, size; +	struct sigaction sa; +	sigset_t sset, osset; + +	sigemptyset(&sset); +	sigaddset(&sset, SIGINT); +	sigprocmask(SIG_BLOCK, &sset, &osset); + +	signal(SIGINT, SIG_DFL); + +	sa.sa_handler = winch_handler; +	sigemptyset(&sa.sa_mask); +	sa.sa_flags = SA_RESTART; +	sigaction(SIGWINCH, &sa, NULL); + +	*argptr++ = NULL; + +	pipe(pipefd); +	pid = fork(); +	if (pid == 0) { +		sigprocmask(SIG_SETMASK, &osset, NULL); +		dup2(pipefd[1], 2); +		close(pipefd[0]); +		close(pipefd[1]); +		execv(args[0], args); +		_exit(EXIT_FAILURE); +	} + +	close(pipefd[1]); +	bufptr = input_buf; +	while (1) { +		size = input_buf + sizeof(input_buf) - bufptr; +		size = read(pipefd[0], bufptr, size); +		if (size <= 0) { +			if (size < 0) { +				if (errno == EINTR || errno == EAGAIN) +					continue; +				perror("read"); +			} +			break; +		} +		bufptr += size; +	} +	*bufptr++ = 0; +	close(pipefd[0]); +	waitpid(pid, &stat, 0); + +	if (do_resize) { +		init_wsize(); +		do_resize = 0; +		sigprocmask(SIG_SETMASK, &osset, NULL); +		return -1; +	} +	if (WIFSIGNALED(stat)) { +		printf("\finterrupted(%d)\n", WTERMSIG(stat)); +		exit(1); +	} +#if 0 +	printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf); +	sleep(1); +#endif +	sigpending(&sset); +	if (sigismember(&sset, SIGINT)) { +		printf("\finterrupted\n"); +		exit(1); +	} +	sigprocmask(SIG_SETMASK, &osset, NULL); + +	return WEXITSTATUS(stat); +} + +static void search_conf(void) +{ +	struct symbol **sym_arr; +	int stat; +	struct gstr res; + +again: +	cprint_init(); +	cprint("--title"); +	cprint("Search Configuration Parameter"); +	cprint("--inputbox"); +	cprint("Enter Keyword"); +	cprint("10"); +	cprint("75"); +	cprint(""); +	stat = exec_conf(); +	if (stat < 0) +		goto again; +	switch (stat) { +	case 0: +		break; +	case 1: +		show_helptext("Search Configuration", search_help); +		goto again; +	default: +		return; +	} + +	sym_arr = sym_re_search(input_buf); +	res = get_relations_str(sym_arr); +	free(sym_arr); +	show_textbox("Search Results", str_get(&res), 0, 0); +	str_free(&res); +} + +static void build_conf(struct menu *menu) +{ +	struct symbol *sym; +	struct property *prop; +	struct menu *child; +	int type, tmp, doint = 2; +	tristate val; +	char ch; + +	if (!menu_is_visible(menu)) +		return; + +	sym = menu->sym; +	prop = menu->prompt; +	if (!sym) { +		if (prop && menu != current_menu) { +			const char *prompt = menu_get_prompt(menu); +			switch (prop->type) { +			case P_MENU: +				child_count++; +				cprint("m%p", menu); + +				if (single_menu_mode) { +					cprint1("%s%*c%s", +						menu->data ? "-->" : "++>", +						indent + 1, ' ', prompt); +				} else +					cprint1("   %*c%s  --->", indent + 1, ' ', prompt); + +				cprint_done(); +				if (single_menu_mode && menu->data) +					goto conf_childs; +				return; +			default: +				if (prompt) { +					child_count++; +					cprint(":%p", menu); +					cprint("---%*c%s", indent + 1, ' ', prompt); +				} +			} +		} else +			doint = 0; +		goto conf_childs; +	} + +	type = sym_get_type(sym); +	if (sym_is_choice(sym)) { +		struct symbol *def_sym = sym_get_choice_value(sym); +		struct menu *def_menu = NULL; + +		child_count++; +		for (child = menu->list; child; child = child->next) { +			if (menu_is_visible(child) && child->sym == def_sym) +				def_menu = child; +		} + +		val = sym_get_tristate_value(sym); +		if (sym_is_changable(sym)) { +			cprint("t%p", menu); +			switch (type) { +			case S_BOOLEAN: +				cprint1("[%c]", val == no ? ' ' : '*'); +				break; +			case S_TRISTATE: +				switch (val) { +				case yes: ch = '*'; break; +				case mod: ch = 'M'; break; +				default:  ch = ' '; break; +				} +				cprint1("<%c>", ch); +				break; +			} +		} else { +			cprint("%c%p", def_menu ? 't' : ':', menu); +			cprint1("   "); +		} + +		cprint1("%*c%s", indent + 1, ' ', menu_get_prompt(menu)); +		if (val == yes) { +			if (def_menu) { +				cprint1(" (%s)", menu_get_prompt(def_menu)); +				cprint1("  --->"); +				cprint_done(); +				if (def_menu->list) { +					indent += 2; +					build_conf(def_menu); +					indent -= 2; +				} +			} else +				cprint_done(); +			return; +		} +		cprint_done(); +	} else { +		if (menu == current_menu) { +			cprint(":%p", menu); +			cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu)); +			goto conf_childs; +		} +		child_count++; +		val = sym_get_tristate_value(sym); +		if (sym_is_choice_value(sym) && val == yes) { +			cprint(":%p", menu); +			cprint1("   "); +		} else { +			switch (type) { +			case S_BOOLEAN: +				cprint("t%p", menu); +				if (sym_is_changable(sym)) +					cprint1("[%c]", val == no ? ' ' : '*'); +				else +					cprint1("---"); +				break; +			case S_TRISTATE: +				cprint("t%p", menu); +				switch (val) { +				case yes: ch = '*'; break; +				case mod: ch = 'M'; break; +				default:  ch = ' '; break; +				} +				if (sym_is_changable(sym)) +					cprint1("<%c>", ch); +				else +					cprint1("---"); +				break; +			default: +				cprint("s%p", menu); +				tmp = cprint1("(%s)", sym_get_string_value(sym)); +				tmp = indent - tmp + 4; +				if (tmp < 0) +					tmp = 0; +				cprint1("%*c%s%s", tmp, ' ', menu_get_prompt(menu), +					(sym_has_value(sym) || !sym_is_changable(sym)) ? +					"" : " (NEW)"); +				cprint_done(); +				goto conf_childs; +			} +		} +		cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), +			(sym_has_value(sym) || !sym_is_changable(sym)) ? +			"" : " (NEW)"); +		if (menu->prompt->type == P_MENU) { +			cprint1("  --->"); +			cprint_done(); +			return; +		} +		cprint_done(); +	} + +conf_childs: +	indent += doint; +	for (child = menu->list; child; child = child->next) +		build_conf(child); +	indent -= doint; +} + +static void conf(struct menu *menu) +{ +	struct menu *submenu; +	const char *prompt = menu_get_prompt(menu); +	struct symbol *sym; +	char active_entry[40]; +	int stat, type, i; + +	unlink("lxdialog.scrltmp"); +	active_entry[0] = 0; +	while (1) { +		cprint_init(); +		cprint("--title"); +		cprint("%s", prompt ? prompt : "Main Menu"); +		cprint("--menu"); +		cprint(menu_instructions); +		cprint("%d", rows); +		cprint("%d", cols); +		cprint("%d", rows - 10); +		cprint("%s", active_entry); +		current_menu = menu; +		build_conf(menu); +		if (!child_count) +			break; +		if (menu == &rootmenu) { +			cprint(":"); +			cprint("--- "); +			cprint("L"); +			cprint("    Load an Alternate Configuration File"); +			cprint("S"); +			cprint("    Save Configuration to an Alternate File"); +		} +		stat = exec_conf(); +		if (stat < 0) +			continue; + +		if (stat == 1 || stat == 255) +			break; + +		type = input_buf[0]; +		if (!type) +			continue; + +		for (i = 0; input_buf[i] && !isspace(input_buf[i]); i++) +			; +		if (i >= sizeof(active_entry)) +			i = sizeof(active_entry) - 1; +		input_buf[i] = 0; +		strcpy(active_entry, input_buf); + +		sym = NULL; +		submenu = NULL; +		if (sscanf(input_buf + 1, "%p", &submenu) == 1) +			sym = submenu->sym; + +		switch (stat) { +		case 0: +			switch (type) { +			case 'm': +				if (single_menu_mode) +					submenu->data = (void *) (long) !submenu->data; +				else +					conf(submenu); +				break; +			case 't': +				if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) +					conf_choice(submenu); +				else if (submenu->prompt->type == P_MENU) +					conf(submenu); +				break; +			case 's': +				conf_string(submenu); +				break; +			case 'L': +				conf_load(); +				break; +			case 'S': +				conf_save(); +				break; +			} +			break; +		case 2: +			if (sym) +				show_help(submenu); +			else +				show_helptext("README", mconf_readme); +			break; +		case 3: +			if (type == 't') { +				if (sym_set_tristate_value(sym, yes)) +					break; +				if (sym_set_tristate_value(sym, mod)) +					show_textbox(NULL, setmod_text, 6, 74); +			} +			break; +		case 4: +			if (type == 't') +				sym_set_tristate_value(sym, no); +			break; +		case 5: +			if (type == 't') +				sym_set_tristate_value(sym, mod); +			break; +		case 6: +			if (type == 't') +				sym_toggle_tristate_value(sym); +			else if (type == 'm') +				conf(submenu); +			break; +		case 7: +			search_conf(); +			break; +		} +	} +} + +static void show_textbox(const char *title, const char *text, int r, int c) +{ +	int fd; + +	fd = creat(".help.tmp", 0777); +	write(fd, text, strlen(text)); +	close(fd); +	show_file(".help.tmp", title, r, c); +	unlink(".help.tmp"); +} + +static void show_helptext(const char *title, const char *text) +{ +	show_textbox(title, text, 0, 0); +} + +static void show_help(struct menu *menu) +{ +	struct gstr help = str_new(); +	struct symbol *sym = menu->sym; + +	if (sym->help) +	{ +		if (sym->name) { +			str_printf(&help, "CONFIG_%s:\n\n", sym->name); +			str_append(&help, sym->help); +			str_append(&help, "\n"); +		} +	} else { +		str_append(&help, nohelp_text); +	} +	get_symbol_str(&help, sym); +	show_helptext(menu_get_prompt(menu), str_get(&help)); +	str_free(&help); +} + +static void show_file(const char *filename, const char *title, int r, int c) +{ +	do { +		cprint_init(); +		if (title) { +			cprint("--title"); +			cprint("%s", title); +		} +		cprint("--textbox"); +		cprint("%s", filename); +		cprint("%d", r ? r : rows); +		cprint("%d", c ? c : cols); +	} while (exec_conf() < 0); +} + +static void conf_choice(struct menu *menu) +{ +	const char *prompt = menu_get_prompt(menu); +	struct menu *child; +	struct symbol *active; +	int stat; + +	active = sym_get_choice_value(menu->sym); +	while (1) { +		cprint_init(); +		cprint("--title"); +		cprint("%s", prompt ? prompt : "Main Menu"); +		cprint("--radiolist"); +		cprint(radiolist_instructions); +		cprint("15"); +		cprint("70"); +		cprint("6"); + +		current_menu = menu; +		for (child = menu->list; child; child = child->next) { +			if (!menu_is_visible(child)) +				continue; +			cprint("%p", child); +			cprint("%s", menu_get_prompt(child)); +			if (child->sym == sym_get_choice_value(menu->sym)) +				cprint("ON"); +			else if (child->sym == active) +				cprint("SELECTED"); +			else +				cprint("OFF"); +		} + +		stat = exec_conf(); +		switch (stat) { +		case 0: +			if (sscanf(input_buf, "%p", &child) != 1) +				break; +			sym_set_tristate_value(child->sym, yes); +			return; +		case 1: +			if (sscanf(input_buf, "%p", &child) == 1) { +				show_help(child); +				active = child->sym; +			} else +				show_help(menu); +			break; +		case 255: +			return; +		} +	} +} + +static void conf_string(struct menu *menu) +{ +	const char *prompt = menu_get_prompt(menu); +	int stat; + +	while (1) { +		cprint_init(); +		cprint("--title"); +		cprint("%s", prompt ? prompt : "Main Menu"); +		cprint("--inputbox"); +		switch (sym_get_type(menu->sym)) { +		case S_INT: +			cprint(inputbox_instructions_int); +			break; +		case S_HEX: +			cprint(inputbox_instructions_hex); +			break; +		case S_STRING: +			cprint(inputbox_instructions_string); +			break; +		default: +			/* panic? */; +		} +		cprint("10"); +		cprint("75"); +		cprint("%s", sym_get_string_value(menu->sym)); +		stat = exec_conf(); +		switch (stat) { +		case 0: +			if (sym_set_string_value(menu->sym, input_buf)) +				return; +			show_textbox(NULL, "You have made an invalid entry.", 5, 43); +			break; +		case 1: +			show_help(menu); +			break; +		case 255: +			return; +		} +	} +} + +static void conf_load(void) +{ +	int stat; + +	while (1) { +		cprint_init(); +		cprint("--inputbox"); +		cprint(load_config_text); +		cprint("11"); +		cprint("55"); +		cprint("%s", filename); +		stat = exec_conf(); +		switch(stat) { +		case 0: +			if (!input_buf[0]) +				return; +			if (!conf_read(input_buf)) +				return; +			show_textbox(NULL, "File does not exist!", 5, 38); +			break; +		case 1: +			show_helptext("Load Alternate Configuration", load_config_help); +			break; +		case 255: +			return; +		} +	} +} + +static void conf_save(void) +{ +	int stat; + +	while (1) { +		cprint_init(); +		cprint("--inputbox"); +		cprint(save_config_text); +		cprint("11"); +		cprint("55"); +		cprint("%s", filename); +		stat = exec_conf(); +		switch(stat) { +		case 0: +			if (!input_buf[0]) +				return; +			if (!conf_write(input_buf)) +				return; +			show_textbox(NULL, "Can't create file!  Probably a nonexistent directory.", 5, 60); +			break; +		case 1: +			show_helptext("Save Alternate Configuration", save_config_help); +			break; +		case 255: +			return; +		} +	} +} + +static void conf_cleanup(void) +{ +	tcsetattr(1, TCSAFLUSH, &ios_org); +	unlink(".help.tmp"); +	unlink("lxdialog.scrltmp"); +} + +int main(int ac, char **av) +{ +	struct symbol *sym; +	char *mode; +	int stat; + +	conf_parse(av[1]); +	conf_read(NULL); + +	sym = sym_lookup("KERNELRELEASE", 0); +	sym_calc_value(sym); +	sprintf(menu_backtitle, "Linux Kernel v%s Configuration", +		sym_get_string_value(sym)); + +	mode = getenv("MENUCONFIG_MODE"); +	if (mode) { +		if (!strcasecmp(mode, "single_menu")) +			single_menu_mode = 1; +	} + +	tcgetattr(1, &ios_org); +	atexit(conf_cleanup); +	init_wsize(); +	conf(&rootmenu); + +	do { +		cprint_init(); +		cprint("--yesno"); +		cprint("Do you wish to save your new kernel configuration?"); +		cprint("5"); +		cprint("60"); +		stat = exec_conf(); +	} while (stat < 0); + +	if (stat == 0) { +		if (conf_write(NULL)) { +			fprintf(stderr, "\n\n" +				"Error during writing of the kernel configuration.\n" +				"Your kernel configuration changes were NOT saved." +				"\n\n"); +			return 1; +		} +		printf("\n\n" +			"*** End of Linux kernel configuration.\n" +			"*** Execute 'make' to build the kernel or try 'make help'." +			"\n\n"); +	} else { +		fprintf(stderr, "\n\n" +			"Your kernel configuration changes were NOT saved." +			"\n\n"); +	} + +	return 0; +} diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c new file mode 100644 index 000000000000..0c13156f3344 --- /dev/null +++ b/scripts/kconfig/menu.c @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <stdlib.h> +#include <string.h> + +#define LKC_DIRECT_LINK +#include "lkc.h" + +struct menu rootmenu; +static struct menu **last_entry_ptr; + +struct file *file_list; +struct file *current_file; + +static void menu_warn(struct menu *menu, const char *fmt, ...) +{ +	va_list ap; +	va_start(ap, fmt); +	fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); +	vfprintf(stderr, fmt, ap); +	fprintf(stderr, "\n"); +	va_end(ap); +} + +static void prop_warn(struct property *prop, const char *fmt, ...) +{ +	va_list ap; +	va_start(ap, fmt); +	fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); +	vfprintf(stderr, fmt, ap); +	fprintf(stderr, "\n"); +	va_end(ap); +} + +void menu_init(void) +{ +	current_entry = current_menu = &rootmenu; +	last_entry_ptr = &rootmenu.list; +} + +void menu_add_entry(struct symbol *sym) +{ +	struct menu *menu; + +	menu = malloc(sizeof(*menu)); +	memset(menu, 0, sizeof(*menu)); +	menu->sym = sym; +	menu->parent = current_menu; +	menu->file = current_file; +	menu->lineno = zconf_lineno(); + +	*last_entry_ptr = menu; +	last_entry_ptr = &menu->next; +	current_entry = menu; +} + +void menu_end_entry(void) +{ +} + +void menu_add_menu(void) +{ +	current_menu = current_entry; +	last_entry_ptr = ¤t_entry->list; +} + +void menu_end_menu(void) +{ +	last_entry_ptr = ¤t_menu->next; +	current_menu = current_menu->parent; +} + +struct expr *menu_check_dep(struct expr *e) +{ +	if (!e) +		return e; + +	switch (e->type) { +	case E_NOT: +		e->left.expr = menu_check_dep(e->left.expr); +		break; +	case E_OR: +	case E_AND: +		e->left.expr = menu_check_dep(e->left.expr); +		e->right.expr = menu_check_dep(e->right.expr); +		break; +	case E_SYMBOL: +		/* change 'm' into 'm' && MODULES */ +		if (e->left.sym == &symbol_mod) +			return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); +		break; +	default: +		break; +	} +	return e; +} + +void menu_add_dep(struct expr *dep) +{ +	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); +} + +void menu_set_type(int type) +{ +	struct symbol *sym = current_entry->sym; + +	if (sym->type == type) +		return; +	if (sym->type == S_UNKNOWN) { +		sym->type = type; +		return; +	} +	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n", +	    sym->name ? sym->name : "<choice>", +	    sym_type_name(sym->type), sym_type_name(type)); +} + +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) +{ +	struct property *prop = prop_alloc(type, current_entry->sym); + +	prop->menu = current_entry; +	prop->text = prompt; +	prop->expr = expr; +	prop->visible.expr = menu_check_dep(dep); + +	if (prompt) { +		if (current_entry->prompt) +			menu_warn(current_entry, "prompt redefined\n"); +		current_entry->prompt = prop; +	} + +	return prop; +} + +void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) +{ +	menu_add_prop(type, prompt, NULL, dep); +} + +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) +{ +	menu_add_prop(type, NULL, expr, dep); +} + +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) +{ +	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); +} + +void sym_check_prop(struct symbol *sym) +{ +	struct property *prop; +	struct symbol *sym2; +	for (prop = sym->prop; prop; prop = prop->next) { +		switch (prop->type) { +		case P_DEFAULT: +			if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && +			    prop->expr->type != E_SYMBOL) +				prop_warn(prop, +				    "default for config symbol '%'" +				    " must be a single symbol", sym->name); +			break; +		case P_SELECT: +			sym2 = prop_get_symbol(prop); +			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) +				prop_warn(prop, +				    "config symbol '%s' uses select, but is " +				    "not boolean or tristate", sym->name); +			else if (sym2->type == S_UNKNOWN) +				prop_warn(prop, +				    "'select' used by config symbol '%s' " +				    "refer to undefined symbol '%s'", +				    sym->name, sym2->name); +			else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE) +				prop_warn(prop, +				    "'%s' has wrong type. 'select' only " +				    "accept arguments of boolean and " +				    "tristate type", sym2->name); +			break; +		case P_RANGE: +			if (sym->type != S_INT && sym->type != S_HEX) +				prop_warn(prop, "range is only allowed " +				                "for int or hex symbols"); +			if (!sym_string_valid(sym, prop->expr->left.sym->name) || +			    !sym_string_valid(sym, prop->expr->right.sym->name)) +				prop_warn(prop, "range is invalid"); +			break; +		default: +			; +		} +	} +} + +void menu_finalize(struct menu *parent) +{ +	struct menu *menu, *last_menu; +	struct symbol *sym; +	struct property *prop; +	struct expr *parentdep, *basedep, *dep, *dep2, **ep; + +	sym = parent->sym; +	if (parent->list) { +		if (sym && sym_is_choice(sym)) { +			/* find the first choice value and find out choice type */ +			for (menu = parent->list; menu; menu = menu->next) { +				if (menu->sym) { +					current_entry = parent; +					menu_set_type(menu->sym->type); +					current_entry = menu; +					menu_set_type(sym->type); +					break; +				} +			} +			parentdep = expr_alloc_symbol(sym); +		} else if (parent->prompt) +			parentdep = parent->prompt->visible.expr; +		else +			parentdep = parent->dep; + +		for (menu = parent->list; menu; menu = menu->next) { +			basedep = expr_transform(menu->dep); +			basedep = expr_alloc_and(expr_copy(parentdep), basedep); +			basedep = expr_eliminate_dups(basedep); +			menu->dep = basedep; +			if (menu->sym) +				prop = menu->sym->prop; +			else +				prop = menu->prompt; +			for (; prop; prop = prop->next) { +				if (prop->menu != menu) +					continue; +				dep = expr_transform(prop->visible.expr); +				dep = expr_alloc_and(expr_copy(basedep), dep); +				dep = expr_eliminate_dups(dep); +				if (menu->sym && menu->sym->type != S_TRISTATE) +					dep = expr_trans_bool(dep); +				prop->visible.expr = dep; +				if (prop->type == P_SELECT) { +					struct symbol *es = prop_get_symbol(prop); +					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, +							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); +				} +			} +		} +		for (menu = parent->list; menu; menu = menu->next) +			menu_finalize(menu); +	} else if (sym) { +		basedep = parent->prompt ? parent->prompt->visible.expr : NULL; +		basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); +		basedep = expr_eliminate_dups(expr_transform(basedep)); +		last_menu = NULL; +		for (menu = parent->next; menu; menu = menu->next) { +			dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; +			if (!expr_contains_symbol(dep, sym)) +				break; +			if (expr_depends_symbol(dep, sym)) +				goto next; +			dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); +			dep = expr_eliminate_dups(expr_transform(dep)); +			dep2 = expr_copy(basedep); +			expr_eliminate_eq(&dep, &dep2); +			expr_free(dep); +			if (!expr_is_yes(dep2)) { +				expr_free(dep2); +				break; +			} +			expr_free(dep2); +		next: +			menu_finalize(menu); +			menu->parent = parent; +			last_menu = menu; +		} +		if (last_menu) { +			parent->list = parent->next; +			parent->next = last_menu->next; +			last_menu->next = NULL; +		} +	} +	for (menu = parent->list; menu; menu = menu->next) { +		if (sym && sym_is_choice(sym) && menu->sym) { +			menu->sym->flags |= SYMBOL_CHOICEVAL; +			if (!menu->prompt) +				menu_warn(menu, "choice value must have a prompt"); +			for (prop = menu->sym->prop; prop; prop = prop->next) { +				if (prop->type == P_PROMPT && prop->menu != menu) { +					prop_warn(prop, "choice values " +					    "currently only support a " +					    "single prompt"); +				} +				if (prop->type == P_DEFAULT) +					prop_warn(prop, "defaults for choice " +					    "values not supported"); +			} +			current_entry = menu; +			menu_set_type(sym->type); +			menu_add_symbol(P_CHOICE, sym, NULL); +			prop = sym_get_choice_prop(sym); +			for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) +				; +			*ep = expr_alloc_one(E_CHOICE, NULL); +			(*ep)->right.sym = menu->sym; +		} +		if (menu->list && (!menu->prompt || !menu->prompt->text)) { +			for (last_menu = menu->list; ; last_menu = last_menu->next) { +				last_menu->parent = parent; +				if (!last_menu->next) +					break; +			} +			last_menu->next = menu->next; +			menu->next = menu->list; +			menu->list = NULL; +		} +	} + +	if (sym && !(sym->flags & SYMBOL_WARNED)) { +		if (sym->type == S_UNKNOWN) +			menu_warn(parent, "config symbol defined " +			    "without type\n"); + +		if (sym_is_choice(sym) && !parent->prompt) +			menu_warn(parent, "choice must have a prompt\n"); + +		/* Check properties connected to this symbol */ +		sym_check_prop(sym); +		sym->flags |= SYMBOL_WARNED; +	} + +	if (sym && !sym_is_optional(sym) && parent->prompt) { +		sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, +				expr_alloc_and(parent->prompt->visible.expr, +					expr_alloc_symbol(&symbol_mod))); +	} +} + +bool menu_is_visible(struct menu *menu) +{ +	struct menu *child; +	struct symbol *sym; +	tristate visible; + +	if (!menu->prompt) +		return false; +	sym = menu->sym; +	if (sym) { +		sym_calc_value(sym); +		visible = menu->prompt->visible.tri; +	} else +		visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); + +	if (visible != no) +		return true; +	if (!sym || sym_get_tristate_value(menu->sym) == no) +		return false; + +	for (child = menu->list; child; child = child->next) +		if (menu_is_visible(child)) +			return true; +	return false; +} + +const char *menu_get_prompt(struct menu *menu) +{ +	if (menu->prompt) +		return menu->prompt->text; +	else if (menu->sym) +		return menu->sym->name; +	return NULL; +} + +struct menu *menu_get_root_menu(struct menu *menu) +{ +	return &rootmenu; +} + +struct menu *menu_get_parent_menu(struct menu *menu) +{ +	enum prop_type type; + +	for (; menu != &rootmenu; menu = menu->parent) { +		type = menu->prompt ? menu->prompt->type : 0; +		if (type == P_MENU) +			break; +	} +	return menu; +} + diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc new file mode 100644 index 000000000000..0cdbf9dbbd51 --- /dev/null +++ b/scripts/kconfig/qconf.cc @@ -0,0 +1,1407 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <qapplication.h> +#include <qmainwindow.h> +#include <qtoolbar.h> +#include <qvbox.h> +#include <qsplitter.h> +#include <qlistview.h> +#include <qtextview.h> +#include <qlineedit.h> +#include <qmenubar.h> +#include <qmessagebox.h> +#include <qaction.h> +#include <qheader.h> +#include <qfiledialog.h> +#include <qregexp.h> + +#include <stdlib.h> + +#include "lkc.h" +#include "qconf.h" + +#include "qconf.moc" +#include "images.c" + +static QApplication *configApp; + +ConfigSettings::ConfigSettings() +	: showAll(false), showName(false), showRange(false), showData(false) +{ +} + +#if QT_VERSION >= 300 +/** + * Reads the list column settings from the application settings. + */ +void ConfigSettings::readListSettings() +{ +	showAll = readBoolEntry("/kconfig/qconf/showAll", false); +	showName = readBoolEntry("/kconfig/qconf/showName", false); +	showRange = readBoolEntry("/kconfig/qconf/showRange", false); +	showData = readBoolEntry("/kconfig/qconf/showData", false); +} + +/** + * Reads a list of integer values from the application settings. + */ +QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok) +{ +	QValueList<int> result; +	QStringList entryList = readListEntry(key, ok); +	if (ok) { +		QStringList::Iterator it; +		for (it = entryList.begin(); it != entryList.end(); ++it) +			result.push_back((*it).toInt()); +	} + +	return result; +} + +/** + * Writes a list of integer values to the application settings. + */ +bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value) +{ +	QStringList stringList; +	QValueList<int>::ConstIterator it; + +	for (it = value.begin(); it != value.end(); ++it) +		stringList.push_back(QString::number(*it)); +	return writeEntry(key, stringList); +} +#endif + + +/* + * update all the children of a menu entry + *   removes/adds the entries from the parent widget as necessary + * + * parent: either the menu list widget or a menu entry widget + * menu: entry to be updated + */ +template <class P> +void ConfigList::updateMenuList(P* parent, struct menu* menu) +{ +	struct menu* child; +	ConfigItem* item; +	ConfigItem* last; +	bool visible; +	enum prop_type type; + +	if (!menu) { +		while ((item = parent->firstChild())) +			delete item; +		return; +	} + +	last = parent->firstChild(); +	if (last && !last->goParent) +		last = 0; +	for (child = menu->list; child; child = child->next) { +		item = last ? last->nextSibling() : parent->firstChild(); +		type = child->prompt ? child->prompt->type : P_UNKNOWN; + +		switch (mode) { +		case menuMode: +			if (!(child->flags & MENU_ROOT)) +				goto hide; +			break; +		case symbolMode: +			if (child->flags & MENU_ROOT) +				goto hide; +			break; +		default: +			break; +		} + +		visible = menu_is_visible(child); +		if (showAll || visible) { +			if (!item || item->menu != child) +				item = new ConfigItem(parent, last, child, visible); +			else +				item->testUpdateMenu(visible); + +			if (mode == fullMode || mode == menuMode || type != P_MENU) +				updateMenuList(item, child); +			else +				updateMenuList(item, 0); +			last = item; +			continue; +		} +	hide: +		if (item && item->menu == child) { +			last = parent->firstChild(); +			if (last == item) +				last = 0; +			else while (last->nextSibling() != item) +				last = last->nextSibling(); +			delete item; +		} +	} +} + +#if QT_VERSION >= 300 +/* + * set the new data + * TODO check the value + */ +void ConfigItem::okRename(int col) +{ +	Parent::okRename(col); +	sym_set_string_value(menu->sym, text(dataColIdx).latin1()); +} +#endif + +/* + * update the displayed of a menu entry + */ +void ConfigItem::updateMenu(void) +{ +	ConfigList* list; +	struct symbol* sym; +	struct property *prop; +	QString prompt; +	int type; +	tristate expr; + +	list = listView(); +	if (goParent) { +		setPixmap(promptColIdx, list->menuBackPix); +		prompt = ".."; +		goto set_prompt; +	} + +	sym = menu->sym; +	prop = menu->prompt; +	prompt = menu_get_prompt(menu); + +	if (prop) switch (prop->type) { +	case P_MENU: +		if (list->mode == singleMode || list->mode == symbolMode) { +			/* a menuconfig entry is displayed differently +			 * depending whether it's at the view root or a child. +			 */ +			if (sym && list->rootEntry == menu) +				break; +			setPixmap(promptColIdx, list->menuPix); +		} else { +			if (sym) +				break; +			setPixmap(promptColIdx, 0); +		} +		goto set_prompt; +	case P_COMMENT: +		setPixmap(promptColIdx, 0); +		goto set_prompt; +	default: +		; +	} +	if (!sym) +		goto set_prompt; + +	setText(nameColIdx, sym->name); + +	type = sym_get_type(sym); +	switch (type) { +	case S_BOOLEAN: +	case S_TRISTATE: +		char ch; + +		if (!sym_is_changable(sym) && !list->showAll) { +			setPixmap(promptColIdx, 0); +			setText(noColIdx, 0); +			setText(modColIdx, 0); +			setText(yesColIdx, 0); +			break; +		} +		expr = sym_get_tristate_value(sym); +		switch (expr) { +		case yes: +			if (sym_is_choice_value(sym) && type == S_BOOLEAN) +				setPixmap(promptColIdx, list->choiceYesPix); +			else +				setPixmap(promptColIdx, list->symbolYesPix); +			setText(yesColIdx, "Y"); +			ch = 'Y'; +			break; +		case mod: +			setPixmap(promptColIdx, list->symbolModPix); +			setText(modColIdx, "M"); +			ch = 'M'; +			break; +		default: +			if (sym_is_choice_value(sym) && type == S_BOOLEAN) +				setPixmap(promptColIdx, list->choiceNoPix); +			else +				setPixmap(promptColIdx, list->symbolNoPix); +			setText(noColIdx, "N"); +			ch = 'N'; +			break; +		} +		if (expr != no) +			setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); +		if (expr != mod) +			setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); +		if (expr != yes) +			setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); + +		setText(dataColIdx, QChar(ch)); +		break; +	case S_INT: +	case S_HEX: +	case S_STRING: +		const char* data; + +		data = sym_get_string_value(sym); +#if QT_VERSION >= 300 +		int i = list->mapIdx(dataColIdx); +		if (i >= 0) +			setRenameEnabled(i, TRUE); +#endif +		setText(dataColIdx, data); +		if (type == S_STRING) +			prompt.sprintf("%s: %s", prompt.latin1(), data); +		else +			prompt.sprintf("(%s) %s", data, prompt.latin1()); +		break; +	} +	if (!sym_has_value(sym) && visible) +		prompt += " (NEW)"; +set_prompt: +	setText(promptColIdx, prompt); +} + +void ConfigItem::testUpdateMenu(bool v) +{ +	ConfigItem* i; + +	visible = v; +	if (!menu) +		return; + +	sym_calc_value(menu->sym); +	if (menu->flags & MENU_CHANGED) { +		/* the menu entry changed, so update all list items */ +		menu->flags &= ~MENU_CHANGED; +		for (i = (ConfigItem*)menu->data; i; i = i->nextItem) +			i->updateMenu(); +	} else if (listView()->updateAll) +		updateMenu(); +} + +void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align) +{ +	ConfigList* list = listView(); + +	if (visible) { +		if (isSelected() && !list->hasFocus() && list->mode == menuMode) +			Parent::paintCell(p, list->inactivedColorGroup, column, width, align); +		else +			Parent::paintCell(p, cg, column, width, align); +	} else +		Parent::paintCell(p, list->disabledColorGroup, column, width, align); +} + +/* + * construct a menu entry + */ +void ConfigItem::init(void) +{ +	if (menu) { +		ConfigList* list = listView(); +		nextItem = (ConfigItem*)menu->data; +		menu->data = this; + +		if (list->mode != fullMode) +			setOpen(TRUE); +		sym_calc_value(menu->sym); +	} +	updateMenu(); +} + +/* + * destruct a menu entry + */ +ConfigItem::~ConfigItem(void) +{ +	if (menu) { +		ConfigItem** ip = (ConfigItem**)&menu->data; +		for (; *ip; ip = &(*ip)->nextItem) { +			if (*ip == this) { +				*ip = nextItem; +				break; +			} +		} +	} +} + +void ConfigLineEdit::show(ConfigItem* i) +{ +	item = i; +	if (sym_get_string_value(item->menu->sym)) +		setText(sym_get_string_value(item->menu->sym)); +	else +		setText(0); +	Parent::show(); +	setFocus(); +} + +void ConfigLineEdit::keyPressEvent(QKeyEvent* e) +{ +	switch (e->key()) { +	case Key_Escape: +		break; +	case Key_Return: +	case Key_Enter: +		sym_set_string_value(item->menu->sym, text().latin1()); +		parent()->updateList(item); +		break; +	default: +		Parent::keyPressEvent(e); +		return; +	} +	e->accept(); +	parent()->list->setFocus(); +	hide(); +} + +ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv, ConfigSettings* configSettings) +	: Parent(p), cview(cv), +	  updateAll(false), +	  symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), +	  choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), +	  menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), +	  showAll(false), showName(false), showRange(false), showData(false), +	  rootEntry(0) +{ +	int i; + +	setSorting(-1); +	setRootIsDecorated(TRUE); +	disabledColorGroup = palette().active(); +	disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text()); +	inactivedColorGroup = palette().active(); +	inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight()); + +	connect(this, SIGNAL(selectionChanged(void)), +		SLOT(updateSelection(void))); + +	if (configSettings) { +		showAll = configSettings->showAll; +		showName = configSettings->showName; +		showRange = configSettings->showRange; +		showData = configSettings->showData; +	} + +	for (i = 0; i < colNr; i++) +		colMap[i] = colRevMap[i] = -1; +	addColumn(promptColIdx, "Option"); + +	reinit(); +} + +void ConfigList::reinit(void) +{ +	removeColumn(dataColIdx); +	removeColumn(yesColIdx); +	removeColumn(modColIdx); +	removeColumn(noColIdx); +	removeColumn(nameColIdx); + +	if (showName) +		addColumn(nameColIdx, "Name"); +	if (showRange) { +		addColumn(noColIdx, "N"); +		addColumn(modColIdx, "M"); +		addColumn(yesColIdx, "Y"); +	} +	if (showData) +		addColumn(dataColIdx, "Value"); + +	updateListAll(); +} + +void ConfigList::updateSelection(void) +{ +	struct menu *menu; +	enum prop_type type; + +	ConfigItem* item = (ConfigItem*)selectedItem(); +	if (!item) +		return; + +	cview->setHelp(item); + +	menu = item->menu; +	if (!menu) +		return; +	type = menu->prompt ? menu->prompt->type : P_UNKNOWN; +	if (mode == menuMode && type == P_MENU) +		emit menuSelected(menu); +} + +void ConfigList::updateList(ConfigItem* item) +{ +	ConfigItem* last = 0; + +	if (!rootEntry) +		goto update; + +	if (rootEntry != &rootmenu && (mode == singleMode || +	    (mode == symbolMode && rootEntry->parent != &rootmenu))) { +		item = firstChild(); +		if (!item) +			item = new ConfigItem(this, 0, true); +		last = item; +	} +	if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && +	    rootEntry->sym && rootEntry->prompt) { +		item = last ? last->nextSibling() : firstChild(); +		if (!item) +			item = new ConfigItem(this, last, rootEntry, true); +		else +			item->testUpdateMenu(true); + +		updateMenuList(item, rootEntry); +		triggerUpdate(); +		return; +	} +update: +	updateMenuList(this, rootEntry); +	triggerUpdate(); +} + +void ConfigList::setAllOpen(bool open) +{ +	QListViewItemIterator it(this); + +	for (; it.current(); it++) +		it.current()->setOpen(open); +} + +void ConfigList::setValue(ConfigItem* item, tristate val) +{ +	struct symbol* sym; +	int type; +	tristate oldval; + +	sym = item->menu ? item->menu->sym : 0; +	if (!sym) +		return; + +	type = sym_get_type(sym); +	switch (type) { +	case S_BOOLEAN: +	case S_TRISTATE: +		oldval = sym_get_tristate_value(sym); + +		if (!sym_set_tristate_value(sym, val)) +			return; +		if (oldval == no && item->menu->list) +			item->setOpen(TRUE); +		parent()->updateList(item); +		break; +	} +} + +void ConfigList::changeValue(ConfigItem* item) +{ +	struct symbol* sym; +	struct menu* menu; +	int type, oldexpr, newexpr; + +	menu = item->menu; +	if (!menu) +		return; +	sym = menu->sym; +	if (!sym) { +		if (item->menu->list) +			item->setOpen(!item->isOpen()); +		return; +	} + +	type = sym_get_type(sym); +	switch (type) { +	case S_BOOLEAN: +	case S_TRISTATE: +		oldexpr = sym_get_tristate_value(sym); +		newexpr = sym_toggle_tristate_value(sym); +		if (item->menu->list) { +			if (oldexpr == newexpr) +				item->setOpen(!item->isOpen()); +			else if (oldexpr == no) +				item->setOpen(TRUE); +		} +		if (oldexpr != newexpr) +			parent()->updateList(item); +		break; +	case S_INT: +	case S_HEX: +	case S_STRING: +#if QT_VERSION >= 300 +		if (colMap[dataColIdx] >= 0) +			item->startRename(colMap[dataColIdx]); +		else +#endif +			parent()->lineEdit->show(item); +		break; +	} +} + +void ConfigList::setRootMenu(struct menu *menu) +{ +	enum prop_type type; + +	if (rootEntry == menu) +		return; +	type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; +	if (type != P_MENU) +		return; +	updateMenuList(this, 0); +	rootEntry = menu; +	updateListAll(); +	setSelected(currentItem(), hasFocus()); +} + +void ConfigList::setParentMenu(void) +{ +	ConfigItem* item; +	struct menu *oldroot; + +	oldroot = rootEntry; +	if (rootEntry == &rootmenu) +		return; +	setRootMenu(menu_get_parent_menu(rootEntry->parent)); + +	QListViewItemIterator it(this); +	for (; (item = (ConfigItem*)it.current()); it++) { +		if (item->menu == oldroot) { +			setCurrentItem(item); +			ensureItemVisible(item); +			break; +		} +	} +} + +void ConfigList::keyPressEvent(QKeyEvent* ev) +{ +	QListViewItem* i = currentItem(); +	ConfigItem* item; +	struct menu *menu; +	enum prop_type type; + +	if (ev->key() == Key_Escape && mode != fullMode) { +		emit parentSelected(); +		ev->accept(); +		return; +	} + +	if (!i) { +		Parent::keyPressEvent(ev); +		return; +	} +	item = (ConfigItem*)i; + +	switch (ev->key()) { +	case Key_Return: +	case Key_Enter: +		if (item->goParent) { +			emit parentSelected(); +			break; +		} +		menu = item->menu; +		if (!menu) +			break; +		type = menu->prompt ? menu->prompt->type : P_UNKNOWN; +		if (type == P_MENU && rootEntry != menu && +		    mode != fullMode && mode != menuMode) { +			emit menuSelected(menu); +			break; +		} +	case Key_Space: +		changeValue(item); +		break; +	case Key_N: +		setValue(item, no); +		break; +	case Key_M: +		setValue(item, mod); +		break; +	case Key_Y: +		setValue(item, yes); +		break; +	default: +		Parent::keyPressEvent(ev); +		return; +	} +	ev->accept(); +} + +void ConfigList::contentsMousePressEvent(QMouseEvent* e) +{ +	//QPoint p(contentsToViewport(e->pos())); +	//printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y()); +	Parent::contentsMousePressEvent(e); +} + +void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e) +{ +	QPoint p(contentsToViewport(e->pos())); +	ConfigItem* item = (ConfigItem*)itemAt(p); +	struct menu *menu; +	enum prop_type ptype; +	const QPixmap* pm; +	int idx, x; + +	if (!item) +		goto skip; + +	menu = item->menu; +	x = header()->offset() + p.x(); +	idx = colRevMap[header()->sectionAt(x)]; +	switch (idx) { +	case promptColIdx: +		pm = item->pixmap(promptColIdx); +		if (pm) { +			int off = header()->sectionPos(0) + itemMargin() + +				treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0)); +			if (x >= off && x < off + pm->width()) { +				if (item->goParent) { +					emit parentSelected(); +					break; +				} else if (!menu) +					break; +				ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; +				if (ptype == P_MENU && rootEntry != menu && +				    mode != fullMode && mode != menuMode) +					emit menuSelected(menu); +				else +					changeValue(item); +			} +		} +		break; +	case noColIdx: +		setValue(item, no); +		break; +	case modColIdx: +		setValue(item, mod); +		break; +	case yesColIdx: +		setValue(item, yes); +		break; +	case dataColIdx: +		changeValue(item); +		break; +	} + +skip: +	//printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); +	Parent::contentsMouseReleaseEvent(e); +} + +void ConfigList::contentsMouseMoveEvent(QMouseEvent* e) +{ +	//QPoint p(contentsToViewport(e->pos())); +	//printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y()); +	Parent::contentsMouseMoveEvent(e); +} + +void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e) +{ +	QPoint p(contentsToViewport(e->pos())); +	ConfigItem* item = (ConfigItem*)itemAt(p); +	struct menu *menu; +	enum prop_type ptype; + +	if (!item) +		goto skip; +	if (item->goParent) { +		emit parentSelected(); +		goto skip; +	} +	menu = item->menu; +	if (!menu) +		goto skip; +	ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; +	if (ptype == P_MENU && (mode == singleMode || mode == symbolMode)) +		emit menuSelected(menu); +	else if (menu->sym) +		changeValue(item); + +skip: +	//printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); +	Parent::contentsMouseDoubleClickEvent(e); +} + +void ConfigList::focusInEvent(QFocusEvent *e) +{ +	Parent::focusInEvent(e); + +	QListViewItem* item = currentItem(); +	if (!item) +		return; + +	setSelected(item, TRUE); +	emit gotFocus(); +} + +ConfigView* ConfigView::viewList; + +ConfigView::ConfigView(QWidget* parent, ConfigMainWindow* cview, +		       ConfigSettings *configSettings) +	: Parent(parent) +{ +	list = new ConfigList(this, cview, configSettings); +	lineEdit = new ConfigLineEdit(this); +	lineEdit->hide(); + +	this->nextView = viewList; +	viewList = this; +} + +ConfigView::~ConfigView(void) +{ +	ConfigView** vp; + +	for (vp = &viewList; *vp; vp = &(*vp)->nextView) { +		if (*vp == this) { +			*vp = nextView; +			break; +		} +	} +} + +void ConfigView::updateList(ConfigItem* item) +{ +	ConfigView* v; + +	for (v = viewList; v; v = v->nextView) +		v->list->updateList(item); +} + +void ConfigView::updateListAll(void) +{ +	ConfigView* v; + +	for (v = viewList; v; v = v->nextView) +		v->list->updateListAll(); +} + +/* + * Construct the complete config widget + */ +ConfigMainWindow::ConfigMainWindow(void) +{ +	QMenuBar* menu; +	bool ok; +	int x, y, width, height; + +	QWidget *d = configApp->desktop(); + +	ConfigSettings* configSettings = new ConfigSettings(); +#if QT_VERSION >= 300 +	width = configSettings->readNumEntry("/kconfig/qconf/window width", d->width() - 64); +	height = configSettings->readNumEntry("/kconfig/qconf/window height", d->height() - 64); +	resize(width, height); +	x = configSettings->readNumEntry("/kconfig/qconf/window x", 0, &ok); +	if (ok) +		y = configSettings->readNumEntry("/kconfig/qconf/window y", 0, &ok); +	if (ok) +		move(x, y); +	showDebug = configSettings->readBoolEntry("/kconfig/qconf/showDebug", false); + +	// read list settings into configSettings, will be used later for ConfigList setup +	configSettings->readListSettings(); +#else +	width = d->width() - 64; +	height = d->height() - 64; +	resize(width, height); +	showDebug = false; +#endif + +	split1 = new QSplitter(this); +	split1->setOrientation(QSplitter::Horizontal); +	setCentralWidget(split1); + +	menuView = new ConfigView(split1, this, configSettings); +	menuList = menuView->list; + +	split2 = new QSplitter(split1); +	split2->setOrientation(QSplitter::Vertical); + +	// create config tree +	configView = new ConfigView(split2, this, configSettings); +	configList = configView->list; + +	helpText = new QTextView(split2); +	helpText->setTextFormat(Qt::RichText); + +	setTabOrder(configList, helpText); +	configList->setFocus(); + +	menu = menuBar(); +	toolBar = new QToolBar("Tools", this); + +	backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this); +	  connect(backAction, SIGNAL(activated()), SLOT(goBack())); +	  backAction->setEnabled(FALSE); +	QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this); +	  connect(quitAction, SIGNAL(activated()), SLOT(close())); +	QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this); +	  connect(loadAction, SIGNAL(activated()), SLOT(loadConfig())); +	QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this); +	  connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); +	QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this); +	  connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); +	QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this); +	  connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); +	QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this); +	  connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView())); +	QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this); +	  connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView())); + +	QAction *showNameAction = new QAction(NULL, "Show Name", 0, this); +	  showNameAction->setToggleAction(TRUE); +	  showNameAction->setOn(configList->showName); +	  connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool))); +	QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this); +	  showRangeAction->setToggleAction(TRUE); +	  showRangeAction->setOn(configList->showRange); +	  connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool))); +	QAction *showDataAction = new QAction(NULL, "Show Data", 0, this); +	  showDataAction->setToggleAction(TRUE); +	  showDataAction->setOn(configList->showData); +	  connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool))); +	QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this); +	  showAllAction->setToggleAction(TRUE); +	  showAllAction->setOn(configList->showAll); +	  connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool))); +	QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this); +	  showDebugAction->setToggleAction(TRUE); +	  showDebugAction->setOn(showDebug); +	  connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); + +	QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this); +	  connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); +	QAction *showAboutAction = new QAction(NULL, "About", 0, this); +	  connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout())); + +	// init tool bar +	backAction->addTo(toolBar); +	toolBar->addSeparator(); +	loadAction->addTo(toolBar); +	saveAction->addTo(toolBar); +	toolBar->addSeparator(); +	singleViewAction->addTo(toolBar); +	splitViewAction->addTo(toolBar); +	fullViewAction->addTo(toolBar); + +	// create config menu +	QPopupMenu* config = new QPopupMenu(this); +	menu->insertItem("&File", config); +	loadAction->addTo(config); +	saveAction->addTo(config); +	saveAsAction->addTo(config); +	config->insertSeparator(); +	quitAction->addTo(config); + +	// create options menu +	QPopupMenu* optionMenu = new QPopupMenu(this); +	menu->insertItem("&Option", optionMenu); +	showNameAction->addTo(optionMenu); +	showRangeAction->addTo(optionMenu); +	showDataAction->addTo(optionMenu); +	optionMenu->insertSeparator(); +	showAllAction->addTo(optionMenu); +	showDebugAction->addTo(optionMenu); + +	// create help menu +	QPopupMenu* helpMenu = new QPopupMenu(this); +	menu->insertSeparator(); +	menu->insertItem("&Help", helpMenu); +	showIntroAction->addTo(helpMenu); +	showAboutAction->addTo(helpMenu); + +	connect(configList, SIGNAL(menuSelected(struct menu *)), +		SLOT(changeMenu(struct menu *))); +	connect(configList, SIGNAL(parentSelected()), +		SLOT(goBack())); +	connect(menuList, SIGNAL(menuSelected(struct menu *)), +		SLOT(changeMenu(struct menu *))); + +	connect(configList, SIGNAL(gotFocus(void)), +		SLOT(listFocusChanged(void))); +	connect(menuList, SIGNAL(gotFocus(void)), +		SLOT(listFocusChanged(void))); + +#if QT_VERSION >= 300 +	QString listMode = configSettings->readEntry("/kconfig/qconf/listMode", "symbol"); +	if (listMode == "single") +		showSingleView(); +	else if (listMode == "full") +		showFullView(); +	else /*if (listMode == "split")*/ +		showSplitView(); + +	// UI setup done, restore splitter positions +	QValueList<int> sizes = configSettings->readSizes("/kconfig/qconf/split1", &ok); +	if (ok) +		split1->setSizes(sizes); + +	sizes = configSettings->readSizes("/kconfig/qconf/split2", &ok); +	if (ok) +		split2->setSizes(sizes); +#else +	showSplitView(); +#endif +	delete configSettings; +} + +static QString print_filter(const char *str) +{ +	QRegExp re("[<>&\"\\n]"); +	QString res = str; +	for (int i = 0; (i = res.find(re, i)) >= 0;) { +		switch (res[i].latin1()) { +		case '<': +			res.replace(i, 1, "<"); +			i += 4; +			break; +		case '>': +			res.replace(i, 1, ">"); +			i += 4; +			break; +		case '&': +			res.replace(i, 1, "&"); +			i += 5; +			break; +		case '"': +			res.replace(i, 1, """); +			i += 6; +			break; +		case '\n': +			res.replace(i, 1, "<br>"); +			i += 4; +			break; +		} +	} +	return res; +} + +static void expr_print_help(void *data, const char *str) +{ +	((QString*)data)->append(print_filter(str)); +} + +/* + * display a new help entry as soon as a new menu entry is selected + */ +void ConfigMainWindow::setHelp(QListViewItem* item) +{ +	struct symbol* sym; +	struct menu* menu = 0; + +	configList->parent()->lineEdit->hide(); +	if (item) +		menu = ((ConfigItem*)item)->menu; +	if (!menu) { +		helpText->setText(NULL); +		return; +	} + +	QString head, debug, help; +	menu = ((ConfigItem*)item)->menu; +	sym = menu->sym; +	if (sym) { +		if (menu->prompt) { +			head += "<big><b>"; +			head += print_filter(menu->prompt->text); +			head += "</b></big>"; +			if (sym->name) { +				head += " ("; +				head += print_filter(sym->name); +				head += ")"; +			} +		} else if (sym->name) { +			head += "<big><b>"; +			head += print_filter(sym->name); +			head += "</b></big>"; +		} +		head += "<br><br>"; + +		if (showDebug) { +			debug += "type: "; +			debug += print_filter(sym_type_name(sym->type)); +			if (sym_is_choice(sym)) +				debug += " (choice)"; +			debug += "<br>"; +			if (sym->rev_dep.expr) { +				debug += "reverse dep: "; +				expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); +				debug += "<br>"; +			} +			for (struct property *prop = sym->prop; prop; prop = prop->next) { +				switch (prop->type) { +				case P_PROMPT: +				case P_MENU: +					debug += "prompt: "; +					debug += print_filter(prop->text); +					debug += "<br>"; +					break; +				case P_DEFAULT: +					debug += "default: "; +					expr_print(prop->expr, expr_print_help, &debug, E_NONE); +					debug += "<br>"; +					break; +				case P_CHOICE: +					if (sym_is_choice(sym)) { +						debug += "choice: "; +						expr_print(prop->expr, expr_print_help, &debug, E_NONE); +						debug += "<br>"; +					} +					break; +				case P_SELECT: +					debug += "select: "; +					expr_print(prop->expr, expr_print_help, &debug, E_NONE); +					debug += "<br>"; +					break; +				case P_RANGE: +					debug += "range: "; +					expr_print(prop->expr, expr_print_help, &debug, E_NONE); +					debug += "<br>"; +					break; +				default: +					debug += "unknown property: "; +					debug += prop_get_type_name(prop->type); +					debug += "<br>"; +				} +				if (prop->visible.expr) { +					debug += "    dep: "; +					expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); +					debug += "<br>"; +				} +			} +			debug += "<br>"; +		} + +		help = print_filter(sym->help); +	} else if (menu->prompt) { +		head += "<big><b>"; +		head += print_filter(menu->prompt->text); +		head += "</b></big><br><br>"; +		if (showDebug) { +			if (menu->prompt->visible.expr) { +				debug += "  dep: "; +				expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); +				debug += "<br><br>"; +			} +		} +	} +	if (showDebug) +		debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno); +	helpText->setText(head + debug + help); +} + +void ConfigMainWindow::loadConfig(void) +{ +	QString s = QFileDialog::getOpenFileName(".config", NULL, this); +	if (s.isNull()) +		return; +	if (conf_read(s.latin1())) +		QMessageBox::information(this, "qconf", "Unable to load configuration!"); +	ConfigView::updateListAll(); +} + +void ConfigMainWindow::saveConfig(void) +{ +	if (conf_write(NULL)) +		QMessageBox::information(this, "qconf", "Unable to save configuration!"); +} + +void ConfigMainWindow::saveConfigAs(void) +{ +	QString s = QFileDialog::getSaveFileName(".config", NULL, this); +	if (s.isNull()) +		return; +	if (conf_write(s.latin1())) +		QMessageBox::information(this, "qconf", "Unable to save configuration!"); +} + +void ConfigMainWindow::changeMenu(struct menu *menu) +{ +	configList->setRootMenu(menu); +	backAction->setEnabled(TRUE); +} + +void ConfigMainWindow::listFocusChanged(void) +{ +	if (menuList->hasFocus()) { +		if (menuList->mode == menuMode) +			configList->clearSelection(); +		setHelp(menuList->selectedItem()); +	} else if (configList->hasFocus()) { +		setHelp(configList->selectedItem()); +	} +} + +void ConfigMainWindow::goBack(void) +{ +	ConfigItem* item; + +	configList->setParentMenu(); +	if (configList->rootEntry == &rootmenu) +		backAction->setEnabled(FALSE); +	item = (ConfigItem*)menuList->selectedItem(); +	while (item) { +		if (item->menu == configList->rootEntry) { +			menuList->setSelected(item, TRUE); +			break; +		} +		item = (ConfigItem*)item->parent(); +	} +} + +void ConfigMainWindow::showSingleView(void) +{ +	menuView->hide(); +	menuList->setRootMenu(0); +	configList->mode = singleMode; +	if (configList->rootEntry == &rootmenu) +		configList->updateListAll(); +	else +		configList->setRootMenu(&rootmenu); +	configList->setAllOpen(TRUE); +	configList->setFocus(); +} + +void ConfigMainWindow::showSplitView(void) +{ +	configList->mode = symbolMode; +	if (configList->rootEntry == &rootmenu) +		configList->updateListAll(); +	else +		configList->setRootMenu(&rootmenu); +	configList->setAllOpen(TRUE); +	configApp->processEvents(); +	menuList->mode = menuMode; +	menuList->setRootMenu(&rootmenu); +	menuList->setAllOpen(TRUE); +	menuView->show(); +	menuList->setFocus(); +} + +void ConfigMainWindow::showFullView(void) +{ +	menuView->hide(); +	menuList->setRootMenu(0); +	configList->mode = fullMode; +	if (configList->rootEntry == &rootmenu) +		configList->updateListAll(); +	else +		configList->setRootMenu(&rootmenu); +	configList->setAllOpen(FALSE); +	configList->setFocus(); +} + +void ConfigMainWindow::setShowAll(bool b) +{ +	if (configList->showAll == b) +		return; +	configList->showAll = b; +	configList->updateListAll(); +	menuList->showAll = b; +	menuList->updateListAll(); +} + +void ConfigMainWindow::setShowDebug(bool b) +{ +	if (showDebug == b) +		return; +	showDebug = b; +} + +void ConfigMainWindow::setShowName(bool b) +{ +	if (configList->showName == b) +		return; +	configList->showName = b; +	configList->reinit(); +	menuList->showName = b; +	menuList->reinit(); +} + +void ConfigMainWindow::setShowRange(bool b) +{ +	if (configList->showRange == b) +		return; +	configList->showRange = b; +	configList->reinit(); +	menuList->showRange = b; +	menuList->reinit(); +} + +void ConfigMainWindow::setShowData(bool b) +{ +	if (configList->showData == b) +		return; +	configList->showData = b; +	configList->reinit(); +	menuList->showData = b; +	menuList->reinit(); +} + +/* + * ask for saving configuration before quitting + * TODO ask only when something changed + */ +void ConfigMainWindow::closeEvent(QCloseEvent* e) +{ +	if (!sym_change_count) { +		e->accept(); +		return; +	} +	QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning, +			QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); +	mb.setButtonText(QMessageBox::Yes, "&Save Changes"); +	mb.setButtonText(QMessageBox::No, "&Discard Changes"); +	mb.setButtonText(QMessageBox::Cancel, "Cancel Exit"); +	switch (mb.exec()) { +	case QMessageBox::Yes: +		conf_write(NULL); +	case QMessageBox::No: +		e->accept(); +		break; +	case QMessageBox::Cancel: +		e->ignore(); +		break; +	} +} + +void ConfigMainWindow::showIntro(void) +{ +	static char str[] = "Welcome to the qconf graphical kernel configuration tool for Linux.\n\n" +		"For each option, a blank box indicates the feature is disabled, a check\n" +		"indicates it is enabled, and a dot indicates that it is to be compiled\n" +		"as a module.  Clicking on the box will cycle through the three states.\n\n" +		"If you do not see an option (e.g., a device driver) that you believe\n" +		"should be present, try turning on Show All Options under the Options menu.\n" +		"Although there is no cross reference yet to help you figure out what other\n" +		"options must be enabled to support the option you are interested in, you can\n" +		"still view the help of a grayed-out option.\n\n" +		"Toggling Show Debug Info under the Options menu will show the dependencies,\n" +		"which you can then match by examining other options.\n\n"; + +	QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::showAbout(void) +{ +	static char str[] = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n" +		"Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"; + +	QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::saveSettings(void) +{ +#if QT_VERSION >= 300 +	ConfigSettings *configSettings = new ConfigSettings; +	configSettings->writeEntry("/kconfig/qconf/window x", pos().x()); +	configSettings->writeEntry("/kconfig/qconf/window y", pos().y()); +	configSettings->writeEntry("/kconfig/qconf/window width", size().width()); +	configSettings->writeEntry("/kconfig/qconf/window height", size().height()); +	configSettings->writeEntry("/kconfig/qconf/showName", configList->showName); +	configSettings->writeEntry("/kconfig/qconf/showRange", configList->showRange); +	configSettings->writeEntry("/kconfig/qconf/showData", configList->showData); +	configSettings->writeEntry("/kconfig/qconf/showAll", configList->showAll); +	configSettings->writeEntry("/kconfig/qconf/showDebug", showDebug); + +	QString entry; +	switch(configList->mode) { +	case singleMode : +		entry = "single"; +		break; + +	case symbolMode : +		entry = "split"; +		break; + +	case fullMode : +		entry = "full"; +		break; +	} +	configSettings->writeEntry("/kconfig/qconf/listMode", entry); + +	configSettings->writeSizes("/kconfig/qconf/split1", split1->sizes()); +	configSettings->writeSizes("/kconfig/qconf/split2", split2->sizes()); + +	delete configSettings; +#endif +} + +void fixup_rootmenu(struct menu *menu) +{ +	struct menu *child; +	static int menu_cnt = 0; + +	menu->flags |= MENU_ROOT; +	for (child = menu->list; child; child = child->next) { +		if (child->prompt && child->prompt->type == P_MENU) { +			menu_cnt++; +			fixup_rootmenu(child); +			menu_cnt--; +		} else if (!menu_cnt) +			fixup_rootmenu(child); +	} +} + +static const char *progname; + +static void usage(void) +{ +	printf("%s <config>\n", progname); +	exit(0); +} + +int main(int ac, char** av) +{ +	ConfigMainWindow* v; +	const char *name; + +#ifndef LKC_DIRECT_LINK +	kconfig_load(); +#endif + +	progname = av[0]; +	configApp = new QApplication(ac, av); +	if (ac > 1 && av[1][0] == '-') { +		switch (av[1][1]) { +		case 'h': +		case '?': +			usage(); +		} +		name = av[2]; +	} else +		name = av[1]; +	if (!name) +		usage(); + +	conf_parse(name); +	fixup_rootmenu(&rootmenu); +	conf_read(NULL); +	//zconfdump(stdout); + +	v = new ConfigMainWindow(); + +	//zconfdump(stdout); +	v->show(); +	configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); +	configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); +	configApp->exec(); + +	return 0; +} diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h new file mode 100644 index 000000000000..7c03927d4c7c --- /dev/null +++ b/scripts/kconfig/qconf.h @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <qlistview.h> +#if QT_VERSION >= 300 +#include <qsettings.h> +#else +class QSettings { }; +#endif + +class ConfigList; +class ConfigItem; +class ConfigLineEdit; +class ConfigMainWindow; + + +class ConfigSettings : public QSettings { +public: +	ConfigSettings(); + +#if QT_VERSION >= 300 +	void readListSettings(); +	QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok); +	bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value); +#endif + +	bool showAll; +	bool showName; +	bool showRange; +	bool showData; +}; + +class ConfigView : public QVBox { +	Q_OBJECT +	typedef class QVBox Parent; +public: +	ConfigView(QWidget* parent, ConfigMainWindow* cview, ConfigSettings* configSettings); +	~ConfigView(void); +	static void updateList(ConfigItem* item); +	static void updateListAll(void); + +public: +	ConfigList* list; +	ConfigLineEdit* lineEdit; + +	static ConfigView* viewList; +	ConfigView* nextView; +}; + +enum colIdx { +	promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr +}; +enum listMode { +	singleMode, menuMode, symbolMode, fullMode +}; + +class ConfigList : public QListView { +	Q_OBJECT +	typedef class QListView Parent; +public: +	ConfigList(ConfigView* p, ConfigMainWindow* cview, ConfigSettings *configSettings); +	void reinit(void); +	ConfigView* parent(void) const +	{ +		return (ConfigView*)Parent::parent(); +	} + +protected: +	ConfigMainWindow* cview; + +	void keyPressEvent(QKeyEvent *e); +	void contentsMousePressEvent(QMouseEvent *e); +	void contentsMouseReleaseEvent(QMouseEvent *e); +	void contentsMouseMoveEvent(QMouseEvent *e); +	void contentsMouseDoubleClickEvent(QMouseEvent *e); +	void focusInEvent(QFocusEvent *e); +public slots: +	void setRootMenu(struct menu *menu); + +	void updateList(ConfigItem *item); +	void setValue(ConfigItem* item, tristate val); +	void changeValue(ConfigItem* item); +	void updateSelection(void); +signals: +	void menuSelected(struct menu *menu); +	void parentSelected(void); +	void gotFocus(void); + +public: +	void updateListAll(void) +	{ +		updateAll = true; +		updateList(NULL); +		updateAll = false; +	} +	ConfigList* listView() +	{ +		return this; +	} +	ConfigItem* firstChild() const +	{ +		return (ConfigItem *)Parent::firstChild(); +	} +	int mapIdx(colIdx idx) +	{ +		return colMap[idx]; +	} +	void addColumn(colIdx idx, const QString& label) +	{ +		colMap[idx] = Parent::addColumn(label); +		colRevMap[colMap[idx]] = idx; +	} +	void removeColumn(colIdx idx) +	{ +		int col = colMap[idx]; +		if (col >= 0) { +			Parent::removeColumn(col); +			colRevMap[col] = colMap[idx] = -1; +		} +	} +	void setAllOpen(bool open); +	void setParentMenu(void); + +	template <class P> +	void ConfigList::updateMenuList(P*, struct menu*); + +	bool updateAll; + +	QPixmap symbolYesPix, symbolModPix, symbolNoPix; +	QPixmap choiceYesPix, choiceNoPix; +	QPixmap menuPix, menuInvPix, menuBackPix, voidPix; + +	bool showAll, showName, showRange, showData; +	enum listMode mode; +	struct menu *rootEntry; +	QColorGroup disabledColorGroup; +	QColorGroup inactivedColorGroup; + +private: +	int colMap[colNr]; +	int colRevMap[colNr]; +}; + +class ConfigItem : public QListViewItem { +	typedef class QListViewItem Parent; +public: +	ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v) +	: Parent(parent, after), menu(m), visible(v), goParent(false) +	{ +		init(); +	} +	ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) +	: Parent(parent, after), menu(m), visible(v), goParent(false) +	{ +		init(); +	} +	ConfigItem(QListView *parent, ConfigItem *after, bool v) +	: Parent(parent, after), menu(0), visible(v), goParent(true) +	{ +		init(); +	} +	~ConfigItem(void); +	void init(void); +#if QT_VERSION >= 300 +	void okRename(int col); +#endif +	void updateMenu(void); +	void testUpdateMenu(bool v); +	ConfigList* listView() const +	{ +		return (ConfigList*)Parent::listView(); +	} +	ConfigItem* firstChild() const +	{ +		return (ConfigItem *)Parent::firstChild(); +	} +	ConfigItem* nextSibling() const +	{ +		return (ConfigItem *)Parent::nextSibling(); +	} +	void setText(colIdx idx, const QString& text) +	{ +		Parent::setText(listView()->mapIdx(idx), text); +	} +	QString text(colIdx idx) const +	{ +		return Parent::text(listView()->mapIdx(idx)); +	} +	void setPixmap(colIdx idx, const QPixmap& pm) +	{ +		Parent::setPixmap(listView()->mapIdx(idx), pm); +	} +	const QPixmap* pixmap(colIdx idx) const +	{ +		return Parent::pixmap(listView()->mapIdx(idx)); +	} +	void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align); + +	ConfigItem* nextItem; +	struct menu *menu; +	bool visible; +	bool goParent; +}; + +class ConfigLineEdit : public QLineEdit { +	Q_OBJECT +	typedef class QLineEdit Parent; +public: +	ConfigLineEdit(ConfigView* parent) +	: Parent(parent) +	{ } +	ConfigView* parent(void) const +	{ +		return (ConfigView*)Parent::parent(); +	} +	void show(ConfigItem *i); +	void keyPressEvent(QKeyEvent *e); + +public: +	ConfigItem *item; +}; + +class ConfigMainWindow : public QMainWindow { +	Q_OBJECT +public: +	ConfigMainWindow(void); +public slots: +	void setHelp(QListViewItem* item); +	void changeMenu(struct menu *); +	void listFocusChanged(void); +	void goBack(void); +	void loadConfig(void); +	void saveConfig(void); +	void saveConfigAs(void); +	void showSingleView(void); +	void showSplitView(void); +	void showFullView(void); +	void setShowAll(bool); +	void setShowDebug(bool); +	void setShowRange(bool); +	void setShowName(bool); +	void setShowData(bool); +	void showIntro(void); +	void showAbout(void); +	void saveSettings(void); + +protected: +	void closeEvent(QCloseEvent *e); + +	ConfigView *menuView; +	ConfigList *menuList; +	ConfigView *configView; +	ConfigList *configList; +	QTextView *helpText; +	QToolBar *toolBar; +	QAction *backAction; +	QSplitter* split1; +	QSplitter* split2; + +	bool showDebug; +}; diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c new file mode 100644 index 000000000000..affa52f5c651 --- /dev/null +++ b/scripts/kconfig/symbol.c @@ -0,0 +1,816 @@ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <regex.h> +#include <sys/utsname.h> + +#define LKC_DIRECT_LINK +#include "lkc.h" + +struct symbol symbol_yes = { +	.name = "y", +	.curr = { "y", yes }, +	.flags = SYMBOL_YES|SYMBOL_VALID, +}, symbol_mod = { +	.name = "m", +	.curr = { "m", mod }, +	.flags = SYMBOL_MOD|SYMBOL_VALID, +}, symbol_no = { +	.name = "n", +	.curr = { "n", no }, +	.flags = SYMBOL_NO|SYMBOL_VALID, +}, symbol_empty = { +	.name = "", +	.curr = { "", no }, +	.flags = SYMBOL_VALID, +}; + +int sym_change_count; +struct symbol *modules_sym; +tristate modules_val; + +void sym_add_default(struct symbol *sym, const char *def) +{ +	struct property *prop = prop_alloc(P_DEFAULT, sym); + +	prop->expr = expr_alloc_symbol(sym_lookup(def, 1)); +} + +void sym_init(void) +{ +	struct symbol *sym; +	struct utsname uts; +	char *p; +	static bool inited = false; + +	if (inited) +		return; +	inited = true; + +	uname(&uts); + +	sym = sym_lookup("ARCH", 0); +	sym->type = S_STRING; +	sym->flags |= SYMBOL_AUTO; +	p = getenv("ARCH"); +	if (p) +		sym_add_default(sym, p); + +	sym = sym_lookup("KERNELRELEASE", 0); +	sym->type = S_STRING; +	sym->flags |= SYMBOL_AUTO; +	p = getenv("KERNELRELEASE"); +	if (p) +		sym_add_default(sym, p); + +	sym = sym_lookup("UNAME_RELEASE", 0); +	sym->type = S_STRING; +	sym->flags |= SYMBOL_AUTO; +	sym_add_default(sym, uts.release); +} + +enum symbol_type sym_get_type(struct symbol *sym) +{ +	enum symbol_type type = sym->type; + +	if (type == S_TRISTATE) { +		if (sym_is_choice_value(sym) && sym->visible == yes) +			type = S_BOOLEAN; +		else if (modules_val == no) +			type = S_BOOLEAN; +	} +	return type; +} + +const char *sym_type_name(enum symbol_type type) +{ +	switch (type) { +	case S_BOOLEAN: +		return "boolean"; +	case S_TRISTATE: +		return "tristate"; +	case S_INT: +		return "integer"; +	case S_HEX: +		return "hex"; +	case S_STRING: +		return "string"; +	case S_UNKNOWN: +		return "unknown"; +	case S_OTHER: +		break; +	} +	return "???"; +} + +struct property *sym_get_choice_prop(struct symbol *sym) +{ +	struct property *prop; + +	for_all_choices(sym, prop) +		return prop; +	return NULL; +} + +struct property *sym_get_default_prop(struct symbol *sym) +{ +	struct property *prop; + +	for_all_defaults(sym, prop) { +		prop->visible.tri = expr_calc_value(prop->visible.expr); +		if (prop->visible.tri != no) +			return prop; +	} +	return NULL; +} + +struct property *sym_get_range_prop(struct symbol *sym) +{ +	struct property *prop; + +	for_all_properties(sym, prop, P_RANGE) { +		prop->visible.tri = expr_calc_value(prop->visible.expr); +		if (prop->visible.tri != no) +			return prop; +	} +	return NULL; +} + +static void sym_calc_visibility(struct symbol *sym) +{ +	struct property *prop; +	tristate tri; + +	/* any prompt visible? */ +	tri = no; +	for_all_prompts(sym, prop) { +		prop->visible.tri = expr_calc_value(prop->visible.expr); +		tri = E_OR(tri, prop->visible.tri); +	} +	if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) +		tri = yes; +	if (sym->visible != tri) { +		sym->visible = tri; +		sym_set_changed(sym); +	} +	if (sym_is_choice_value(sym)) +		return; +	tri = no; +	if (sym->rev_dep.expr) +		tri = expr_calc_value(sym->rev_dep.expr); +	if (tri == mod && sym_get_type(sym) == S_BOOLEAN) +		tri = yes; +	if (sym->rev_dep.tri != tri) { +		sym->rev_dep.tri = tri; +		sym_set_changed(sym); +	} +} + +static struct symbol *sym_calc_choice(struct symbol *sym) +{ +	struct symbol *def_sym; +	struct property *prop; +	struct expr *e; + +	/* is the user choice visible? */ +	def_sym = sym->user.val; +	if (def_sym) { +		sym_calc_visibility(def_sym); +		if (def_sym->visible != no) +			return def_sym; +	} + +	/* any of the defaults visible? */ +	for_all_defaults(sym, prop) { +		prop->visible.tri = expr_calc_value(prop->visible.expr); +		if (prop->visible.tri == no) +			continue; +		def_sym = prop_get_symbol(prop); +		sym_calc_visibility(def_sym); +		if (def_sym->visible != no) +			return def_sym; +	} + +	/* just get the first visible value */ +	prop = sym_get_choice_prop(sym); +	for (e = prop->expr; e; e = e->left.expr) { +		def_sym = e->right.sym; +		sym_calc_visibility(def_sym); +		if (def_sym->visible != no) +			return def_sym; +	} + +	/* no choice? reset tristate value */ +	sym->curr.tri = no; +	return NULL; +} + +void sym_calc_value(struct symbol *sym) +{ +	struct symbol_value newval, oldval; +	struct property *prop; +	struct expr *e; + +	if (!sym) +		return; + +	if (sym->flags & SYMBOL_VALID) +		return; +	sym->flags |= SYMBOL_VALID; + +	oldval = sym->curr; + +	switch (sym->type) { +	case S_INT: +	case S_HEX: +	case S_STRING: +		newval = symbol_empty.curr; +		break; +	case S_BOOLEAN: +	case S_TRISTATE: +		newval = symbol_no.curr; +		break; +	default: +		sym->curr.val = sym->name; +		sym->curr.tri = no; +		return; +	} +	if (!sym_is_choice_value(sym)) +		sym->flags &= ~SYMBOL_WRITE; + +	sym_calc_visibility(sym); + +	/* set default if recursively called */ +	sym->curr = newval; + +	switch (sym_get_type(sym)) { +	case S_BOOLEAN: +	case S_TRISTATE: +		if (sym_is_choice_value(sym) && sym->visible == yes) { +			prop = sym_get_choice_prop(sym); +			newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; +		} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) { +			sym->flags |= SYMBOL_WRITE; +			if (sym_has_value(sym)) +				newval.tri = sym->user.tri; +			else if (!sym_is_choice(sym)) { +				prop = sym_get_default_prop(sym); +				if (prop) +					newval.tri = expr_calc_value(prop->expr); +			} +			newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri); +		} else if (!sym_is_choice(sym)) { +			prop = sym_get_default_prop(sym); +			if (prop) { +				sym->flags |= SYMBOL_WRITE; +				newval.tri = expr_calc_value(prop->expr); +			} +		} +		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) +			newval.tri = yes; +		break; +	case S_STRING: +	case S_HEX: +	case S_INT: +		if (sym->visible != no) { +			sym->flags |= SYMBOL_WRITE; +			if (sym_has_value(sym)) { +				newval.val = sym->user.val; +				break; +			} +		} +		prop = sym_get_default_prop(sym); +		if (prop) { +			struct symbol *ds = prop_get_symbol(prop); +			if (ds) { +				sym->flags |= SYMBOL_WRITE; +				sym_calc_value(ds); +				newval.val = ds->curr.val; +			} +		} +		break; +	default: +		; +	} + +	sym->curr = newval; +	if (sym_is_choice(sym) && newval.tri == yes) +		sym->curr.val = sym_calc_choice(sym); + +	if (memcmp(&oldval, &sym->curr, sizeof(oldval))) +		sym_set_changed(sym); +	if (modules_sym == sym) +		modules_val = modules_sym->curr.tri; + +	if (sym_is_choice(sym)) { +		int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); +		prop = sym_get_choice_prop(sym); +		for (e = prop->expr; e; e = e->left.expr) { +			e->right.sym->flags |= flags; +			if (flags & SYMBOL_CHANGED) +				sym_set_changed(e->right.sym); +		} +	} +} + +void sym_clear_all_valid(void) +{ +	struct symbol *sym; +	int i; + +	for_all_symbols(i, sym) +		sym->flags &= ~SYMBOL_VALID; +	sym_change_count++; +	if (modules_sym) +		sym_calc_value(modules_sym); +} + +void sym_set_changed(struct symbol *sym) +{ +	struct property *prop; + +	sym->flags |= SYMBOL_CHANGED; +	for (prop = sym->prop; prop; prop = prop->next) { +		if (prop->menu) +			prop->menu->flags |= MENU_CHANGED; +	} +} + +void sym_set_all_changed(void) +{ +	struct symbol *sym; +	int i; + +	for_all_symbols(i, sym) +		sym_set_changed(sym); +} + +bool sym_tristate_within_range(struct symbol *sym, tristate val) +{ +	int type = sym_get_type(sym); + +	if (sym->visible == no) +		return false; + +	if (type != S_BOOLEAN && type != S_TRISTATE) +		return false; + +	if (type == S_BOOLEAN && val == mod) +		return false; +	if (sym->visible <= sym->rev_dep.tri) +		return false; +	if (sym_is_choice_value(sym) && sym->visible == yes) +		return val == yes; +	return val >= sym->rev_dep.tri && val <= sym->visible; +} + +bool sym_set_tristate_value(struct symbol *sym, tristate val) +{ +	tristate oldval = sym_get_tristate_value(sym); + +	if (oldval != val && !sym_tristate_within_range(sym, val)) +		return false; + +	if (sym->flags & SYMBOL_NEW) { +		sym->flags &= ~SYMBOL_NEW; +		sym_set_changed(sym); +	} +	if (sym_is_choice_value(sym) && val == yes) { +		struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + +		cs->user.val = sym; +		cs->flags &= ~SYMBOL_NEW; +	} + +	sym->user.tri = val; +	if (oldval != val) { +		sym_clear_all_valid(); +		if (sym == modules_sym) +			sym_set_all_changed(); +	} + +	return true; +} + +tristate sym_toggle_tristate_value(struct symbol *sym) +{ +	tristate oldval, newval; + +	oldval = newval = sym_get_tristate_value(sym); +	do { +		switch (newval) { +		case no: +			newval = mod; +			break; +		case mod: +			newval = yes; +			break; +		case yes: +			newval = no; +			break; +		} +		if (sym_set_tristate_value(sym, newval)) +			break; +	} while (oldval != newval); +	return newval; +} + +bool sym_string_valid(struct symbol *sym, const char *str) +{ +	signed char ch; + +	switch (sym->type) { +	case S_STRING: +		return true; +	case S_INT: +		ch = *str++; +		if (ch == '-') +			ch = *str++; +		if (!isdigit(ch)) +			return false; +		if (ch == '0' && *str != 0) +			return false; +		while ((ch = *str++)) { +			if (!isdigit(ch)) +				return false; +		} +		return true; +	case S_HEX: +		if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) +			str += 2; +		ch = *str++; +		do { +			if (!isxdigit(ch)) +				return false; +		} while ((ch = *str++)); +		return true; +	case S_BOOLEAN: +	case S_TRISTATE: +		switch (str[0]) { +		case 'y': case 'Y': +		case 'm': case 'M': +		case 'n': case 'N': +			return true; +		} +		return false; +	default: +		return false; +	} +} + +bool sym_string_within_range(struct symbol *sym, const char *str) +{ +	struct property *prop; +	int val; + +	switch (sym->type) { +	case S_STRING: +		return sym_string_valid(sym, str); +	case S_INT: +		if (!sym_string_valid(sym, str)) +			return false; +		prop = sym_get_range_prop(sym); +		if (!prop) +			return true; +		val = strtol(str, NULL, 10); +		return val >= strtol(prop->expr->left.sym->name, NULL, 10) && +		       val <= strtol(prop->expr->right.sym->name, NULL, 10); +	case S_HEX: +		if (!sym_string_valid(sym, str)) +			return false; +		prop = sym_get_range_prop(sym); +		if (!prop) +			return true; +		val = strtol(str, NULL, 16); +		return val >= strtol(prop->expr->left.sym->name, NULL, 16) && +		       val <= strtol(prop->expr->right.sym->name, NULL, 16); +	case S_BOOLEAN: +	case S_TRISTATE: +		switch (str[0]) { +		case 'y': case 'Y': +			return sym_tristate_within_range(sym, yes); +		case 'm': case 'M': +			return sym_tristate_within_range(sym, mod); +		case 'n': case 'N': +			return sym_tristate_within_range(sym, no); +		} +		return false; +	default: +		return false; +	} +} + +bool sym_set_string_value(struct symbol *sym, const char *newval) +{ +	const char *oldval; +	char *val; +	int size; + +	switch (sym->type) { +	case S_BOOLEAN: +	case S_TRISTATE: +		switch (newval[0]) { +		case 'y': case 'Y': +			return sym_set_tristate_value(sym, yes); +		case 'm': case 'M': +			return sym_set_tristate_value(sym, mod); +		case 'n': case 'N': +			return sym_set_tristate_value(sym, no); +		} +		return false; +	default: +		; +	} + +	if (!sym_string_within_range(sym, newval)) +		return false; + +	if (sym->flags & SYMBOL_NEW) { +		sym->flags &= ~SYMBOL_NEW; +		sym_set_changed(sym); +	} + +	oldval = sym->user.val; +	size = strlen(newval) + 1; +	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { +		size += 2; +		sym->user.val = val = malloc(size); +		*val++ = '0'; +		*val++ = 'x'; +	} else if (!oldval || strcmp(oldval, newval)) +		sym->user.val = val = malloc(size); +	else +		return true; + +	strcpy(val, newval); +	free((void *)oldval); +	sym_clear_all_valid(); + +	return true; +} + +const char *sym_get_string_value(struct symbol *sym) +{ +	tristate val; + +	switch (sym->type) { +	case S_BOOLEAN: +	case S_TRISTATE: +		val = sym_get_tristate_value(sym); +		switch (val) { +		case no: +			return "n"; +		case mod: +			return "m"; +		case yes: +			return "y"; +		} +		break; +	default: +		; +	} +	return (const char *)sym->curr.val; +} + +bool sym_is_changable(struct symbol *sym) +{ +	return sym->visible > sym->rev_dep.tri; +} + +struct symbol *sym_lookup(const char *name, int isconst) +{ +	struct symbol *symbol; +	const char *ptr; +	char *new_name; +	int hash = 0; + +	if (name) { +		if (name[0] && !name[1]) { +			switch (name[0]) { +			case 'y': return &symbol_yes; +			case 'm': return &symbol_mod; +			case 'n': return &symbol_no; +			} +		} +		for (ptr = name; *ptr; ptr++) +			hash += *ptr; +		hash &= 0xff; + +		for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { +			if (!strcmp(symbol->name, name)) { +				if ((isconst && symbol->flags & SYMBOL_CONST) || +				    (!isconst && !(symbol->flags & SYMBOL_CONST))) +					return symbol; +			} +		} +		new_name = strdup(name); +	} else { +		new_name = NULL; +		hash = 256; +	} + +	symbol = malloc(sizeof(*symbol)); +	memset(symbol, 0, sizeof(*symbol)); +	symbol->name = new_name; +	symbol->type = S_UNKNOWN; +	symbol->flags = SYMBOL_NEW; +	if (isconst) +		symbol->flags |= SYMBOL_CONST; + +	symbol->next = symbol_hash[hash]; +	symbol_hash[hash] = symbol; + +	return symbol; +} + +struct symbol *sym_find(const char *name) +{ +	struct symbol *symbol = NULL; +	const char *ptr; +	int hash = 0; + +	if (!name) +		return NULL; + +	if (name[0] && !name[1]) { +		switch (name[0]) { +		case 'y': return &symbol_yes; +		case 'm': return &symbol_mod; +		case 'n': return &symbol_no; +		} +	} +	for (ptr = name; *ptr; ptr++) +		hash += *ptr; +	hash &= 0xff; + +	for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { +		if (!strcmp(symbol->name, name) && +		    !(symbol->flags & SYMBOL_CONST)) +				break; +	} + +	return symbol; +} + +struct symbol **sym_re_search(const char *pattern) +{ +	struct symbol *sym, **sym_arr = NULL; +	int i, cnt, size; +	regex_t re; + +	cnt = size = 0; +	/* Skip if empty */ +	if (strlen(pattern) == 0) +		return NULL; +	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) +		return NULL; + +	for_all_symbols(i, sym) { +		if (sym->flags & SYMBOL_CONST || !sym->name) +			continue; +		if (regexec(&re, sym->name, 0, NULL, 0)) +			continue; +		if (cnt + 1 >= size) { +			void *tmp = sym_arr; +			size += 16; +			sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); +			if (!sym_arr) { +				free(tmp); +				return NULL; +			} +		} +		sym_arr[cnt++] = sym; +	} +	if (sym_arr) +		sym_arr[cnt] = NULL; +	regfree(&re); + +	return sym_arr; +} + + +struct symbol *sym_check_deps(struct symbol *sym); + +static struct symbol *sym_check_expr_deps(struct expr *e) +{ +	struct symbol *sym; + +	if (!e) +		return NULL; +	switch (e->type) { +	case E_OR: +	case E_AND: +		sym = sym_check_expr_deps(e->left.expr); +		if (sym) +			return sym; +		return sym_check_expr_deps(e->right.expr); +	case E_NOT: +		return sym_check_expr_deps(e->left.expr); +	case E_EQUAL: +	case E_UNEQUAL: +		sym = sym_check_deps(e->left.sym); +		if (sym) +			return sym; +		return sym_check_deps(e->right.sym); +	case E_SYMBOL: +		return sym_check_deps(e->left.sym); +	default: +		break; +	} +	printf("Oops! How to check %d?\n", e->type); +	return NULL; +} + +struct symbol *sym_check_deps(struct symbol *sym) +{ +	struct symbol *sym2; +	struct property *prop; + +	if (sym->flags & SYMBOL_CHECK_DONE) +		return NULL; +	if (sym->flags & SYMBOL_CHECK) { +		printf("Warning! Found recursive dependency: %s", sym->name); +		return sym; +	} + +	sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); +	sym2 = sym_check_expr_deps(sym->rev_dep.expr); +	if (sym2) +		goto out; + +	for (prop = sym->prop; prop; prop = prop->next) { +		if (prop->type == P_CHOICE || prop->type == P_SELECT) +			continue; +		sym2 = sym_check_expr_deps(prop->visible.expr); +		if (sym2) +			goto out; +		if (prop->type != P_DEFAULT || sym_is_choice(sym)) +			continue; +		sym2 = sym_check_expr_deps(prop->expr); +		if (sym2) +			goto out; +	} +out: +	if (sym2) +		printf(" %s", sym->name); +	sym->flags &= ~SYMBOL_CHECK; +	return sym2; +} + +struct property *prop_alloc(enum prop_type type, struct symbol *sym) +{ +	struct property *prop; +	struct property **propp; + +	prop = malloc(sizeof(*prop)); +	memset(prop, 0, sizeof(*prop)); +	prop->type = type; +	prop->sym = sym; +	prop->file = current_file; +	prop->lineno = zconf_lineno(); + +	/* append property to the prop list of symbol */ +	if (sym) { +		for (propp = &sym->prop; *propp; propp = &(*propp)->next) +			; +		*propp = prop; +	} + +	return prop; +} + +struct symbol *prop_get_symbol(struct property *prop) +{ +	if (prop->expr && (prop->expr->type == E_SYMBOL || +			   prop->expr->type == E_CHOICE)) +		return prop->expr->left.sym; +	return NULL; +} + +const char *prop_get_type_name(enum prop_type type) +{ +	switch (type) { +	case P_PROMPT: +		return "prompt"; +	case P_COMMENT: +		return "comment"; +	case P_MENU: +		return "menu"; +	case P_DEFAULT: +		return "default"; +	case P_CHOICE: +		return "choice"; +	case P_SELECT: +		return "select"; +	case P_RANGE: +		return "range"; +	case P_UNKNOWN: +		break; +	} +	return "unknown"; +} diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c new file mode 100644 index 000000000000..1fa4c0b801b3 --- /dev/null +++ b/scripts/kconfig/util.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org> + * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org> + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include <string.h> +#include "lkc.h" + +/* file already present in list? If not add it */ +struct file *file_lookup(const char *name) +{ +	struct file *file; + +	for (file = file_list; file; file = file->next) { +		if (!strcmp(name, file->name)) +			return file; +	} + +	file = malloc(sizeof(*file)); +	memset(file, 0, sizeof(*file)); +	file->name = strdup(name); +	file->next = file_list; +	file_list = file; +	return file; +} + +/* write a dependency file as used by kbuild to track dependencies */ +int file_write_dep(const char *name) +{ +	struct file *file; +	FILE *out; + +	if (!name) +		name = ".config.cmd"; +	out = fopen("..config.tmp", "w"); +	if (!out) +		return 1; +	fprintf(out, "deps_config := \\\n"); +	for (file = file_list; file; file = file->next) { +		if (file->next) +			fprintf(out, "\t%s \\\n", file->name); +		else +			fprintf(out, "\t%s\n", file->name); +	} +	fprintf(out, "\n.config include/linux/autoconf.h: $(deps_config)\n\n$(deps_config):\n"); +	fclose(out); +	rename("..config.tmp", name); +	return 0; +} + + +/* Allocate initial growable sting */ +struct gstr str_new(void) +{ +	struct gstr gs; +	gs.s = malloc(sizeof(char) * 64); +	gs.len = 16; +	strcpy(gs.s, "\0"); +	return gs; +} + +/* Allocate and assign growable string */ +struct gstr str_assign(const char *s) +{ +	struct gstr gs; +	gs.s = strdup(s); +	gs.len = strlen(s) + 1; +	return gs; +} + +/* Free storage for growable string */ +void str_free(struct gstr *gs) +{ +	if (gs->s) +		free(gs->s); +	gs->s = NULL; +	gs->len = 0; +} + +/* Append to growable string */ +void str_append(struct gstr *gs, const char *s) +{ +	size_t l = strlen(gs->s) + strlen(s) + 1; +	if (l > gs->len) { +		gs->s   = realloc(gs->s, l); +		gs->len = l; +	} +	strcat(gs->s, s); +} + +/* Append printf formatted string to growable string */ +void str_printf(struct gstr *gs, const char *fmt, ...) +{ +	va_list ap; +	char s[10000]; /* big enough... */ +	va_start(ap, fmt); +	vsnprintf(s, sizeof(s), fmt, ap); +	str_append(gs, s); +	va_end(ap); +} + +/* Retreive value of growable string */ +const char *str_get(struct gstr *gs) +{ +	return gs->s; +} + diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l new file mode 100644 index 000000000000..55517b2877cd --- /dev/null +++ b/scripts/kconfig/zconf.l @@ -0,0 +1,366 @@ +%option backup nostdinit noyywrap never-interactive full ecs +%option 8bit backup nodefault perf-report perf-report +%x COMMAND HELP STRING PARAM +%{ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define START_STRSIZE	16 + +char *text; +static char *text_ptr; +static int text_size, text_asize; + +struct buffer { +        struct buffer *parent; +        YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static struct buffer *zconf_endfile(void); + +void new_string(void) +{ +	text = malloc(START_STRSIZE); +	text_asize = START_STRSIZE; +	text_ptr = text; +	text_size = 0; +	*text_ptr = 0; +} + +void append_string(const char *str, int size) +{ +	int new_size = text_size + size + 1; +	if (new_size > text_asize) { +		text = realloc(text, new_size); +		text_asize = new_size; +		text_ptr = text + text_size; +	} +	memcpy(text_ptr, str, size); +	text_ptr += size; +	text_size += size; +	*text_ptr = 0; +} + +void alloc_string(const char *str, int size) +{ +	text = malloc(size + 1); +	memcpy(text, str, size); +	text[size] = 0; +} +%} + +ws	[ \n\t] +n	[A-Za-z0-9_] + +%% +	int str = 0; +	int ts, i; + +[ \t]*#.*\n	current_file->lineno++; +[ \t]*#.* + +[ \t]*\n	current_file->lineno++; return T_EOL; + +[ \t]+	{ +	BEGIN(COMMAND); +} + +.	{ +	unput(yytext[0]); +	BEGIN(COMMAND); +} + + +<COMMAND>{ +	"mainmenu"		BEGIN(PARAM); return T_MAINMENU; +	"menu"			BEGIN(PARAM); return T_MENU; +	"endmenu"		BEGIN(PARAM); return T_ENDMENU; +	"source"		BEGIN(PARAM); return T_SOURCE; +	"choice"		BEGIN(PARAM); return T_CHOICE; +	"endchoice"		BEGIN(PARAM); return T_ENDCHOICE; +	"comment"		BEGIN(PARAM); return T_COMMENT; +	"config"		BEGIN(PARAM); return T_CONFIG; +	"menuconfig"		BEGIN(PARAM); return T_MENUCONFIG; +	"help"			BEGIN(PARAM); return T_HELP; +	"if"			BEGIN(PARAM); return T_IF; +	"endif"			BEGIN(PARAM); return T_ENDIF; +	"depends"		BEGIN(PARAM); return T_DEPENDS; +	"requires"		BEGIN(PARAM); return T_REQUIRES; +	"optional"		BEGIN(PARAM); return T_OPTIONAL; +	"default"		BEGIN(PARAM); return T_DEFAULT; +	"prompt"		BEGIN(PARAM); return T_PROMPT; +	"tristate"		BEGIN(PARAM); return T_TRISTATE; +	"def_tristate"		BEGIN(PARAM); return T_DEF_TRISTATE; +	"bool"			BEGIN(PARAM); return T_BOOLEAN; +	"boolean"		BEGIN(PARAM); return T_BOOLEAN; +	"def_bool"		BEGIN(PARAM); return T_DEF_BOOLEAN; +	"def_boolean"		BEGIN(PARAM); return T_DEF_BOOLEAN; +	"int"			BEGIN(PARAM); return T_INT; +	"hex"			BEGIN(PARAM); return T_HEX; +	"string"		BEGIN(PARAM); return T_STRING; +	"select"		BEGIN(PARAM); return T_SELECT; +	"enable"		BEGIN(PARAM); return T_SELECT; +	"range"			BEGIN(PARAM); return T_RANGE; +	{n}+	{ +		alloc_string(yytext, yyleng); +		zconflval.string = text; +		return T_WORD; +	} +	. +	\n	current_file->lineno++; BEGIN(INITIAL); +} + +<PARAM>{ +	"&&"	return T_AND; +	"||"	return T_OR; +	"("	return T_OPEN_PAREN; +	")"	return T_CLOSE_PAREN; +	"!"	return T_NOT; +	"="	return T_EQUAL; +	"!="	return T_UNEQUAL; +	"if"	return T_IF; +	"on"	return T_ON; +	\"|\'	{ +		str = yytext[0]; +		new_string(); +		BEGIN(STRING); +	} +	\n	BEGIN(INITIAL); current_file->lineno++; return T_EOL; +	---	/* ignore */ +	({n}|[-/.])+	{ +		alloc_string(yytext, yyleng); +		zconflval.string = text; +		return T_WORD; +	} +	#.*	/* comment */ +	\\\n	current_file->lineno++; +	. +	<<EOF>> { +		BEGIN(INITIAL); +	} +} + +<STRING>{ +	[^'"\\\n]+/\n	{ +		append_string(yytext, yyleng); +		zconflval.string = text; +		return T_WORD_QUOTE; +	} +	[^'"\\\n]+	{ +		append_string(yytext, yyleng); +	} +	\\.?/\n	{ +		append_string(yytext + 1, yyleng - 1); +		zconflval.string = text; +		return T_WORD_QUOTE; +	} +	\\.?	{ +		append_string(yytext + 1, yyleng - 1); +	} +	\'|\"	{ +		if (str == yytext[0]) { +			BEGIN(PARAM); +			zconflval.string = text; +			return T_WORD_QUOTE; +		} else +			append_string(yytext, 1); +	} +	\n	{ +		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); +		current_file->lineno++; +		BEGIN(INITIAL); +		return T_EOL; +	} +	<<EOF>>	{ +		BEGIN(INITIAL); +	} +} + +<HELP>{ +	[ \t]+	{ +		ts = 0; +		for (i = 0; i < yyleng; i++) { +			if (yytext[i] == '\t') +				ts = (ts & ~7) + 8; +			else +				ts++; +		} +		last_ts = ts; +		if (first_ts) { +			if (ts < first_ts) { +				zconf_endhelp(); +				return T_HELPTEXT; +			} +			ts -= first_ts; +			while (ts > 8) { +				append_string("        ", 8); +				ts -= 8; +			} +			append_string("        ", ts); +		} +	} +	[ \t]*\n/[^ \t\n] { +		current_file->lineno++; +		zconf_endhelp(); +		return T_HELPTEXT; +	} +	[ \t]*\n	{ +		current_file->lineno++; +		append_string("\n", 1); +	} +	[^ \t\n].* { +		append_string(yytext, yyleng); +		if (!first_ts) +			first_ts = last_ts; +	} +	<<EOF>>	{ +		zconf_endhelp(); +		return T_HELPTEXT; +	} +} + +<<EOF>>	{ +	if (current_buf) { +		zconf_endfile(); +		return T_EOF; +	} +	fclose(yyin); +	yyterminate(); +} + +%% +void zconf_starthelp(void) +{ +	new_string(); +	last_ts = first_ts = 0; +	BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ +	zconflval.string = text; +	BEGIN(INITIAL); +} + + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ +	char *env, fullname[PATH_MAX+1]; +	FILE *f; + +	f = fopen(name, "r"); +	if (!f && name[0] != '/') { +		env = getenv(SRCTREE); +		if (env) { +			sprintf(fullname, "%s/%s", env, name); +			f = fopen(fullname, "r"); +		} +	} +	return f; +} + +void zconf_initscan(const char *name) +{ +	yyin = zconf_fopen(name); +	if (!yyin) { +		printf("can't find file %s\n", name); +		exit(1); +	} + +	current_buf = malloc(sizeof(*current_buf)); +	memset(current_buf, 0, sizeof(*current_buf)); + +	current_file = file_lookup(name); +	current_file->lineno = 1; +	current_file->flags = FILE_BUSY; +} + +void zconf_nextfile(const char *name) +{ +	struct file *file = file_lookup(name); +	struct buffer *buf = malloc(sizeof(*buf)); +	memset(buf, 0, sizeof(*buf)); + +	current_buf->state = YY_CURRENT_BUFFER; +	yyin = zconf_fopen(name); +	if (!yyin) { +		printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name); +		exit(1); +	} +	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); +	buf->parent = current_buf; +	current_buf = buf; + +	if (file->flags & FILE_BUSY) { +		printf("recursive scan (%s)?\n", name); +		exit(1); +	} +	if (file->flags & FILE_SCANNED) { +		printf("file %s already scanned?\n", name); +		exit(1); +	} +	file->flags |= FILE_BUSY; +	file->lineno = 1; +	file->parent = current_file; +	current_file = file; +} + +static struct buffer *zconf_endfile(void) +{ +	struct buffer *parent; + +	current_file->flags |= FILE_SCANNED; +	current_file->flags &= ~FILE_BUSY; +	current_file = current_file->parent; + +	parent = current_buf->parent; +	if (parent) { +		fclose(yyin); +		yy_delete_buffer(YY_CURRENT_BUFFER); +		yy_switch_to_buffer(parent->state); +	} +	free(current_buf); +	current_buf = parent; + +	return parent; +} + +int zconf_lineno(void) +{ +	if (current_buf) +		return current_file->lineno - 1; +	else +		return 0; +} + +char *zconf_curname(void) +{ +	if (current_buf) +		return current_file->name; +	else +		return "<none>"; +} diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped new file mode 100644 index 000000000000..f163d8d2d9ef --- /dev/null +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -0,0 +1,2130 @@ +/* A Bison parser, made by GNU Bison 1.875a.  */ + +/* Skeleton parser for Yacc-like parsing with Bison, +   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + +   This program is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published by +   the Free Software Foundation; either version 2, or (at your option) +   any later version. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software +   Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* As a special exception, when this file is copied by Bison into a +   Bison output file, you may use that output file without restriction. +   This special exception was added by the Free Software Foundation +   in version 1.24 of Bison.  */ + +/* Written by Richard Stallman by simplifying the original so called +   ``semantic'' parser.  */ + +/* All symbols defined below should begin with yy or YY, to avoid +   infringing on user name space.  This should be done even for local +   variables, as they might otherwise be expanded by user macros. +   There are some unavoidable exceptions within include files to +   define necessary library symbols; they are noted "INFRINGES ON +   USER NAME SPACE" below.  */ + +/* Identify Bison output.  */ +#define YYBISON 1 + +/* Skeleton name.  */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers.  */ +#define YYPURE 0 + +/* Using locations.  */ +#define YYLSP_NEEDED 0 + +/* If NAME_PREFIX is specified substitute the variables and functions +   names.  */ +#define yyparse zconfparse +#define yylex   zconflex +#define yyerror zconferror +#define yylval  zconflval +#define yychar  zconfchar +#define yydebug zconfdebug +#define yynerrs zconfnerrs + + +/* Tokens.  */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE +   /* Put the tokens into the symbol table, so that GDB and other debuggers +      know about them.  */ +   enum yytokentype { +     T_MAINMENU = 258, +     T_MENU = 259, +     T_ENDMENU = 260, +     T_SOURCE = 261, +     T_CHOICE = 262, +     T_ENDCHOICE = 263, +     T_COMMENT = 264, +     T_CONFIG = 265, +     T_MENUCONFIG = 266, +     T_HELP = 267, +     T_HELPTEXT = 268, +     T_IF = 269, +     T_ENDIF = 270, +     T_DEPENDS = 271, +     T_REQUIRES = 272, +     T_OPTIONAL = 273, +     T_PROMPT = 274, +     T_DEFAULT = 275, +     T_TRISTATE = 276, +     T_DEF_TRISTATE = 277, +     T_BOOLEAN = 278, +     T_DEF_BOOLEAN = 279, +     T_STRING = 280, +     T_INT = 281, +     T_HEX = 282, +     T_WORD = 283, +     T_WORD_QUOTE = 284, +     T_UNEQUAL = 285, +     T_EOF = 286, +     T_EOL = 287, +     T_CLOSE_PAREN = 288, +     T_OPEN_PAREN = 289, +     T_ON = 290, +     T_SELECT = 291, +     T_RANGE = 292, +     T_OR = 293, +     T_AND = 294, +     T_EQUAL = 295, +     T_NOT = 296 +   }; +#endif +#define T_MAINMENU 258 +#define T_MENU 259 +#define T_ENDMENU 260 +#define T_SOURCE 261 +#define T_CHOICE 262 +#define T_ENDCHOICE 263 +#define T_COMMENT 264 +#define T_CONFIG 265 +#define T_MENUCONFIG 266 +#define T_HELP 267 +#define T_HELPTEXT 268 +#define T_IF 269 +#define T_ENDIF 270 +#define T_DEPENDS 271 +#define T_REQUIRES 272 +#define T_OPTIONAL 273 +#define T_PROMPT 274 +#define T_DEFAULT 275 +#define T_TRISTATE 276 +#define T_DEF_TRISTATE 277 +#define T_BOOLEAN 278 +#define T_DEF_BOOLEAN 279 +#define T_STRING 280 +#define T_INT 281 +#define T_HEX 282 +#define T_WORD 283 +#define T_WORD_QUOTE 284 +#define T_UNEQUAL 285 +#define T_EOF 286 +#define T_EOL 287 +#define T_CLOSE_PAREN 288 +#define T_OPEN_PAREN 289 +#define T_ON 290 +#define T_SELECT 291 +#define T_RANGE 292 +#define T_OR 293 +#define T_AND 294 +#define T_EQUAL 295 +#define T_NOT 296 + + + + +/* Copy the first part of user declarations.  */ + + +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD		0x0001 +#define DEBUG_PARSE	0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(int token, int starttoken, int endtoken); + +struct symbol *symbol_hash[257]; + +static struct menu *current_menu, *current_entry; + +#define YYERROR_VERBOSE + + +/* Enabling traces.  */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages.  */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) + +typedef union YYSTYPE { +	int token; +	char *string; +	struct symbol *symbol; +	struct expr *expr; +	struct menu *menu; +} YYSTYPE; +/* Line 191 of yacc.c.  */ + +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations.  */ + + +#define LKC_DIRECT_LINK +#include "lkc.h" + + +/* Line 214 of yacc.c.  */ + + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols.  */ + +# if YYSTACK_USE_ALLOCA +#  define YYSTACK_ALLOC alloca +# else +#  ifndef YYSTACK_USE_ALLOCA +#   if defined (alloca) || defined (_ALLOCA_H) +#    define YYSTACK_ALLOC alloca +#   else +#    ifdef __GNUC__ +#     define YYSTACK_ALLOC __builtin_alloca +#    endif +#   endif +#  endif +# endif + +# ifdef YYSTACK_ALLOC +   /* Pacify GCC's `empty if-body' warning. */ +#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +#  if defined (__STDC__) || defined (__cplusplus) +#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +#   define YYSIZE_T size_t +#  endif +#  define YYSTACK_ALLOC malloc +#  define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ +     && (! defined (__cplusplus) \ +	 || (YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member.  */ +union yyalloc +{ +  short yyss; +  YYSTYPE yyvs; +  }; + +/* The size of the maximum gap between one aligned stack and the next.  */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with +   N elements.  */ +# define YYSTACK_BYTES(N) \ +     ((N) * (sizeof (short) + sizeof (YYSTYPE))				\ +      + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO.  The source and destination do +   not overlap.  */ +# ifndef YYCOPY +#  if 1 < __GNUC__ +#   define YYCOPY(To, From, Count) \ +      __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +#  else +#   define YYCOPY(To, From, Count)		\ +      do					\ +	{					\ +	  register YYSIZE_T yyi;		\ +	  for (yyi = 0; yyi < (Count); yyi++)	\ +	    (To)[yyi] = (From)[yyi];		\ +	}					\ +      while (0) +#  endif +# endif + +/* Relocate STACK from its old location to the new one.  The +   local variables YYSIZE and YYSTACKSIZE give the old and new number of +   elements in the stack, and YYPTR gives the new location of the +   stack.  Advance YYPTR to a properly aligned location for the next +   stack.  */ +# define YYSTACK_RELOCATE(Stack)					\ +    do									\ +      {									\ +	YYSIZE_T yynewbytes;						\ +	YYCOPY (&yyptr->Stack, Stack, yysize);				\ +	Stack = &yyptr->Stack;						\ +	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ +	yyptr += yynewbytes / sizeof (*yyptr);				\ +      }									\ +    while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) +   typedef signed char yysigned_char; +#else +   typedef short yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL  2 +/* YYLAST -- Last index in YYTABLE.  */ +#define YYLAST   201 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS  42 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS  41 +/* YYNRULES -- Number of rules. */ +#define YYNRULES  104 +/* YYNRULES -- Number of states. */ +#define YYNSTATES  182 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */ +#define YYUNDEFTOK  2 +#define YYMAXUTOK   296 + +#define YYTRANSLATE(YYX) 						\ +  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */ +static const unsigned char yytranslate[] = +{ +       0,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     1,     2,     3,     4, +       5,     6,     7,     8,     9,    10,    11,    12,    13,    14, +      15,    16,    17,    18,    19,    20,    21,    22,    23,    24, +      25,    26,    27,    28,    29,    30,    31,    32,    33,    34, +      35,    36,    37,    38,    39,    40,    41 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in +   YYRHS.  */ +static const unsigned short yyprhs[] = +{ +       0,     0,     3,     4,     7,     9,    11,    13,    17,    19, +      21,    23,    26,    28,    30,    32,    34,    36,    38,    42, +      45,    49,    52,    53,    56,    59,    62,    65,    69,    74, +      78,    83,    87,    91,    95,   100,   105,   110,   116,   119, +     122,   124,   128,   131,   132,   135,   138,   141,   144,   149, +     153,   157,   160,   165,   166,   169,   173,   175,   179,   182, +     183,   186,   189,   192,   196,   199,   201,   205,   208,   209, +     212,   215,   218,   222,   226,   228,   232,   235,   238,   241, +     242,   245,   248,   253,   257,   261,   262,   265,   267,   269, +     272,   275,   278,   280,   282,   283,   286,   288,   292,   296, +     300,   303,   307,   311,   313 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ +      43,     0,    -1,    -1,    43,    44,    -1,    45,    -1,    55, +      -1,    66,    -1,     3,    77,    79,    -1,     5,    -1,    15, +      -1,     8,    -1,     1,    79,    -1,    61,    -1,    71,    -1, +      47,    -1,    49,    -1,    69,    -1,    79,    -1,    10,    28, +      32,    -1,    46,    50,    -1,    11,    28,    32,    -1,    48, +      50,    -1,    -1,    50,    51,    -1,    50,    75,    -1,    50, +      73,    -1,    50,    32,    -1,    21,    76,    32,    -1,    22, +      81,    80,    32,    -1,    23,    76,    32,    -1,    24,    81, +      80,    32,    -1,    26,    76,    32,    -1,    27,    76,    32, +      -1,    25,    76,    32,    -1,    19,    77,    80,    32,    -1, +      20,    81,    80,    32,    -1,    36,    28,    80,    32,    -1, +      37,    82,    82,    80,    32,    -1,     7,    32,    -1,    52, +      56,    -1,    78,    -1,    53,    58,    54,    -1,    53,    58, +      -1,    -1,    56,    57,    -1,    56,    75,    -1,    56,    73, +      -1,    56,    32,    -1,    19,    77,    80,    32,    -1,    21, +      76,    32,    -1,    23,    76,    32,    -1,    18,    32,    -1, +      20,    28,    80,    32,    -1,    -1,    58,    45,    -1,    14, +      81,    32,    -1,    78,    -1,    59,    62,    60,    -1,    59, +      62,    -1,    -1,    62,    45,    -1,    62,    66,    -1,    62, +      55,    -1,     4,    77,    32,    -1,    63,    74,    -1,    78, +      -1,    64,    67,    65,    -1,    64,    67,    -1,    -1,    67, +      45,    -1,    67,    66,    -1,    67,    55,    -1,    67,     1, +      32,    -1,     6,    77,    32,    -1,    68,    -1,     9,    77, +      32,    -1,    70,    74,    -1,    12,    32,    -1,    72,    13, +      -1,    -1,    74,    75,    -1,    74,    32,    -1,    16,    35, +      81,    32,    -1,    16,    81,    32,    -1,    17,    81,    32, +      -1,    -1,    77,    80,    -1,    28,    -1,    29,    -1,     5, +      79,    -1,     8,    79,    -1,    15,    79,    -1,    32,    -1, +      31,    -1,    -1,    14,    81,    -1,    82,    -1,    82,    40, +      82,    -1,    82,    30,    82,    -1,    34,    81,    33,    -1, +      41,    81,    -1,    81,    38,    81,    -1,    81,    39,    81, +      -1,    28,    -1,    29,    -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */ +static const unsigned short yyrline[] = +{ +       0,    94,    94,    95,    98,    99,   100,   101,   102,   103, +     104,   105,   109,   110,   111,   112,   113,   114,   120,   128, +     134,   142,   152,   154,   155,   156,   157,   160,   166,   173, +     179,   186,   192,   198,   204,   210,   216,   222,   230,   239, +     245,   254,   255,   261,   263,   264,   265,   266,   269,   275, +     281,   287,   293,   299,   301,   306,   315,   324,   325,   331, +     333,   334,   335,   340,   347,   353,   362,   363,   369,   371, +     372,   373,   374,   377,   383,   390,   397,   404,   410,   417, +     418,   419,   422,   427,   432,   440,   442,   447,   448,   451, +     452,   453,   457,   457,   459,   460,   463,   464,   465,   466, +     467,   468,   469,   472,   473 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. +   First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ +  "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU",  +  "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",  +  "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",  +  "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE",  +  "T_DEF_TRISTATE", "T_BOOLEAN", "T_DEF_BOOLEAN", "T_STRING", "T_INT",  +  "T_HEX", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", "T_EOF", "T_EOL",  +  "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", "T_SELECT", "T_RANGE", "T_OR",  +  "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block",  +  "common_block", "config_entry_start", "config_stmt",  +  "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",  +  "config_option", "choice", "choice_entry", "choice_end", "choice_stmt",  +  "choice_option_list", "choice_option", "choice_block", "if", "if_end",  +  "if_stmt", "if_block", "menu", "menu_entry", "menu_end", "menu_stmt",  +  "menu_block", "source", "source_stmt", "comment", "comment_stmt",  +  "help_start", "help", "depends_list", "depends", "prompt_stmt_opt",  +  "prompt", "end", "nl_or_eof", "if_expr", "expr", "symbol", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to +   token YYLEX-NUM.  */ +static const unsigned short yytoknum[] = +{ +       0,   256,   257,   258,   259,   260,   261,   262,   263,   264, +     265,   266,   267,   268,   269,   270,   271,   272,   273,   274, +     275,   276,   277,   278,   279,   280,   281,   282,   283,   284, +     285,   286,   287,   288,   289,   290,   291,   292,   293,   294, +     295,   296 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */ +static const unsigned char yyr1[] = +{ +       0,    42,    43,    43,    44,    44,    44,    44,    44,    44, +      44,    44,    45,    45,    45,    45,    45,    45,    46,    47, +      48,    49,    50,    50,    50,    50,    50,    51,    51,    51, +      51,    51,    51,    51,    51,    51,    51,    51,    52,    53, +      54,    55,    55,    56,    56,    56,    56,    56,    57,    57, +      57,    57,    57,    58,    58,    59,    60,    61,    61,    62, +      62,    62,    62,    63,    64,    65,    66,    66,    67,    67, +      67,    67,    67,    68,    69,    70,    71,    72,    73,    74, +      74,    74,    75,    75,    75,    76,    76,    77,    77,    78, +      78,    78,    79,    79,    80,    80,    81,    81,    81,    81, +      81,    81,    81,    82,    82 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */ +static const unsigned char yyr2[] = +{ +       0,     2,     0,     2,     1,     1,     1,     3,     1,     1, +       1,     2,     1,     1,     1,     1,     1,     1,     3,     2, +       3,     2,     0,     2,     2,     2,     2,     3,     4,     3, +       4,     3,     3,     3,     4,     4,     4,     5,     2,     2, +       1,     3,     2,     0,     2,     2,     2,     2,     4,     3, +       3,     2,     4,     0,     2,     3,     1,     3,     2,     0, +       2,     2,     2,     3,     2,     1,     3,     2,     0,     2, +       2,     2,     3,     3,     1,     3,     2,     2,     2,     0, +       2,     2,     4,     3,     3,     0,     2,     1,     1,     2, +       2,     2,     1,     1,     0,     2,     1,     3,     3,     3, +       2,     3,     3,     1,     1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state +   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero +   means the default is an error.  */ +static const unsigned char yydefact[] = +{ +       2,     0,     1,     0,     0,     0,     8,     0,     0,    10, +       0,     0,     0,     0,     9,    93,    92,     3,     4,    22, +      14,    22,    15,    43,    53,     5,    59,    12,    79,    68, +       6,    74,    16,    79,    13,    17,    11,    87,    88,     0, +       0,     0,    38,     0,     0,     0,   103,   104,     0,     0, +       0,    96,    19,    21,    39,    42,    58,    64,     0,    76, +       7,    63,    73,    75,    18,    20,     0,   100,    55,     0, +       0,     0,     0,     0,     0,     0,     0,     0,    85,     0, +      85,     0,    85,    85,    85,    26,     0,     0,    23,     0, +      25,    24,     0,     0,     0,    85,    85,    47,    44,    46, +      45,     0,     0,     0,    54,    41,    40,    60,    62,    57, +      61,    56,    81,    80,     0,    69,    71,    66,    70,    65, +      99,   101,   102,    98,    97,    77,     0,     0,     0,    94, +      94,     0,    94,    94,     0,    94,     0,     0,     0,    94, +       0,    78,    51,    94,    94,     0,     0,    89,    90,    91, +      72,     0,    83,    84,     0,     0,     0,    27,    86,     0, +      29,     0,    33,    31,    32,     0,    94,     0,     0,    49, +      50,    82,    95,    34,    35,    28,    30,    36,     0,    48, +      52,    37 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const short yydefgoto[] = +{ +      -1,     1,    17,    18,    19,    20,    21,    22,    52,    88, +      23,    24,   105,    25,    54,    98,    55,    26,   109,    27, +      56,    28,    29,   117,    30,    58,    31,    32,    33,    34, +      89,    90,    57,    91,   131,   132,   106,    35,   155,    50, +      51 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing +   STATE-NUM.  */ +#define YYPACT_NINF -99 +static const short yypact[] = +{ +     -99,    48,   -99,    38,    46,    46,   -99,    46,   -29,   -99, +      46,   -17,    -3,   -11,   -99,   -99,   -99,   -99,   -99,   -99, +     -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99, +     -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,    38, +      12,    15,   -99,    18,    51,    62,   -99,   -99,   -11,   -11, +       4,   -24,   138,   138,   160,   121,   110,    -4,    81,    -4, +     -99,   -99,   -99,   -99,   -99,   -99,   -19,   -99,   -99,   -11, +     -11,    70,    70,    73,    32,   -11,    46,   -11,    46,   -11, +      46,   -11,    46,    46,    46,   -99,    36,    70,   -99,    95, +     -99,   -99,    96,    46,   106,    46,    46,   -99,   -99,   -99, +     -99,    38,    38,    38,   -99,   -99,   -99,   -99,   -99,   -99, +     -99,   -99,   -99,   -99,   112,   -99,   -99,   -99,   -99,   -99, +     -99,   117,   -99,   -99,   -99,   -99,   -11,    33,    65,   131, +       1,   119,   131,     1,   136,     1,   153,   154,   155,   131, +      70,   -99,   -99,   131,   131,   156,   157,   -99,   -99,   -99, +     -99,   101,   -99,   -99,   -11,   158,   159,   -99,   -99,   161, +     -99,   162,   -99,   -99,   -99,   163,   131,   164,   165,   -99, +     -99,   -99,    99,   -99,   -99,   -99,   -99,   -99,   166,   -99, +     -99,   -99 +}; + +/* YYPGOTO[NTERM-NUM].  */ +static const short yypgoto[] = +{ +     -99,   -99,   -99,   111,   -99,   -99,   -99,   -99,   178,   -99, +     -99,   -99,   -99,    91,   -99,   -99,   -99,   -99,   -99,   -99, +     -99,   -99,   -99,   -99,   115,   -99,   -99,   -99,   -99,   -99, +     -99,   146,   168,    89,    27,     0,   126,    -1,   -98,   -48, +     -63 +}; + +/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If +   positive, shift that token.  If negative, reduce the rule which +   number is the opposite.  If zero, do what YYDEFACT says. +   If YYTABLE_NINF, syntax error.  */ +#define YYTABLE_NINF -68 +static const short yytable[] = +{ +      66,    67,    36,    42,    39,    40,    71,    41,   123,   124, +      43,    44,    74,    75,   120,   154,    72,    46,    47,    69, +      70,   121,   122,    48,   140,    45,   127,   128,   112,   130, +      49,   133,   156,   135,   158,   159,    68,   161,    60,    69, +      70,   165,    69,    70,    61,   167,   168,    62,     2,     3, +      63,     4,     5,     6,     7,     8,     9,    10,    11,    12, +      46,    47,    13,    14,   139,   152,    48,   126,   178,    15, +      16,    69,    70,    49,    37,    38,   129,   166,   151,    15, +      16,   -67,   114,    64,   -67,     5,   101,     7,     8,   102, +      10,    11,    12,   143,    65,    13,   103,   153,    46,    47, +     147,   148,   149,    69,    70,   125,   172,   134,   141,   136, +     137,   138,    15,    16,     5,   101,     7,     8,   102,    10, +      11,    12,   145,   146,    13,   103,   101,     7,   142,   102, +      10,    11,    12,   171,   144,    13,   103,    69,    70,    69, +      70,    15,    16,   100,   150,   154,   113,   108,   113,   116, +      73,   157,    15,    16,    74,    75,    70,    76,    77,    78, +      79,    80,    81,    82,    83,    84,   104,   107,   160,   115, +      85,   110,    73,   118,    86,    87,    74,    75,    92,    93, +      94,    95,   111,    96,   119,   162,   163,   164,   169,   170, +     173,   174,    97,   175,   176,   177,   179,   180,   181,    53, +      99,    59 +}; + +static const unsigned char yycheck[] = +{ +      48,    49,     3,    32,     4,     5,    30,     7,    71,    72, +      10,    28,    16,    17,    33,    14,    40,    28,    29,    38, +      39,    69,    70,    34,    87,    28,    74,    75,    32,    77, +      41,    79,   130,    81,   132,   133,    32,   135,    39,    38, +      39,   139,    38,    39,    32,   143,   144,    32,     0,     1, +      32,     3,     4,     5,     6,     7,     8,     9,    10,    11, +      28,    29,    14,    15,    28,    32,    34,    35,   166,    31, +      32,    38,    39,    41,    28,    29,    76,   140,   126,    31, +      32,     0,     1,    32,     3,     4,     5,     6,     7,     8, +       9,    10,    11,    93,    32,    14,    15,    32,    28,    29, +     101,   102,   103,    38,    39,    32,   154,    80,    13,    82, +      83,    84,    31,    32,     4,     5,     6,     7,     8,     9, +      10,    11,    95,    96,    14,    15,     5,     6,    32,     8, +       9,    10,    11,    32,    28,    14,    15,    38,    39,    38, +      39,    31,    32,    54,    32,    14,    57,    56,    59,    58, +      12,    32,    31,    32,    16,    17,    39,    19,    20,    21, +      22,    23,    24,    25,    26,    27,    55,    56,    32,    58, +      32,    56,    12,    58,    36,    37,    16,    17,    18,    19, +      20,    21,    56,    23,    58,    32,    32,    32,    32,    32, +      32,    32,    32,    32,    32,    32,    32,    32,    32,    21, +      54,    33 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing +   symbol of state STATE-NUM.  */ +static const unsigned char yystos[] = +{ +       0,    43,     0,     1,     3,     4,     5,     6,     7,     8, +       9,    10,    11,    14,    15,    31,    32,    44,    45,    46, +      47,    48,    49,    52,    53,    55,    59,    61,    63,    64, +      66,    68,    69,    70,    71,    79,    79,    28,    29,    77, +      77,    77,    32,    77,    28,    28,    28,    29,    34,    41, +      81,    82,    50,    50,    56,    58,    62,    74,    67,    74, +      79,    32,    32,    32,    32,    32,    81,    81,    32,    38, +      39,    30,    40,    12,    16,    17,    19,    20,    21,    22, +      23,    24,    25,    26,    27,    32,    36,    37,    51,    72, +      73,    75,    18,    19,    20,    21,    23,    32,    57,    73, +      75,     5,     8,    15,    45,    54,    78,    45,    55,    60, +      66,    78,    32,    75,     1,    45,    55,    65,    66,    78, +      33,    81,    81,    82,    82,    32,    35,    81,    81,    77, +      81,    76,    77,    81,    76,    81,    76,    76,    76,    28, +      82,    13,    32,    77,    28,    76,    76,    79,    79,    79, +      32,    81,    32,    32,    14,    80,    80,    32,    80,    80, +      32,    80,    32,    32,    32,    80,    82,    80,    80,    32, +      32,    32,    81,    32,    32,    32,    32,    32,    80,    32, +      32,    32 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +#  define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok		(yyerrstatus = 0) +#define yyclearin	(yychar = YYEMPTY) +#define YYEMPTY		(-2) +#define YYEOF		0 + +#define YYACCEPT	goto yyacceptlab +#define YYABORT		goto yyabortlab +#define YYERROR		goto yyerrlab1 + + +/* Like YYERROR except do call yyerror.  This remains here temporarily +   to ease the transition to the new meaning of YYERROR, for GCC. +   Once GCC version 2 has supplanted version 1, this can go.  */ + +#define YYFAIL		goto yyerrlab + +#define YYRECOVERING()  (!!yyerrstatus) + +#define YYBACKUP(Token, Value)					\ +do								\ +  if (yychar == YYEMPTY && yylen == 1)				\ +    {								\ +      yychar = (Token);						\ +      yylval = (Value);						\ +      yytoken = YYTRANSLATE (yychar);				\ +      YYPOPSTACK;						\ +      goto yybackup;						\ +    }								\ +  else								\ +    { 								\ +      yyerror ("syntax error: cannot back up");\ +      YYERROR;							\ +    }								\ +while (0) + +#define YYTERROR	1 +#define YYERRCODE	256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions +   are run).  */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N)         \ +  Current.first_line   = Rhs[1].first_line;      \ +  Current.first_column = Rhs[1].first_column;    \ +  Current.last_line    = Rhs[N].last_line;       \ +  Current.last_column  = Rhs[N].last_column; +#endif + +/* YYLEX -- calling `yylex' with the right arguments.  */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested.  */ +#if YYDEBUG + +# ifndef YYFPRINTF +#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +#  define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args)			\ +do {						\ +  if (yydebug)					\ +    YYFPRINTF Args;				\ +} while (0) + +# define YYDSYMPRINT(Args)			\ +do {						\ +  if (yydebug)					\ +    yysymprint Args;				\ +} while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location)		\ +do {								\ +  if (yydebug)							\ +    {								\ +      YYFPRINTF (stderr, "%s ", Title);				\ +      yysymprint (stderr, 					\ +                  Token, Value);	\ +      YYFPRINTF (stderr, "\n");					\ +    }								\ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (cinluded).                                                   | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short *bottom, short *top) +#else +static void +yy_stack_print (bottom, top) +    short *bottom; +    short *top; +#endif +{ +  YYFPRINTF (stderr, "Stack now"); +  for (/* Nothing. */; bottom <= top; ++bottom) +    YYFPRINTF (stderr, " %d", *bottom); +  YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top)				\ +do {								\ +  if (yydebug)							\ +    yy_stack_print ((Bottom), (Top));				\ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced.  | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) +    int yyrule; +#endif +{ +  int yyi; +  unsigned int yylineno = yyrline[yyrule]; +  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", +             yyrule - 1, yylineno); +  /* Print the symbols being reduced, and their result.  */ +  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) +    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); +  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule)		\ +do {					\ +  if (yydebug)				\ +    yy_reduce_print (Rule);		\ +} while (0) + +/* Nonzero means print parse trace.  It is left uninitialized so that +   multiple parsers can coexist.  */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks.  */ +#ifndef	YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only +   if the built-in stack extension method is used). + +   Do not make this value too large; the results are undefined if +   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) +   evaluated with infinite-precision integer arithmetic.  */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +#  if defined (__GLIBC__) && defined (_STRING_H) +#   define yystrlen strlen +#  else +/* Return the length of YYSTR.  */ +static YYSIZE_T +#   if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +#   else +yystrlen (yystr) +     const char *yystr; +#   endif +{ +  register const char *yys = yystr; + +  while (*yys++ != '\0') +    continue; + +  return yys - yystr - 1; +} +#  endif +# endif + +# ifndef yystpcpy +#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +#   define yystpcpy stpcpy +#  else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in +   YYDEST.  */ +static char * +#   if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +#   else +yystpcpy (yydest, yysrc) +     char *yydest; +     const char *yysrc; +#   endif +{ +  register char *yyd = yydest; +  register const char *yys = yysrc; + +  while ((*yyd++ = *yys++) != '\0') +    continue; + +  return yyd - 1; +} +#  endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT.  | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) +    FILE *yyoutput; +    int yytype; +    YYSTYPE *yyvaluep; +#endif +{ +  /* Pacify ``unused variable'' warnings.  */ +  (void) yyvaluep; + +  if (yytype < YYNTOKENS) +    { +      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); +# ifdef YYPRINT +      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif +    } +  else +    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + +  switch (yytype) +    { +      default: +        break; +    } +  YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol.  | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yytype, yyvaluep) +    int yytype; +    YYSTYPE *yyvaluep; +#endif +{ +  /* Pacify ``unused variable'' warnings.  */ +  (void) yyvaluep; + +  switch (yytype) +    { + +      default: +        break; +    } +} + + +/* Prevent warnings from -Wmissing-prototypes.  */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The lookahead symbol.  */ +int yychar; + +/* The semantic value of the lookahead symbol.  */ +YYSTYPE yylval; + +/* Number of syntax errors so far.  */ +int yynerrs; + + + +/*----------. +| yyparse.  | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) +  void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ +   +  register int yystate; +  register int yyn; +  int yyresult; +  /* Number of tokens to shift before error messages enabled.  */ +  int yyerrstatus; +  /* Lookahead token as an internal (translated) token number.  */ +  int yytoken = 0; + +  /* Three stacks and their tools: +     `yyss': related to states, +     `yyvs': related to semantic values, +     `yyls': related to locations. + +     Refer to the stacks thru separate pointers, to allow yyoverflow +     to reallocate them elsewhere.  */ + +  /* The state stack.  */ +  short	yyssa[YYINITDEPTH]; +  short *yyss = yyssa; +  register short *yyssp; + +  /* The semantic value stack.  */ +  YYSTYPE yyvsa[YYINITDEPTH]; +  YYSTYPE *yyvs = yyvsa; +  register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK   (yyvsp--, yyssp--) + +  YYSIZE_T yystacksize = YYINITDEPTH; + +  /* The variables used to return semantic value and location from the +     action routines.  */ +  YYSTYPE yyval; + + +  /* When reducing, the number of symbols on the RHS of the reduced +     rule.  */ +  int yylen; + +  YYDPRINTF ((stderr, "Starting parse\n")); + +  yystate = 0; +  yyerrstatus = 0; +  yynerrs = 0; +  yychar = YYEMPTY;		/* Cause a token to be read.  */ + +  /* Initialize stack pointers. +     Waste one element of value and location stack +     so that they stay on the same level as the state stack. +     The wasted elements are never initialized.  */ + +  yyssp = yyss; +  yyvsp = yyvs; + +  goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate.  | +`------------------------------------------------------------*/ + yynewstate: +  /* In all cases, when you get here, the value and location stacks +     have just been pushed. so pushing a state here evens the stacks. +     */ +  yyssp++; + + yysetstate: +  *yyssp = yystate; + +  if (yyss + yystacksize - 1 <= yyssp) +    { +      /* Get the current used size of the three stacks, in elements.  */ +      YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow +      { +	/* Give user a chance to reallocate the stack. Use copies of +	   these so that the &'s don't force the real ones into +	   memory.  */ +	YYSTYPE *yyvs1 = yyvs; +	short *yyss1 = yyss; + + +	/* Each stack pointer address is followed by the size of the +	   data in use in that stack, in bytes.  This used to be a +	   conditional around just the two extra args, but that might +	   be undefined if yyoverflow is a macro.  */ +	yyoverflow ("parser stack overflow", +		    &yyss1, yysize * sizeof (*yyssp), +		    &yyvs1, yysize * sizeof (*yyvsp), + +		    &yystacksize); + +	yyss = yyss1; +	yyvs = yyvs1; +      } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE +      goto yyoverflowlab; +# else +      /* Extend the stack our own way.  */ +      if (YYMAXDEPTH <= yystacksize) +	goto yyoverflowlab; +      yystacksize *= 2; +      if (YYMAXDEPTH < yystacksize) +	yystacksize = YYMAXDEPTH; + +      { +	short *yyss1 = yyss; +	union yyalloc *yyptr = +	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); +	if (! yyptr) +	  goto yyoverflowlab; +	YYSTACK_RELOCATE (yyss); +	YYSTACK_RELOCATE (yyvs); + +#  undef YYSTACK_RELOCATE +	if (yyss1 != yyssa) +	  YYSTACK_FREE (yyss1); +      } +# endif +#endif /* no yyoverflow */ + +      yyssp = yyss + yysize - 1; +      yyvsp = yyvs + yysize - 1; + + +      YYDPRINTF ((stderr, "Stack size increased to %lu\n", +		  (unsigned long int) yystacksize)); + +      if (yyss + yystacksize - 1 <= yyssp) +	YYABORT; +    } + +  YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + +  goto yybackup; + +/*-----------. +| yybackup.  | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state.  */ +/* Read a lookahead token if we need one and don't already have one.  */ +/* yyresume: */ + +  /* First try to decide what to do without reference to lookahead token.  */ + +  yyn = yypact[yystate]; +  if (yyn == YYPACT_NINF) +    goto yydefault; + +  /* Not known => get a lookahead token if don't already have one.  */ + +  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */ +  if (yychar == YYEMPTY) +    { +      YYDPRINTF ((stderr, "Reading a token: ")); +      yychar = YYLEX; +    } + +  if (yychar <= YYEOF) +    { +      yychar = yytoken = YYEOF; +      YYDPRINTF ((stderr, "Now at end of input.\n")); +    } +  else +    { +      yytoken = YYTRANSLATE (yychar); +      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); +    } + +  /* If the proper action on seeing token YYTOKEN is to reduce or to +     detect an error, take that action.  */ +  yyn += yytoken; +  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) +    goto yydefault; +  yyn = yytable[yyn]; +  if (yyn <= 0) +    { +      if (yyn == 0 || yyn == YYTABLE_NINF) +	goto yyerrlab; +      yyn = -yyn; +      goto yyreduce; +    } + +  if (yyn == YYFINAL) +    YYACCEPT; + +  /* Shift the lookahead token.  */ +  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); + +  /* Discard the token being shifted unless it is eof.  */ +  if (yychar != YYEOF) +    yychar = YYEMPTY; + +  *++yyvsp = yylval; + + +  /* Count tokens shifted since error; after three, turn off error +     status.  */ +  if (yyerrstatus) +    yyerrstatus--; + +  yystate = yyn; +  goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state.  | +`-----------------------------------------------------------*/ +yydefault: +  yyn = yydefact[yystate]; +  if (yyn == 0) +    goto yyerrlab; +  goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction.  | +`-----------------------------*/ +yyreduce: +  /* yyn is the number of a rule to reduce with.  */ +  yylen = yyr2[yyn]; + +  /* If YYLEN is nonzero, implement the default value of the action: +     `$$ = $1'. + +     Otherwise, the following line sets YYVAL to garbage. +     This behavior is undocumented and Bison +     users should not rely upon it.  Assigning to YYVAL +     unconditionally makes the parser a bit smaller, and it avoids a +     GCC warning that YYVAL may be used uninitialized.  */ +  yyval = yyvsp[1-yylen]; + + +  YY_REDUCE_PRINT (yyn); +  switch (yyn) +    { +        case 8: + +    { zconfprint("unexpected 'endmenu' statement"); ;} +    break; + +  case 9: + +    { zconfprint("unexpected 'endif' statement"); ;} +    break; + +  case 10: + +    { zconfprint("unexpected 'endchoice' statement"); ;} +    break; + +  case 11: + +    { zconfprint("syntax error"); yyerrok; ;} +    break; + +  case 18: + +    { +	struct symbol *sym = sym_lookup(yyvsp[-1].string, 0); +	sym->flags |= SYMBOL_OPTIONAL; +	menu_add_entry(sym); +	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string); +;} +    break; + +  case 19: + +    { +	menu_end_entry(); +	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 20: + +    { +	struct symbol *sym = sym_lookup(yyvsp[-1].string, 0); +	sym->flags |= SYMBOL_OPTIONAL; +	menu_add_entry(sym); +	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string); +;} +    break; + +  case 21: + +    { +	if (current_entry->prompt) +		current_entry->prompt->type = P_MENU; +	else +		zconfprint("warning: menuconfig statement without prompt"); +	menu_end_entry(); +	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 27: + +    { +	menu_set_type(S_TRISTATE); +	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 28: + +    { +	menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr); +	menu_set_type(S_TRISTATE); +	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 29: + +    { +	menu_set_type(S_BOOLEAN); +	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 30: + +    { +	menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr); +	menu_set_type(S_BOOLEAN); +	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 31: + +    { +	menu_set_type(S_INT); +	printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 32: + +    { +	menu_set_type(S_HEX); +	printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 33: + +    { +	menu_set_type(S_STRING); +	printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 34: + +    { +	menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr); +	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 35: + +    { +	menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr); +	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 36: + +    { +	menu_add_symbol(P_SELECT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr); +	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 37: + +    { +	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,yyvsp[-3].symbol, yyvsp[-2].symbol), yyvsp[-1].expr); +	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 38: + +    { +	struct symbol *sym = sym_lookup(NULL, 0); +	sym->flags |= SYMBOL_CHOICE; +	menu_add_entry(sym); +	menu_add_expr(P_CHOICE, NULL, NULL); +	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 39: + +    { +	menu_end_entry(); +	menu_add_menu(); +;} +    break; + +  case 40: + +    { +	if (zconf_endtoken(yyvsp[0].token, T_CHOICE, T_ENDCHOICE)) { +		menu_end_menu(); +		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); +	} +;} +    break; + +  case 42: + +    { +	printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno); +	zconfnerrs++; +;} +    break; + +  case 48: + +    { +	menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr); +	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 49: + +    { +	menu_set_type(S_TRISTATE); +	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 50: + +    { +	menu_set_type(S_BOOLEAN); +	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 51: + +    { +	current_entry->sym->flags |= SYMBOL_OPTIONAL; +	printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 52: + +    { +	menu_add_symbol(P_DEFAULT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr); +	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 55: + +    { +	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); +	menu_add_entry(NULL); +	menu_add_dep(yyvsp[-1].expr); +	menu_end_entry(); +	menu_add_menu(); +;} +    break; + +  case 56: + +    { +	if (zconf_endtoken(yyvsp[0].token, T_IF, T_ENDIF)) { +		menu_end_menu(); +		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); +	} +;} +    break; + +  case 58: + +    { +	printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno); +	zconfnerrs++; +;} +    break; + +  case 63: + +    { +	menu_add_entry(NULL); +	menu_add_prop(P_MENU, yyvsp[-1].string, NULL, NULL); +	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 64: + +    { +	menu_end_entry(); +	menu_add_menu(); +;} +    break; + +  case 65: + +    { +	if (zconf_endtoken(yyvsp[0].token, T_MENU, T_ENDMENU)) { +		menu_end_menu(); +		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); +	} +;} +    break; + +  case 67: + +    { +	printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno); +	zconfnerrs++; +;} +    break; + +  case 72: + +    { zconfprint("invalid menu option"); yyerrok; ;} +    break; + +  case 73: + +    { +	yyval.string = yyvsp[-1].string; +	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string); +;} +    break; + +  case 74: + +    { +	zconf_nextfile(yyvsp[0].string); +;} +    break; + +  case 75: + +    { +	menu_add_entry(NULL); +	menu_add_prop(P_COMMENT, yyvsp[-1].string, NULL, NULL); +	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 76: + +    { +	menu_end_entry(); +;} +    break; + +  case 77: + +    { +	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); +	zconf_starthelp(); +;} +    break; + +  case 78: + +    { +	current_entry->sym->help = yyvsp[0].string; +;} +    break; + +  case 82: + +    { +	menu_add_dep(yyvsp[-1].expr); +	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 83: + +    { +	menu_add_dep(yyvsp[-1].expr); +	printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 84: + +    { +	menu_add_dep(yyvsp[-1].expr); +	printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno()); +;} +    break; + +  case 86: + +    { +	menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr); +;} +    break; + +  case 89: + +    { yyval.token = T_ENDMENU; ;} +    break; + +  case 90: + +    { yyval.token = T_ENDCHOICE; ;} +    break; + +  case 91: + +    { yyval.token = T_ENDIF; ;} +    break; + +  case 94: + +    { yyval.expr = NULL; ;} +    break; + +  case 95: + +    { yyval.expr = yyvsp[0].expr; ;} +    break; + +  case 96: + +    { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); ;} +    break; + +  case 97: + +    { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;} +    break; + +  case 98: + +    { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;} +    break; + +  case 99: + +    { yyval.expr = yyvsp[-1].expr; ;} +    break; + +  case 100: + +    { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); ;} +    break; + +  case 101: + +    { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); ;} +    break; + +  case 102: + +    { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); ;} +    break; + +  case 103: + +    { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); ;} +    break; + +  case 104: + +    { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); ;} +    break; + + +    } + +/* Line 999 of yacc.c.  */ + + +  yyvsp -= yylen; +  yyssp -= yylen; + + +  YY_STACK_PRINT (yyss, yyssp); + +  *++yyvsp = yyval; + + +  /* Now `shift' the result of the reduction.  Determine what state +     that goes to, based on the state we popped back to and the rule +     number reduced by.  */ + +  yyn = yyr1[yyn]; + +  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; +  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) +    yystate = yytable[yystate]; +  else +    yystate = yydefgoto[yyn - YYNTOKENS]; + +  goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: +  /* If not already recovering from an error, report this error.  */ +  if (!yyerrstatus) +    { +      ++yynerrs; +#if YYERROR_VERBOSE +      yyn = yypact[yystate]; + +      if (YYPACT_NINF < yyn && yyn < YYLAST) +	{ +	  YYSIZE_T yysize = 0; +	  int yytype = YYTRANSLATE (yychar); +	  char *yymsg; +	  int yyx, yycount; + +	  yycount = 0; +	  /* Start YYX at -YYN if negative to avoid negative indexes in +	     YYCHECK.  */ +	  for (yyx = yyn < 0 ? -yyn : 0; +	       yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) +	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) +	      yysize += yystrlen (yytname[yyx]) + 15, yycount++; +	  yysize += yystrlen ("syntax error, unexpected ") + 1; +	  yysize += yystrlen (yytname[yytype]); +	  yymsg = (char *) YYSTACK_ALLOC (yysize); +	  if (yymsg != 0) +	    { +	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); +	      yyp = yystpcpy (yyp, yytname[yytype]); + +	      if (yycount < 5) +		{ +		  yycount = 0; +		  for (yyx = yyn < 0 ? -yyn : 0; +		       yyx < (int) (sizeof (yytname) / sizeof (char *)); +		       yyx++) +		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) +		      { +			const char *yyq = ! yycount ? ", expecting " : " or "; +			yyp = yystpcpy (yyp, yyq); +			yyp = yystpcpy (yyp, yytname[yyx]); +			yycount++; +		      } +		} +	      yyerror (yymsg); +	      YYSTACK_FREE (yymsg); +	    } +	  else +	    yyerror ("syntax error; also virtual memory exhausted"); +	} +      else +#endif /* YYERROR_VERBOSE */ +	yyerror ("syntax error"); +    } + + + +  if (yyerrstatus == 3) +    { +      /* If just tried and failed to reuse lookahead token after an +	 error, discard it.  */ + +      /* Return failure if at end of input.  */ +      if (yychar == YYEOF) +        { +	  /* Pop the error token.  */ +          YYPOPSTACK; +	  /* Pop the rest of the stack.  */ +	  while (yyss < yyssp) +	    { +	      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); +	      yydestruct (yystos[*yyssp], yyvsp); +	      YYPOPSTACK; +	    } +	  YYABORT; +        } + +      YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); +      yydestruct (yytoken, &yylval); +      yychar = YYEMPTY; + +    } + +  /* Else will try to reuse lookahead token after shifting the error +     token.  */ +  goto yyerrlab1; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action.  | +`----------------------------------------------------*/ +yyerrlab1: +  yyerrstatus = 3;	/* Each real token shifted decrements this.  */ + +  for (;;) +    { +      yyn = yypact[yystate]; +      if (yyn != YYPACT_NINF) +	{ +	  yyn += YYTERROR; +	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) +	    { +	      yyn = yytable[yyn]; +	      if (0 < yyn) +		break; +	    } +	} + +      /* Pop the current state because it cannot handle the error token.  */ +      if (yyssp == yyss) +	YYABORT; + +      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); +      yydestruct (yystos[yystate], yyvsp); +      yyvsp--; +      yystate = *--yyssp; + +      YY_STACK_PRINT (yyss, yyssp); +    } + +  if (yyn == YYFINAL) +    YYACCEPT; + +  YYDPRINTF ((stderr, "Shifting error token, ")); + +  *++yyvsp = yylval; + + +  yystate = yyn; +  goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here.  | +`-------------------------------------*/ +yyacceptlab: +  yyresult = 0; +  goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here.  | +`-----------------------------------*/ +yyabortlab: +  yyresult = 1; +  goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here.  | +`----------------------------------------------*/ +yyoverflowlab: +  yyerror ("parser stack overflow"); +  yyresult = 2; +  /* Fall through.  */ +#endif + +yyreturn: +#ifndef yyoverflow +  if (yyss != yyssa) +    YYSTACK_FREE (yyss); +#endif +  return yyresult; +} + + + + + +void conf_parse(const char *name) +{ +	struct symbol *sym; +	int i; + +	zconf_initscan(name); + +	sym_init(); +	menu_init(); +	modules_sym = sym_lookup("MODULES", 0); +	rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL); + +	//zconfdebug = 1; +	zconfparse(); +	if (zconfnerrs) +		exit(1); +	menu_finalize(&rootmenu); +	for_all_symbols(i, sym) { +                if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym)) +                        printf("\n"); +		else +			sym->flags |= SYMBOL_CHECK_DONE; +        } + +	sym_change_count = 1; +} + +const char *zconf_tokenname(int token) +{ +	switch (token) { +	case T_MENU:		return "menu"; +	case T_ENDMENU:		return "endmenu"; +	case T_CHOICE:		return "choice"; +	case T_ENDCHOICE:	return "endchoice"; +	case T_IF:		return "if"; +	case T_ENDIF:		return "endif"; +	} +	return "<token>"; +} + +static bool zconf_endtoken(int token, int starttoken, int endtoken) +{ +	if (token != endtoken) { +		zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken)); +		zconfnerrs++; +		return false; +	} +	if (current_menu->file != current_file) { +		zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken)); +		zconfprint("location of the '%s'", zconf_tokenname(starttoken)); +		zconfnerrs++; +		return false; +	} +	return true; +} + +static void zconfprint(const char *err, ...) +{ +	va_list ap; + +	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1); +	va_start(ap, err); +	vfprintf(stderr, err, ap); +	va_end(ap); +	fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ +	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +void print_quoted_string(FILE *out, const char *str) +{ +	const char *p; +	int len; + +	putc('"', out); +	while ((p = strchr(str, '"'))) { +		len = p - str; +		if (len) +			fprintf(out, "%.*s", len, str); +		fputs("\\\"", out); +		str = p + 1; +	} +	fputs(str, out); +	putc('"', out); +} + +void print_symbol(FILE *out, struct menu *menu) +{ +	struct symbol *sym = menu->sym; +	struct property *prop; + +	if (sym_is_choice(sym)) +		fprintf(out, "choice\n"); +	else +		fprintf(out, "config %s\n", sym->name); +	switch (sym->type) { +	case S_BOOLEAN: +		fputs("  boolean\n", out); +		break; +	case S_TRISTATE: +		fputs("  tristate\n", out); +		break; +	case S_STRING: +		fputs("  string\n", out); +		break; +	case S_INT: +		fputs("  integer\n", out); +		break; +	case S_HEX: +		fputs("  hex\n", out); +		break; +	default: +		fputs("  ???\n", out); +		break; +	} +	for (prop = sym->prop; prop; prop = prop->next) { +		if (prop->menu != menu) +			continue; +		switch (prop->type) { +		case P_PROMPT: +			fputs("  prompt ", out); +			print_quoted_string(out, prop->text); +			if (!expr_is_yes(prop->visible.expr)) { +				fputs(" if ", out); +				expr_fprint(prop->visible.expr, out); +			} +			fputc('\n', out); +			break; +		case P_DEFAULT: +			fputs( "  default ", out); +			expr_fprint(prop->expr, out); +			if (!expr_is_yes(prop->visible.expr)) { +				fputs(" if ", out); +				expr_fprint(prop->visible.expr, out); +			} +			fputc('\n', out); +			break; +		case P_CHOICE: +			fputs("  #choice value\n", out); +			break; +		default: +			fprintf(out, "  unknown prop %d!\n", prop->type); +			break; +		} +	} +	if (sym->help) { +		int len = strlen(sym->help); +		while (sym->help[--len] == '\n') +			sym->help[len] = 0; +		fprintf(out, "  help\n%s\n", sym->help); +	} +	fputc('\n', out); +} + +void zconfdump(FILE *out) +{ +	struct property *prop; +	struct symbol *sym; +	struct menu *menu; + +	menu = rootmenu.list; +	while (menu) { +		if ((sym = menu->sym)) +			print_symbol(out, menu); +		else if ((prop = menu->prompt)) { +			switch (prop->type) { +			case P_COMMENT: +				fputs("\ncomment ", out); +				print_quoted_string(out, prop->text); +				fputs("\n", out); +				break; +			case P_MENU: +				fputs("\nmenu ", out); +				print_quoted_string(out, prop->text); +				fputs("\n", out); +				break; +			default: +				; +			} +			if (!expr_is_yes(prop->visible.expr)) { +				fputs("  depends ", out); +				expr_fprint(prop->visible.expr, out); +				fputc('\n', out); +			} +			fputs("\n", out); +		} + +		if (menu->list) +			menu = menu->list; +		else if (menu->next) +			menu = menu->next; +		else while ((menu = menu->parent)) { +			if (menu->prompt && menu->prompt->type == P_MENU) +				fputs("\nendmenu\n", out); +			if (menu->next) { +				menu = menu->next; +				break; +			} +		} +	} +} + +#include "lex.zconf.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" + + diff --git a/scripts/kconfig/zconf.tab.h_shipped b/scripts/kconfig/zconf.tab.h_shipped new file mode 100644 index 000000000000..3b191ef59985 --- /dev/null +++ b/scripts/kconfig/zconf.tab.h_shipped @@ -0,0 +1,125 @@ +/* A Bison parser, made from zconf.y, by GNU bison 1.75.  */ + +/* Skeleton parser for Yacc-like parsing with Bison, +   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + +   This program is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published by +   the Free Software Foundation; either version 2, or (at your option) +   any later version. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software +   Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* As a special exception, when this file is copied by Bison into a +   Bison output file, you may use that output file without restriction. +   This special exception was added by the Free Software Foundation +   in version 1.24 of Bison.  */ + +#ifndef BISON_ZCONF_TAB_H +# define BISON_ZCONF_TAB_H + +/* Tokens.  */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE +   /* Put the tokens into the symbol table, so that GDB and other debuggers +      know about them.  */ +   enum yytokentype { +     T_MAINMENU = 258, +     T_MENU = 259, +     T_ENDMENU = 260, +     T_SOURCE = 261, +     T_CHOICE = 262, +     T_ENDCHOICE = 263, +     T_COMMENT = 264, +     T_CONFIG = 265, +     T_HELP = 266, +     T_HELPTEXT = 267, +     T_IF = 268, +     T_ENDIF = 269, +     T_DEPENDS = 270, +     T_REQUIRES = 271, +     T_OPTIONAL = 272, +     T_PROMPT = 273, +     T_DEFAULT = 274, +     T_TRISTATE = 275, +     T_BOOLEAN = 276, +     T_INT = 277, +     T_HEX = 278, +     T_WORD = 279, +     T_STRING = 280, +     T_UNEQUAL = 281, +     T_EOF = 282, +     T_EOL = 283, +     T_CLOSE_PAREN = 284, +     T_OPEN_PAREN = 285, +     T_ON = 286, +     T_OR = 287, +     T_AND = 288, +     T_EQUAL = 289, +     T_NOT = 290 +   }; +#endif +#define T_MAINMENU 258 +#define T_MENU 259 +#define T_ENDMENU 260 +#define T_SOURCE 261 +#define T_CHOICE 262 +#define T_ENDCHOICE 263 +#define T_COMMENT 264 +#define T_CONFIG 265 +#define T_HELP 266 +#define T_HELPTEXT 267 +#define T_IF 268 +#define T_ENDIF 269 +#define T_DEPENDS 270 +#define T_REQUIRES 271 +#define T_OPTIONAL 272 +#define T_PROMPT 273 +#define T_DEFAULT 274 +#define T_TRISTATE 275 +#define T_BOOLEAN 276 +#define T_INT 277 +#define T_HEX 278 +#define T_WORD 279 +#define T_STRING 280 +#define T_UNEQUAL 281 +#define T_EOF 282 +#define T_EOL 283 +#define T_CLOSE_PAREN 284 +#define T_OPEN_PAREN 285 +#define T_ON 286 +#define T_OR 287 +#define T_AND 288 +#define T_EQUAL 289 +#define T_NOT 290 + + + + +#ifndef YYSTYPE +#line 33 "zconf.y" +typedef union { +	int token; +	char *string; +	struct symbol *symbol; +	struct expr *expr; +	struct menu *menu; +} yystype; +/* Line 1281 of /usr/share/bison/yacc.c.  */ +#line 118 "zconf.tab.h" +# define YYSTYPE yystype +#endif + +extern YYSTYPE zconflval; + + +#endif /* not BISON_ZCONF_TAB_H */ + diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y new file mode 100644 index 000000000000..54460f8d3696 --- /dev/null +++ b/scripts/kconfig/zconf.y @@ -0,0 +1,690 @@ +%{ +/* + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> + * Released under the terms of the GNU GPL v2.0. + */ + +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD		0x0001 +#define DEBUG_PARSE	0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(int token, int starttoken, int endtoken); + +struct symbol *symbol_hash[257]; + +static struct menu *current_menu, *current_entry; + +#define YYERROR_VERBOSE +%} +%expect 40 + +%union +{ +	int token; +	char *string; +	struct symbol *symbol; +	struct expr *expr; +	struct menu *menu; +} + +%token T_MAINMENU +%token T_MENU +%token T_ENDMENU +%token T_SOURCE +%token T_CHOICE +%token T_ENDCHOICE +%token T_COMMENT +%token T_CONFIG +%token T_MENUCONFIG +%token T_HELP +%token <string> T_HELPTEXT +%token T_IF +%token T_ENDIF +%token T_DEPENDS +%token T_REQUIRES +%token T_OPTIONAL +%token T_PROMPT +%token T_DEFAULT +%token T_TRISTATE +%token T_DEF_TRISTATE +%token T_BOOLEAN +%token T_DEF_BOOLEAN +%token T_STRING +%token T_INT +%token T_HEX +%token <string> T_WORD +%token <string> T_WORD_QUOTE +%token T_UNEQUAL +%token T_EOF +%token T_EOL +%token T_CLOSE_PAREN +%token T_OPEN_PAREN +%token T_ON +%token T_SELECT +%token T_RANGE + +%left T_OR +%left T_AND +%left T_EQUAL T_UNEQUAL +%nonassoc T_NOT + +%type <string> prompt +%type <string> source +%type <symbol> symbol +%type <expr> expr +%type <expr> if_expr +%type <token> end + +%{ +#define LKC_DIRECT_LINK +#include "lkc.h" +%} +%% +input:	  /* empty */ +	| input block +; + +block:	  common_block +	| choice_stmt +	| menu_stmt +	| T_MAINMENU prompt nl_or_eof +	| T_ENDMENU		{ zconfprint("unexpected 'endmenu' statement"); } +	| T_ENDIF		{ zconfprint("unexpected 'endif' statement"); } +	| T_ENDCHOICE		{ zconfprint("unexpected 'endchoice' statement"); } +	| error nl_or_eof	{ zconfprint("syntax error"); yyerrok; } +; + +common_block: +	  if_stmt +	| comment_stmt +	| config_stmt +	| menuconfig_stmt +	| source_stmt +	| nl_or_eof +; + + +/* config/menuconfig entry */ + +config_entry_start: T_CONFIG T_WORD T_EOL +{ +	struct symbol *sym = sym_lookup($2, 0); +	sym->flags |= SYMBOL_OPTIONAL; +	menu_add_entry(sym); +	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +config_stmt: config_entry_start config_option_list +{ +	menu_end_entry(); +	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL +{ +	struct symbol *sym = sym_lookup($2, 0); +	sym->flags |= SYMBOL_OPTIONAL; +	menu_add_entry(sym); +	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +menuconfig_stmt: menuconfig_entry_start config_option_list +{ +	if (current_entry->prompt) +		current_entry->prompt->type = P_MENU; +	else +		zconfprint("warning: menuconfig statement without prompt"); +	menu_end_entry(); +	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +config_option_list: +	  /* empty */ +	| config_option_list config_option +	| config_option_list depends +	| config_option_list help +	| config_option_list T_EOL +; + +config_option: T_TRISTATE prompt_stmt_opt T_EOL +{ +	menu_set_type(S_TRISTATE); +	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_DEF_TRISTATE expr if_expr T_EOL +{ +	menu_add_expr(P_DEFAULT, $2, $3); +	menu_set_type(S_TRISTATE); +	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_BOOLEAN prompt_stmt_opt T_EOL +{ +	menu_set_type(S_BOOLEAN); +	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_DEF_BOOLEAN expr if_expr T_EOL +{ +	menu_add_expr(P_DEFAULT, $2, $3); +	menu_set_type(S_BOOLEAN); +	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_INT prompt_stmt_opt T_EOL +{ +	menu_set_type(S_INT); +	printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_HEX prompt_stmt_opt T_EOL +{ +	menu_set_type(S_HEX); +	printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_STRING prompt_stmt_opt T_EOL +{ +	menu_set_type(S_STRING); +	printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_PROMPT prompt if_expr T_EOL +{ +	menu_add_prompt(P_PROMPT, $2, $3); +	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_DEFAULT expr if_expr T_EOL +{ +	menu_add_expr(P_DEFAULT, $2, $3); +	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_SELECT T_WORD if_expr T_EOL +{ +	menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); +	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_RANGE symbol symbol if_expr T_EOL +{ +	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); +	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +}; + +/* choice entry */ + +choice: T_CHOICE T_EOL +{ +	struct symbol *sym = sym_lookup(NULL, 0); +	sym->flags |= SYMBOL_CHOICE; +	menu_add_entry(sym); +	menu_add_expr(P_CHOICE, NULL, NULL); +	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +}; + +choice_entry: choice choice_option_list +{ +	menu_end_entry(); +	menu_add_menu(); +}; + +choice_end: end +{ +	if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { +		menu_end_menu(); +		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); +	} +}; + +choice_stmt: +	  choice_entry choice_block choice_end +	| choice_entry choice_block +{ +	printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno); +	zconfnerrs++; +}; + +choice_option_list: +	  /* empty */ +	| choice_option_list choice_option +	| choice_option_list depends +	| choice_option_list help +	| choice_option_list T_EOL +; + +choice_option: T_PROMPT prompt if_expr T_EOL +{ +	menu_add_prompt(P_PROMPT, $2, $3); +	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_TRISTATE prompt_stmt_opt T_EOL +{ +	menu_set_type(S_TRISTATE); +	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_BOOLEAN prompt_stmt_opt T_EOL +{ +	menu_set_type(S_BOOLEAN); +	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_OPTIONAL T_EOL +{ +	current_entry->sym->flags |= SYMBOL_OPTIONAL; +	printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_DEFAULT T_WORD if_expr T_EOL +{ +	menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); +	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); +}; + +choice_block: +	  /* empty */ +	| choice_block common_block +; + +/* if entry */ + +if: T_IF expr T_EOL +{ +	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); +	menu_add_entry(NULL); +	menu_add_dep($2); +	menu_end_entry(); +	menu_add_menu(); +}; + +if_end: end +{ +	if (zconf_endtoken($1, T_IF, T_ENDIF)) { +		menu_end_menu(); +		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); +	} +}; + +if_stmt: +	  if if_block if_end +	| if if_block +{ +	printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno); +	zconfnerrs++; +}; + +if_block: +	  /* empty */ +	| if_block common_block +	| if_block menu_stmt +	| if_block choice_stmt +; + +/* menu entry */ + +menu: T_MENU prompt T_EOL +{ +	menu_add_entry(NULL); +	menu_add_prop(P_MENU, $2, NULL, NULL); +	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +}; + +menu_entry: menu depends_list +{ +	menu_end_entry(); +	menu_add_menu(); +}; + +menu_end: end +{ +	if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { +		menu_end_menu(); +		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); +	} +}; + +menu_stmt: +	  menu_entry menu_block menu_end +	| menu_entry menu_block +{ +	printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno); +	zconfnerrs++; +}; + +menu_block: +	  /* empty */ +	| menu_block common_block +	| menu_block menu_stmt +	| menu_block choice_stmt +	| menu_block error T_EOL		{ zconfprint("invalid menu option"); yyerrok; } +; + +source: T_SOURCE prompt T_EOL +{ +	$$ = $2; +	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +source_stmt: source +{ +	zconf_nextfile($1); +}; + +/* comment entry */ + +comment: T_COMMENT prompt T_EOL +{ +	menu_add_entry(NULL); +	menu_add_prop(P_COMMENT, $2, NULL, NULL); +	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +}; + +comment_stmt: comment depends_list +{ +	menu_end_entry(); +}; + +/* help option */ + +help_start: T_HELP T_EOL +{ +	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); +	zconf_starthelp(); +}; + +help: help_start T_HELPTEXT +{ +	current_entry->sym->help = $2; +}; + +/* depends option */ + +depends_list:	  /* empty */ +		| depends_list depends +		| depends_list T_EOL +; + +depends: T_DEPENDS T_ON expr T_EOL +{ +	menu_add_dep($3); +	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +} +	| T_DEPENDS expr T_EOL +{ +	menu_add_dep($2); +	printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno()); +} +	| T_REQUIRES expr T_EOL +{ +	menu_add_dep($2); +	printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno()); +}; + +/* prompt statement */ + +prompt_stmt_opt: +	  /* empty */ +	| prompt if_expr +{ +	menu_add_prop(P_PROMPT, $1, NULL, $2); +}; + +prompt:	  T_WORD +	| T_WORD_QUOTE +; + +end:	  T_ENDMENU nl_or_eof	{ $$ = T_ENDMENU; } +	| T_ENDCHOICE nl_or_eof	{ $$ = T_ENDCHOICE; } +	| T_ENDIF nl_or_eof	{ $$ = T_ENDIF; } +; + +nl_or_eof: +	T_EOL | T_EOF; + +if_expr:  /* empty */			{ $$ = NULL; } +	| T_IF expr			{ $$ = $2; } +; + +expr:	  symbol				{ $$ = expr_alloc_symbol($1); } +	| symbol T_EQUAL symbol			{ $$ = expr_alloc_comp(E_EQUAL, $1, $3); } +	| symbol T_UNEQUAL symbol		{ $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } +	| T_OPEN_PAREN expr T_CLOSE_PAREN	{ $$ = $2; } +	| T_NOT expr				{ $$ = expr_alloc_one(E_NOT, $2); } +	| expr T_OR expr			{ $$ = expr_alloc_two(E_OR, $1, $3); } +	| expr T_AND expr			{ $$ = expr_alloc_two(E_AND, $1, $3); } +; + +symbol:	  T_WORD	{ $$ = sym_lookup($1, 0); free($1); } +	| T_WORD_QUOTE	{ $$ = sym_lookup($1, 1); free($1); } +; + +%% + +void conf_parse(const char *name) +{ +	struct symbol *sym; +	int i; + +	zconf_initscan(name); + +	sym_init(); +	menu_init(); +	modules_sym = sym_lookup("MODULES", 0); +	rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL); + +	//zconfdebug = 1; +	zconfparse(); +	if (zconfnerrs) +		exit(1); +	menu_finalize(&rootmenu); +	for_all_symbols(i, sym) { +                if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym)) +                        printf("\n"); +		else +			sym->flags |= SYMBOL_CHECK_DONE; +        } + +	sym_change_count = 1; +} + +const char *zconf_tokenname(int token) +{ +	switch (token) { +	case T_MENU:		return "menu"; +	case T_ENDMENU:		return "endmenu"; +	case T_CHOICE:		return "choice"; +	case T_ENDCHOICE:	return "endchoice"; +	case T_IF:		return "if"; +	case T_ENDIF:		return "endif"; +	} +	return "<token>"; +} + +static bool zconf_endtoken(int token, int starttoken, int endtoken) +{ +	if (token != endtoken) { +		zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken)); +		zconfnerrs++; +		return false; +	} +	if (current_menu->file != current_file) { +		zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken)); +		zconfprint("location of the '%s'", zconf_tokenname(starttoken)); +		zconfnerrs++; +		return false; +	} +	return true; +} + +static void zconfprint(const char *err, ...) +{ +	va_list ap; + +	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1); +	va_start(ap, err); +	vfprintf(stderr, err, ap); +	va_end(ap); +	fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ +	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +void print_quoted_string(FILE *out, const char *str) +{ +	const char *p; +	int len; + +	putc('"', out); +	while ((p = strchr(str, '"'))) { +		len = p - str; +		if (len) +			fprintf(out, "%.*s", len, str); +		fputs("\\\"", out); +		str = p + 1; +	} +	fputs(str, out); +	putc('"', out); +} + +void print_symbol(FILE *out, struct menu *menu) +{ +	struct symbol *sym = menu->sym; +	struct property *prop; + +	if (sym_is_choice(sym)) +		fprintf(out, "choice\n"); +	else +		fprintf(out, "config %s\n", sym->name); +	switch (sym->type) { +	case S_BOOLEAN: +		fputs("  boolean\n", out); +		break; +	case S_TRISTATE: +		fputs("  tristate\n", out); +		break; +	case S_STRING: +		fputs("  string\n", out); +		break; +	case S_INT: +		fputs("  integer\n", out); +		break; +	case S_HEX: +		fputs("  hex\n", out); +		break; +	default: +		fputs("  ???\n", out); +		break; +	} +	for (prop = sym->prop; prop; prop = prop->next) { +		if (prop->menu != menu) +			continue; +		switch (prop->type) { +		case P_PROMPT: +			fputs("  prompt ", out); +			print_quoted_string(out, prop->text); +			if (!expr_is_yes(prop->visible.expr)) { +				fputs(" if ", out); +				expr_fprint(prop->visible.expr, out); +			} +			fputc('\n', out); +			break; +		case P_DEFAULT: +			fputs( "  default ", out); +			expr_fprint(prop->expr, out); +			if (!expr_is_yes(prop->visible.expr)) { +				fputs(" if ", out); +				expr_fprint(prop->visible.expr, out); +			} +			fputc('\n', out); +			break; +		case P_CHOICE: +			fputs("  #choice value\n", out); +			break; +		default: +			fprintf(out, "  unknown prop %d!\n", prop->type); +			break; +		} +	} +	if (sym->help) { +		int len = strlen(sym->help); +		while (sym->help[--len] == '\n') +			sym->help[len] = 0; +		fprintf(out, "  help\n%s\n", sym->help); +	} +	fputc('\n', out); +} + +void zconfdump(FILE *out) +{ +	struct property *prop; +	struct symbol *sym; +	struct menu *menu; + +	menu = rootmenu.list; +	while (menu) { +		if ((sym = menu->sym)) +			print_symbol(out, menu); +		else if ((prop = menu->prompt)) { +			switch (prop->type) { +			case P_COMMENT: +				fputs("\ncomment ", out); +				print_quoted_string(out, prop->text); +				fputs("\n", out); +				break; +			case P_MENU: +				fputs("\nmenu ", out); +				print_quoted_string(out, prop->text); +				fputs("\n", out); +				break; +			default: +				; +			} +			if (!expr_is_yes(prop->visible.expr)) { +				fputs("  depends ", out); +				expr_fprint(prop->visible.expr, out); +				fputc('\n', out); +			} +			fputs("\n", out); +		} + +		if (menu->list) +			menu = menu->list; +		else if (menu->next) +			menu = menu->next; +		else while ((menu = menu->parent)) { +			if (menu->prompt && menu->prompt->type == P_MENU) +				fputs("\nendmenu\n", out); +			if (menu->next) { +				menu = menu->next; +				break; +			} +		} +	} +} + +#include "lex.zconf.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" diff --git a/scripts/kernel-doc b/scripts/kernel-doc new file mode 100755 index 000000000000..8b1dab63f11c --- /dev/null +++ b/scripts/kernel-doc @@ -0,0 +1,1831 @@ +#!/usr/bin/perl -w + +use strict; + +## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ## +## Copyright (C) 2000, 1  Tim Waugh <twaugh@redhat.com>          ## +## Copyright (C) 2001  Simon Huggins                             ## +## 								 ## +## #define enhancements by Armin Kuster <akuster@mvista.com>	 ## +## Copyright (c) 2000 MontaVista Software, Inc.			 ## +## 								 ## +## This software falls under the GNU General Public License.     ## +## Please read the COPYING file for more information             ## + +# w.o. 03-11-2000: added the '-filelist' option. + +# 18/01/2001 - 	Cleanups +# 		Functions prototyped as foo(void) same as foo() +# 		Stop eval'ing where we don't need to. +# -- huggie@earth.li + +# 27/06/2001 -  Allowed whitespace after initial "/**" and +#               allowed comments before function declarations. +# -- Christian Kreibich <ck@whoop.org> + +# Still to do: +# 	- add perldoc documentation +# 	- Look more closely at some of the scarier bits :) + +# 26/05/2001 - 	Support for separate source and object trees. +#		Return error code. +# 		Keith Owens <kaos@ocs.com.au> + +# 23/09/2001 - Added support for typedefs, structs, enums and unions +#              Support for Context section; can be terminated using empty line +#              Small fixes (like spaces vs. \s in regex) +# -- Tim Jansen <tim@tjansen.de> + + +# +# This will read a 'c' file and scan for embedded comments in the +# style of gnome comments (+minor extensions - see below). +# + +# Note: This only supports 'c'. + +# usage: +# kerneldoc [ -docbook | -html | -text | -man ] +#           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile +# or +#           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile +# +#  Set output format using one of -docbook -html -text or -man.  Default is man. +# +#  -function funcname +#	If set, then only generate documentation for the given function(s).  All +#	other functions are ignored. +# +#  -nofunction funcname +#	If set, then only generate documentation for the other function(s).  All +#	other functions are ignored. Cannot be used with -function together +#	(yes thats a bug - perl hackers can fix it 8)) +# +#  c files - list of 'c' files to process +# +#  All output goes to stdout, with errors to stderr. + +# +# format of comments. +# In the following table, (...)? signifies optional structure. +#                         (...)* signifies 0 or more structure elements +# /** +#  * function_name(:)? (- short description)? +# (* @parameterx: (description of parameter x)?)* +# (* a blank line)? +#  * (Description:)? (Description of function)? +#  * (section header: (section description)? )* +#  (*)?*/ +# +# So .. the trivial example would be: +# +# /** +#  * my_function +#  **/ +# +# If the Description: header tag is ommitted, then there must be a blank line +# after the last parameter specification. +# e.g. +# /** +#  * my_function - does my stuff +#  * @my_arg: its mine damnit +#  * +#  * Does my stuff explained.  +#  */ +# +#  or, could also use: +# /** +#  * my_function - does my stuff +#  * @my_arg: its mine damnit +#  * Description: Does my stuff explained.  +#  */ +# etc. +# +# Beside functions you can also write documentation for structs, unions,  +# enums and typedefs. Instead of the function name you must write the name  +# of the declaration;  the struct/union/enum/typedef must always precede  +# the name. Nesting of declarations is not supported.  +# Use the argument mechanism to document members or constants. +# e.g. +# /** +#  * struct my_struct - short description +#  * @a: first member +#  * @b: second member +#  *  +#  * Longer description +#  */ +# struct my_struct { +#     int a; +#     int b; +# }; +# +# All descriptions can be multiline, except the short function description. +#  +# You can also add additional sections. When documenting kernel functions you  +# should document the "Context:" of the function, e.g. whether the functions  +# can be called form interrupts. Unlike other sections you can end it with an +# empty line.  +# Example-sections should contain the string EXAMPLE so that they are marked  +# appropriately in DocBook. +# +# Example: +# /** +#  * user_function - function that can only be called in user context +#  * @a: some argument +#  * Context: !in_interrupt() +#  *  +#  * Some description +#  * Example: +#  *    user_function(22); +#  */ +# ... +# +# +# All descriptive text is further processed, scanning for the following special +# patterns, which are highlighted appropriately. +# +# 'funcname()' - function +# '$ENVVAR' - environmental variable +# '&struct_name' - name of a structure (up to two words including 'struct') +# '@parameter' - name of a parameter +# '%CONST' - name of a constant. + +my $errors = 0; +my $warnings = 0; + +# match expressions used to find embedded type information +my $type_constant = '\%([-_\w]+)'; +my $type_func = '(\w+)\(\)'; +my $type_param = '\@(\w+)'; +my $type_struct = '\&((struct\s*)?[_\w]+)'; +my $type_env = '(\$\w+)'; + +# Output conversion substitutions. +#  One for each output format + +# these work fairly well +my %highlights_html = ( $type_constant, "<i>\$1</i>", +			$type_func, "<b>\$1</b>", +			$type_struct, "<i>\$1</i>", +			$type_param, "<tt><b>\$1</b></tt>" ); +my $blankline_html = "<p>"; + +# XML, docbook format +my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>", +			$type_constant, "<constant>\$1</constant>", +			$type_func, "<function>\$1</function>", +			$type_struct, "<structname>\$1</structname>", +			$type_env, "<envar>\$1</envar>", +			$type_param, "<parameter>\$1</parameter>" ); +my $blankline_xml = "</para><para>\n"; + +# gnome, docbook format +my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>", +			 $type_func, "<function>\$1</function>", +			 $type_struct, "<structname>\$1</structname>", +			 $type_env, "<envar>\$1</envar>", +			 $type_param, "<parameter>\$1</parameter>" ); +my $blankline_gnome = "</para><para>\n"; + +# these are pretty rough +my %highlights_man = ( $type_constant, "\$1", +		       $type_func, "\\\\fB\$1\\\\fP", +		       $type_struct, "\\\\fI\$1\\\\fP", +		       $type_param, "\\\\fI\$1\\\\fP" ); +my $blankline_man = ""; + +# text-mode +my %highlights_text = ( $type_constant, "\$1", +			$type_func, "\$1", +			$type_struct, "\$1", +			$type_param, "\$1" ); +my $blankline_text = ""; + + +sub usage { +    print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n"; +    print "         [ -function funcname [ -function funcname ...] ]\n"; +    print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n"; +    print "         c source file(s) > outputfile\n"; +    exit 1; +} + +# read arguments +if ($#ARGV==-1) { +    usage(); +} + +my $verbose = 0; +my $output_mode = "man"; +my %highlights = %highlights_man; +my $blankline = $blankline_man; +my $modulename = "Kernel API"; +my $function_only = 0; +my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',  +		'July', 'August', 'September', 'October',  +		'November', 'December')[(localtime)[4]] .  +  " " . ((localtime)[5]+1900); + +# Essentially these are globals +# They probably want to be tidied up made more localised or summat. +# CAVEAT EMPTOR!  Some of the others I localised may not want to be which +# could cause "use of undefined value" or other bugs. +my ($function, %function_table,%parametertypes,$declaration_purpose); +my ($type,$declaration_name,$return_type); +my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map); + +# Generated docbook code is inserted in a template at a point where  +# docbook v3.1 requires a non-zero sequence of RefEntry's; see: +# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html +# We keep track of number of generated entries and generate a dummy +# if needs be to ensure the expanded template can be postprocessed +# into html. +my $section_counter = 0; + +my $lineprefix=""; + +# states +# 0 - normal code +# 1 - looking for function name +# 2 - scanning field start. +# 3 - scanning prototype. +# 4 - documentation block +my $state; + +#declaration types: can be +# 'function', 'struct', 'union', 'enum', 'typedef' +my $decl_type; + +my $doc_special = "\@\%\$\&"; + +my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. +my $doc_end = '\*/'; +my $doc_com = '\s*\*\s*'; +my $doc_decl = $doc_com.'(\w+)'; +my $doc_sect = $doc_com.'(['.$doc_special.']?[\w ]+):(.*)'; +my $doc_content = $doc_com.'(.*)'; +my $doc_block = $doc_com.'DOC:\s*(.*)?'; + +my %constants; +my %parameterdescs; +my @parameterlist; +my %sections; +my @sectionlist; + +my $contents = ""; +my $section_default = "Description";	# default section +my $section_intro = "Introduction"; +my $section = $section_default; +my $section_context = "Context"; + +my $undescribed = "-- undescribed --"; + +reset_state(); + +while ($ARGV[0] =~ m/^-(.*)/) { +    my $cmd = shift @ARGV; +    if ($cmd eq "-html") { +	$output_mode = "html"; +	%highlights = %highlights_html; +	$blankline = $blankline_html; +    } elsif ($cmd eq "-man") { +	$output_mode = "man"; +	%highlights = %highlights_man; +	$blankline = $blankline_man; +    } elsif ($cmd eq "-text") { +	$output_mode = "text"; +	%highlights = %highlights_text; +	$blankline = $blankline_text; +    } elsif ($cmd eq "-docbook") { +	$output_mode = "xml"; +	%highlights = %highlights_xml; +	$blankline = $blankline_xml; +    } elsif ($cmd eq "-gnome") { +	$output_mode = "gnome"; +	%highlights = %highlights_gnome; +	$blankline = $blankline_gnome; +    } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document +	$modulename = shift @ARGV; +    } elsif ($cmd eq "-function") { # to only output specific functions +	$function_only = 1; +	$function = shift @ARGV; +	$function_table{$function} = 1; +    } elsif ($cmd eq "-nofunction") { # to only output specific functions +	$function_only = 2; +	$function = shift @ARGV; +	$function_table{$function} = 1; +    } elsif ($cmd eq "-v") { +	$verbose = 1; +    } elsif (($cmd eq "-h") || ($cmd eq "--help")) { +	usage(); +    } elsif ($cmd eq '-filelist') { +	    $filelist = shift @ARGV; +    } +} + + +# generate a sequence of code that will splice in highlighting information +# using the s// operator. +my $dohighlight = ""; +foreach my $pattern (keys %highlights) { +#    print "scanning pattern $pattern ($highlights{$pattern})\n"; +    $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n"; +} + +## +# dumps section contents to arrays/hashes intended for that purpose. +# +sub dump_section { +    my $name = shift; +    my $contents = join "\n", @_; + +    if ($name =~ m/$type_constant/) { +	$name = $1; +#	print STDERR "constant section '$1' = '$contents'\n"; +	$constants{$name} = $contents; +    } elsif ($name =~ m/$type_param/) { +#	print STDERR "parameter def '$1' = '$contents'\n"; +	$name = $1; +	$parameterdescs{$name} = $contents; +    } else { +#	print STDERR "other section '$name' = '$contents'\n"; +	$sections{$name} = $contents; +	push @sectionlist, $name; +    } +} + +## +# output function +# +# parameterdescs, a hash. +#  function => "function name" +#  parameterlist => @list of parameters +#  parameterdescs => %parameter descriptions +#  sectionlist => @list of sections +#  sections => %descriont descriptions +#   + +sub output_highlight { +    my $contents = join "\n",@_; +    my $line; + +#   DEBUG +#   if (!defined $contents) { +#	use Carp; +#	confess "output_highlight got called with no args?\n"; +#   } + +    eval $dohighlight; +    die $@ if $@; +    foreach $line (split "\n", $contents) { +      if ($line eq ""){ +	    print $lineprefix, $blankline; +	} else { +            $line =~ s/\\\\\\/\&/g; +	    print $lineprefix, $line; +	} +	print "\n"; +    } +} + +#output sections in html +sub output_section_html(%) { +    my %args = %{$_[0]}; +    my $section; + +    foreach $section (@{$args{'sectionlist'}}) { +	print "<h3>$section</h3>\n"; +	print "<blockquote>\n"; +	output_highlight($args{'sections'}{$section}); +	print "</blockquote>\n"; +    }   +} + +# output enum in html +sub output_enum_html(%) { +    my %args = %{$_[0]}; +    my ($parameter); +    my $count; +    print "<h2>enum ".$args{'enum'}."</h2>\n"; + +    print "<b>enum ".$args{'enum'}."</b> {<br>\n"; +    $count = 0; +    foreach $parameter (@{$args{'parameterlist'}}) { +        print " <b>".$parameter."</b>"; +	if ($count != $#{$args{'parameterlist'}}) { +	    $count++; +	    print ",\n"; +	} +	print "<br>"; +    } +    print "};<br>\n"; + +    print "<h3>Constants</h3>\n"; +    print "<dl>\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	print "<dt><b>".$parameter."</b>\n"; +	print "<dd>"; +	output_highlight($args{'parameterdescs'}{$parameter}); +    } +    print "</dl>\n"; +    output_section_html(@_); +    print "<hr>\n"; +} + +# output tyepdef in html +sub output_typedef_html(%) { +    my %args = %{$_[0]}; +    my ($parameter); +    my $count; +    print "<h2>typedef ".$args{'typedef'}."</h2>\n"; + +    print "<b>typedef ".$args{'typedef'}."</b>\n"; +    output_section_html(@_); +    print "<hr>\n"; +} + +# output struct in html +sub output_struct_html(%) { +    my %args = %{$_[0]}; +    my ($parameter); + +    print "<h2>".$args{'type'}." ".$args{'struct'}."</h2>\n"; +    print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	if ($parameter =~ /^#/) { +		print "$parameter<br>\n"; +		next; +	} +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; +	$type = $args{'parametertypes'}{$parameter}; +	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { +	    # pointer-to-function +	    print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n"; +	} elsif ($type =~ m/^(.*?)\s*(:.*)/) { +	    print " <i>$1</i> <b>$parameter</b>$2;<br>\n"; +	} else { +	    print " <i>$type</i> <b>$parameter</b>;<br>\n"; +	} +    } +    print "};<br>\n"; + +    print "<h3>Members</h3>\n"; +    print "<dl>\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	($parameter =~ /^#/) && next; + +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; +	print "<dt><b>".$parameter."</b>\n"; +	print "<dd>"; +	output_highlight($args{'parameterdescs'}{$parameter_name}); +    } +    print "</dl>\n"; +    output_section_html(@_); +    print "<hr>\n"; +} + +# output function in html +sub output_function_html(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $count; +    print "<h2>Function</h2>\n"; + +    print "<i>".$args{'functiontype'}."</i>\n"; +    print "<b>".$args{'function'}."</b>\n"; +    print "("; +    $count = 0; +    foreach $parameter (@{$args{'parameterlist'}}) { +	$type = $args{'parametertypes'}{$parameter}; +	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { +	    # pointer-to-function +	    print "<i>$1</i><b>$parameter</b>) <i>($2)</i>"; +	} else { +	    print "<i>".$type."</i> <b>".$parameter."</b>"; +	} +	if ($count != $#{$args{'parameterlist'}}) { +	    $count++; +	    print ",\n"; +	} +    } +    print ")\n"; + +    print "<h3>Arguments</h3>\n"; +    print "<dl>\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; +	print "<dt><b>".$parameter."</b>\n"; +	print "<dd>"; +	output_highlight($args{'parameterdescs'}{$parameter_name}); +    } +    print "</dl>\n"; +    output_section_html(@_); +    print "<hr>\n"; +} + +# output intro in html +sub output_intro_html(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $count; + +    foreach $section (@{$args{'sectionlist'}}) { +	print "<h3>$section</h3>\n"; +	print "<ul>\n"; +	output_highlight($args{'sections'}{$section}); +	print "</ul>\n"; +    } +    print "<hr>\n"; +} + +sub output_section_xml(%) { +    my %args = %{$_[0]}; +    my $section;     +    # print out each section +    $lineprefix="   "; +    foreach $section (@{$args{'sectionlist'}}) { +	print "<refsect1>\n <title>$section</title>\n <para>\n"; +	if ($section =~ m/EXAMPLE/i) { +	    print "<example><para>\n"; +	} +	output_highlight($args{'sections'}{$section}); +	if ($section =~ m/EXAMPLE/i) { +	    print "</para></example>\n"; +	} +	print " </para>\n</refsect1>\n"; +    } +} + +# output function in XML DocBook +sub output_function_xml(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $count; +    my $id; + +    $id = "API-".$args{'function'}; +    $id =~ s/[^A-Za-z0-9]/-/g; + +    print "<refentry>\n"; +    print "<refmeta>\n"; +    print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n"; +    print "</refmeta>\n"; +    print "<refnamediv>\n"; +    print " <refname>".$args{'function'}."</refname>\n"; +    print " <refpurpose>\n"; +    print "  "; +    output_highlight ($args{'purpose'}); +    print " </refpurpose>\n"; +    print "</refnamediv>\n"; + +    print "<refsynopsisdiv>\n"; +    print " <title>Synopsis</title>\n"; +    print "  <funcsynopsis><funcprototype>\n"; +    print "   <funcdef>".$args{'functiontype'}." "; +    print "<function>".$args{'function'}." </function></funcdef>\n"; + +    $count = 0; +    if ($#{$args{'parameterlist'}} >= 0) { +	foreach $parameter (@{$args{'parameterlist'}}) { +	    $type = $args{'parametertypes'}{$parameter}; +	    if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { +		# pointer-to-function +		print "   <paramdef>$1<parameter>$parameter</parameter>)\n"; +		print "     <funcparams>$2</funcparams></paramdef>\n"; +	    } else { +		print "   <paramdef>".$type; +		print " <parameter>$parameter</parameter></paramdef>\n"; +	    } +	} +    } else { +	print "  <void>\n"; +    } +    print "  </funcprototype></funcsynopsis>\n"; +    print "</refsynopsisdiv>\n"; + +    # print parameters +    print "<refsect1>\n <title>Arguments</title>\n"; +    if ($#{$args{'parameterlist'}} >= 0) { +	print " <variablelist>\n"; +	foreach $parameter (@{$args{'parameterlist'}}) { +	    my $parameter_name = $parameter; +	    $parameter_name =~ s/\[.*//; + +	    print "  <varlistentry>\n   <term><parameter>$parameter</parameter></term>\n"; +	    print "   <listitem>\n    <para>\n"; +	    $lineprefix="     "; +	    output_highlight($args{'parameterdescs'}{$parameter_name}); +	    print "    </para>\n   </listitem>\n  </varlistentry>\n"; +	} +	print " </variablelist>\n"; +    } else { +	print " <para>\n  None\n </para>\n"; +    } +    print "</refsect1>\n"; + +    output_section_xml(@_); +    print "</refentry>\n\n"; +} + +# output struct in XML DocBook +sub output_struct_xml(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $id; + +    $id = "API-struct-".$args{'struct'}; +    $id =~ s/[^A-Za-z0-9]/-/g; + +    print "<refentry>\n"; +    print "<refmeta>\n"; +    print "<refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n"; +    print "</refmeta>\n"; +    print "<refnamediv>\n"; +    print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n"; +    print " <refpurpose>\n"; +    print "  "; +    output_highlight ($args{'purpose'}); +    print " </refpurpose>\n"; +    print "</refnamediv>\n"; + +    print "<refsynopsisdiv>\n"; +    print " <title>Synopsis</title>\n"; +    print "  <programlisting>\n"; +    print $args{'type'}." ".$args{'struct'}." {\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	if ($parameter =~ /^#/) { +	    print "$parameter\n"; +	    next; +	} + +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +	defined($args{'parameterdescs'}{$parameter_name}) || next; +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; +	$type = $args{'parametertypes'}{$parameter}; +	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { +	    # pointer-to-function +	    print "  $1 $parameter) ($2);\n"; +	} elsif ($type =~ m/^(.*?)\s*(:.*)/) { +	    print "  $1 $parameter$2;\n"; +	} else { +	    print "  ".$type." ".$parameter.";\n"; +	} +    } +    print "};"; +    print "  </programlisting>\n"; +    print "</refsynopsisdiv>\n"; + +    print " <refsect1>\n"; +    print "  <title>Members</title>\n"; + +    print "  <variablelist>\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +      ($parameter =~ /^#/) && next; + +      my $parameter_name = $parameter; +      $parameter_name =~ s/\[.*//; + +      defined($args{'parameterdescs'}{$parameter_name}) || next; +      ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; +      print "    <varlistentry>"; +      print "      <term>$parameter</term>\n"; +      print "      <listitem><para>\n"; +      output_highlight($args{'parameterdescs'}{$parameter_name}); +      print "      </para></listitem>\n"; +      print "    </varlistentry>\n"; +    } +    print "  </variablelist>\n"; +    print " </refsect1>\n"; + +    output_section_xml(@_); + +    print "</refentry>\n\n"; +} + +# output enum in XML DocBook +sub output_enum_xml(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $count; +    my $id; + +    $id = "API-enum-".$args{'enum'}; +    $id =~ s/[^A-Za-z0-9]/-/g; + +    print "<refentry>\n"; +    print "<refmeta>\n"; +    print "<refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n"; +    print "</refmeta>\n"; +    print "<refnamediv>\n"; +    print " <refname>enum ".$args{'enum'}."</refname>\n"; +    print " <refpurpose>\n"; +    print "  "; +    output_highlight ($args{'purpose'}); +    print " </refpurpose>\n"; +    print "</refnamediv>\n"; + +    print "<refsynopsisdiv>\n"; +    print " <title>Synopsis</title>\n"; +    print "  <programlisting>\n"; +    print "enum ".$args{'enum'}." {\n"; +    $count = 0; +    foreach $parameter (@{$args{'parameterlist'}}) { +        print "  $parameter"; +        if ($count != $#{$args{'parameterlist'}}) { +	    $count++; +	    print ","; +        } +	print "\n"; +    } +    print "};"; +    print "  </programlisting>\n"; +    print "</refsynopsisdiv>\n"; + +    print "<refsect1>\n"; +    print " <title>Constants</title>\n";     +    print "  <variablelist>\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +      my $parameter_name = $parameter; +      $parameter_name =~ s/\[.*//; + +      print "    <varlistentry>"; +      print "      <term>$parameter</term>\n"; +      print "      <listitem><para>\n"; +      output_highlight($args{'parameterdescs'}{$parameter_name}); +      print "      </para></listitem>\n"; +      print "    </varlistentry>\n"; +    } +    print "  </variablelist>\n"; +    print "</refsect1>\n"; + +    output_section_xml(@_); + +    print "</refentry>\n\n"; +} + +# output typedef in XML DocBook +sub output_typedef_xml(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $id; + +    $id = "API-typedef-".$args{'typedef'}; +    $id =~ s/[^A-Za-z0-9]/-/g; + +    print "<refentry>\n"; +    print "<refmeta>\n"; +    print "<refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n"; +    print "</refmeta>\n"; +    print "<refnamediv>\n"; +    print " <refname>typedef ".$args{'typedef'}."</refname>\n"; +    print " <refpurpose>\n"; +    print "  "; +    output_highlight ($args{'purpose'}); +    print " </refpurpose>\n"; +    print "</refnamediv>\n"; + +    print "<refsynopsisdiv>\n"; +    print " <title>Synopsis</title>\n"; +    print "  <synopsis>typedef ".$args{'typedef'}.";</synopsis>\n"; +    print "</refsynopsisdiv>\n"; + +    output_section_xml(@_); + +    print "</refentry>\n\n"; +} + +# output in XML DocBook +sub output_intro_xml(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $count; + +    my $id = $args{'module'}; +    $id =~ s/[^A-Za-z0-9]/-/g; + +    # print out each section +    $lineprefix="   "; +    foreach $section (@{$args{'sectionlist'}}) { +	print "<refsect1>\n <title>$section</title>\n <para>\n"; +	if ($section =~ m/EXAMPLE/i) { +	    print "<example><para>\n"; +	} +	output_highlight($args{'sections'}{$section}); +	if ($section =~ m/EXAMPLE/i) { +	    print "</para></example>\n"; +	} +	print " </para>\n</refsect1>\n"; +    } + +    print "\n\n"; +} + +# output in XML DocBook +sub output_function_gnome { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $count; +    my $id; + +    $id = $args{'module'}."-".$args{'function'}; +    $id =~ s/[^A-Za-z0-9]/-/g; + +    print "<sect2>\n"; +    print " <title id=\"$id\">".$args{'function'}."</title>\n"; + +    print "  <funcsynopsis>\n"; +    print "   <funcdef>".$args{'functiontype'}." "; +    print "<function>".$args{'function'}." "; +    print "</function></funcdef>\n"; + +    $count = 0; +    if ($#{$args{'parameterlist'}} >= 0) { +	foreach $parameter (@{$args{'parameterlist'}}) { +	    $type = $args{'parametertypes'}{$parameter}; +	    if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { +		# pointer-to-function +		print "   <paramdef>$1 <parameter>$parameter</parameter>)\n"; +		print "     <funcparams>$2</funcparams></paramdef>\n"; +	    } else { +		print "   <paramdef>".$type; +		print " <parameter>$parameter</parameter></paramdef>\n"; +	    } +	} +    } else { +	print "  <void>\n"; +    } +    print "  </funcsynopsis>\n"; +    if ($#{$args{'parameterlist'}} >= 0) { +	print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n"; +	print "<tgroup cols=\"2\">\n"; +	print "<colspec colwidth=\"2*\">\n"; +	print "<colspec colwidth=\"8*\">\n"; +	print "<tbody>\n"; +	foreach $parameter (@{$args{'parameterlist'}}) { +	    my $parameter_name = $parameter; +	    $parameter_name =~ s/\[.*//; + +	    print "  <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n"; +	    print "   <entry>\n"; +	    $lineprefix="     "; +	    output_highlight($args{'parameterdescs'}{$parameter_name}); +	    print "    </entry></row>\n"; +	} +	print " </tbody></tgroup></informaltable>\n"; +    } else { +	print " <para>\n  None\n </para>\n"; +    } + +    # print out each section +    $lineprefix="   "; +    foreach $section (@{$args{'sectionlist'}}) { +	print "<simplesect>\n <title>$section</title>\n"; +	if ($section =~ m/EXAMPLE/i) { +	    print "<example><programlisting>\n"; +	} else { +	} +	print "<para>\n"; +	output_highlight($args{'sections'}{$section}); +	print "</para>\n"; +	if ($section =~ m/EXAMPLE/i) { +	    print "</programlisting></example>\n"; +	} else { +	} +	print " </simplesect>\n"; +    } + +    print "</sect2>\n\n"; +} + +## +# output function in man +sub output_function_man(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $count; + +    print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n"; + +    print ".SH NAME\n"; +    print $args{'function'}." \\- ".$args{'purpose'}."\n"; + +    print ".SH SYNOPSIS\n"; +    print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n"; +    $count = 0; +    my $parenth = "("; +    my $post = ","; +    foreach my $parameter (@{$args{'parameterlist'}}) { +	if ($count == $#{$args{'parameterlist'}}) { +	    $post = ");"; +	} +	$type = $args{'parametertypes'}{$parameter}; +	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { +	    # pointer-to-function +	    print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n"; +	} else { +	    $type =~ s/([^\*])$/$1 /; +	    print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n"; +	} +	$count++; +	$parenth = ""; +    } + +    print ".SH ARGUMENTS\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +	print ".IP \"".$parameter."\" 12\n"; +	output_highlight($args{'parameterdescs'}{$parameter_name}); +    } +    foreach $section (@{$args{'sectionlist'}}) { +	print ".SH \"", uc $section, "\"\n"; +	output_highlight($args{'sections'}{$section}); +    } +} + +## +# output enum in man +sub output_enum_man(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $count; + +    print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n"; + +    print ".SH NAME\n"; +    print "enum ".$args{'enum'}." \\- ".$args{'purpose'}."\n"; + +    print ".SH SYNOPSIS\n"; +    print "enum ".$args{'enum'}." {\n"; +    $count = 0; +    foreach my $parameter (@{$args{'parameterlist'}}) { +        print ".br\n.BI \"    $parameter\"\n"; +	if ($count == $#{$args{'parameterlist'}}) { +	    print "\n};\n"; +	    last; +	} +	else { +	    print ", \n.br\n"; +	} +	$count++; +    } + +    print ".SH Constants\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +	print ".IP \"".$parameter."\" 12\n"; +	output_highlight($args{'parameterdescs'}{$parameter_name}); +    } +    foreach $section (@{$args{'sectionlist'}}) { +	print ".SH \"$section\"\n"; +	output_highlight($args{'sections'}{$section}); +    } +} + +## +# output struct in man +sub output_struct_man(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); + +    print ".TH \"$args{'module'}\" 9 \"".$args{'type'}." ".$args{'struct'}."\" \"$man_date\" \"API Manual\" LINUX\n"; + +    print ".SH NAME\n"; +    print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n"; + +    print ".SH SYNOPSIS\n"; +    print $args{'type'}." ".$args{'struct'}." {\n.br\n"; + +    foreach my $parameter (@{$args{'parameterlist'}}) { +	if ($parameter =~ /^#/) { +	    print ".BI \"$parameter\"\n.br\n"; +	    next; +	} +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; +	$type = $args{'parametertypes'}{$parameter}; +	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { +	    # pointer-to-function +	    print ".BI \"    ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n"; +	} elsif ($type =~ m/^(.*?)\s*(:.*)/) { +	    print ".BI \"    ".$1."\" ".$parameter.$2." \""."\"\n;\n"; +	} else { +	    $type =~ s/([^\*])$/$1 /; +	    print ".BI \"    ".$type."\" ".$parameter." \""."\"\n;\n"; +	} +	print "\n.br\n"; +    } +    print "};\n.br\n"; + +    print ".SH Arguments\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	($parameter =~ /^#/) && next; + +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; +	print ".IP \"".$parameter."\" 12\n"; +	output_highlight($args{'parameterdescs'}{$parameter_name}); +    } +    foreach $section (@{$args{'sectionlist'}}) { +	print ".SH \"$section\"\n"; +	output_highlight($args{'sections'}{$section}); +    } +} + +## +# output typedef in man +sub output_typedef_man(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); + +    print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n"; + +    print ".SH NAME\n"; +    print "typedef ".$args{'typedef'}." \\- ".$args{'purpose'}."\n"; + +    foreach $section (@{$args{'sectionlist'}}) { +	print ".SH \"$section\"\n"; +	output_highlight($args{'sections'}{$section}); +    } +} + +sub output_intro_man(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); +    my $count; + +    print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n"; + +    foreach $section (@{$args{'sectionlist'}}) { +	print ".SH \"$section\"\n"; +	output_highlight($args{'sections'}{$section}); +    } +} + +## +# output in text +sub output_function_text(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); + +    print "Function:\n\n"; +    my $start=$args{'functiontype'}." ".$args{'function'}." ("; +    print $start; +    my $count = 0; +    foreach my $parameter (@{$args{'parameterlist'}}) { +	$type = $args{'parametertypes'}{$parameter}; +	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { +	    # pointer-to-function +	    print $1.$parameter.") (".$2; +	} else { +	    print $type." ".$parameter; +	} +	if ($count != $#{$args{'parameterlist'}}) { +	    $count++; +	    print ",\n"; +	    print " " x length($start); +	} else { +	    print ");\n\n"; +	} +    } + +    print "Arguments:\n\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +	print $parameter."\n\t".$args{'parameterdescs'}{$parameter_name}."\n"; +    } +    output_section_text(@_); +} + +#output sections in text +sub output_section_text(%) { +    my %args = %{$_[0]}; +    my $section; + +    print "\n"; +    foreach $section (@{$args{'sectionlist'}}) { +	print "$section:\n\n"; +	output_highlight($args{'sections'}{$section}); +    }   +    print "\n\n"; +} + +# output enum in text +sub output_enum_text(%) { +    my %args = %{$_[0]}; +    my ($parameter); +    my $count; +    print "Enum:\n\n"; + +    print "enum ".$args{'enum'}." {\n"; +    $count = 0; +    foreach $parameter (@{$args{'parameterlist'}}) { +        print "\t$parameter"; +	if ($count != $#{$args{'parameterlist'}}) { +	    $count++; +	    print ","; +	} +	print "\n"; +    } +    print "};\n\n"; + +    print "Constants:\n\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	print "$parameter\n\t"; +	print $args{'parameterdescs'}{$parameter}."\n"; +    } + +    output_section_text(@_); +} + +# output typedef in text +sub output_typedef_text(%) { +    my %args = %{$_[0]}; +    my ($parameter); +    my $count; +    print "Typedef:\n\n"; + +    print "typedef ".$args{'typedef'}."\n"; +    output_section_text(@_); +} + +# output struct as text +sub output_struct_text(%) { +    my %args = %{$_[0]}; +    my ($parameter); + +    print $args{'type'}." ".$args{'struct'}.":\n\n"; +    print $args{'type'}." ".$args{'struct'}." {\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	if ($parameter =~ /^#/) { +	    print "$parameter\n"; +	    next; +	} + +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; +	$type = $args{'parametertypes'}{$parameter}; +	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { +	    # pointer-to-function +	    print "\t$1 $parameter) ($2);\n"; +	} elsif ($type =~ m/^(.*?)\s*(:.*)/) { +	    print "\t$1 $parameter$2;\n"; +	} else { +	    print "\t".$type." ".$parameter.";\n"; +	} +    } +    print "};\n\n"; + +    print "Members:\n\n"; +    foreach $parameter (@{$args{'parameterlist'}}) { +	($parameter =~ /^#/) && next; + +	my $parameter_name = $parameter; +	$parameter_name =~ s/\[.*//; + +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; +	print "$parameter\n\t"; +	print $args{'parameterdescs'}{$parameter_name}."\n"; +    } +    print "\n"; +    output_section_text(@_); +} + +sub output_intro_text(%) { +    my %args = %{$_[0]}; +    my ($parameter, $section); + +    foreach $section (@{$args{'sectionlist'}}) { +	print " $section:\n"; +	print "    -> "; +	output_highlight($args{'sections'}{$section}); +    } +} + +## +# generic output function for typedefs +sub output_declaration { +    no strict 'refs'; +    my $name = shift; +    my $functype = shift; +    my $func = "output_${functype}_$output_mode"; +    if (($function_only==0) ||  +	( $function_only == 1 && defined($function_table{$name})) ||  +	( $function_only == 2 && !defined($function_table{$name}))) +    { +        &$func(@_); +	$section_counter++; +    } +} + +## +# generic output function - calls the right one based +# on current output mode. +sub output_intro { +    no strict 'refs'; +    my $func = "output_intro_".$output_mode; +    &$func(@_); +    $section_counter++; +} + +## +# takes a declaration (struct, union, enum, typedef) and  +# invokes the right handler. NOT called for functions. +sub dump_declaration($$) { +    no strict 'refs'; +    my ($prototype, $file) = @_; +    my $func = "dump_".$decl_type; +    &$func(@_); +} + +sub dump_union($$) { +    dump_struct(@_); +} + +sub dump_struct($$) { +    my $x = shift; +    my $file = shift; + +    if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) { +        $declaration_name = $2; +        my $members = $3; + +	# ignore embedded structs or unions +	$members =~ s/{.*?}//g; + +	create_parameterlist($members, ';', $file); + +	output_declaration($declaration_name, +			   'struct', +			   {'struct' => $declaration_name, +			    'module' => $modulename, +			    'parameterlist' => \@parameterlist, +			    'parameterdescs' => \%parameterdescs, +			    'parametertypes' => \%parametertypes, +			    'sectionlist' => \@sectionlist, +			    'sections' => \%sections, +			    'purpose' => $declaration_purpose, +			    'type' => $decl_type +			   }); +    } +    else { +        print STDERR "Error(${file}:$.): Cannot parse struct or union!\n"; +	++$errors; +    } +} + +sub dump_enum($$) { +    my $x = shift; +    my $file = shift; + +    if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { +        $declaration_name = $1; +        my $members = $2; + +	foreach my $arg (split ',', $members) { +	    $arg =~ s/^\s*(\w+).*/$1/; +	    push @parameterlist, $arg; +	    if (!$parameterdescs{$arg}) { +	        $parameterdescs{$arg} = $undescribed; +	        print STDERR "Warning(${file}:$.): Enum value '$arg' ". +		    "not described in enum '$declaration_name'\n"; +	    } + +	} +	 +	output_declaration($declaration_name, +			   'enum', +			   {'enum' => $declaration_name, +			    'module' => $modulename, +			    'parameterlist' => \@parameterlist, +			    'parameterdescs' => \%parameterdescs, +			    'sectionlist' => \@sectionlist, +			    'sections' => \%sections, +			    'purpose' => $declaration_purpose +			   }); +    } +    else { +        print STDERR "Error(${file}:$.): Cannot parse enum!\n"; +	++$errors; +    } +} + +sub dump_typedef($$) { +    my $x = shift; +    my $file = shift; + +    while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { +        $x =~ s/\(*.\)\s*;$/;/; +	$x =~ s/\[*.\]\s*;$/;/; +    } + +    if ($x =~ /typedef.*\s+(\w+)\s*;/) { +        $declaration_name = $1; + +	output_declaration($declaration_name, +			   'typedef', +			   {'typedef' => $declaration_name, +			    'module' => $modulename, +			    'sectionlist' => \@sectionlist, +			    'sections' => \%sections, +			    'purpose' => $declaration_purpose +			   }); +    } +    else { +        print STDERR "Error(${file}:$.): Cannot parse typedef!\n"; +	++$errors; +    } +} + +sub create_parameterlist($$$) { +    my $args = shift; +    my $splitter = shift; +    my $file = shift; +    my $type; +    my $param; + +    while ($args =~ /(\([^\),]+),/) { +        $args =~ s/(\([^\),]+),/$1#/g; +    } +     +    foreach my $arg (split($splitter, $args)) { +	# strip comments +	$arg =~ s/\/\*.*\*\///; +        # strip leading/trailing spaces +        $arg =~ s/^\s*//; +	$arg =~ s/\s*$//; +	$arg =~ s/\s+/ /; + +	if ($arg =~ /^#/) { +	    # Treat preprocessor directive as a typeless variable just to fill +	    # corresponding data structures "correctly". Catch it later in +	    # output_* subs. +	    push_parameter($arg, "", $file); +	} elsif ($arg =~ m/\(/) { +	    # pointer-to-function +	    $arg =~ tr/#/,/; +	    $arg =~ m/[^\(]+\(\*([^\)]+)\)/; +	    $param = $1; +	    $type = $arg; +	    $type =~ s/([^\(]+\(\*)$param/$1/; +	    push_parameter($param, $type, $file); +	} else { +	    $arg =~ s/\s*:\s*/:/g; +	    $arg =~ s/\s*\[/\[/g; + +	    my @args = split('\s*,\s*', $arg); +	    if ($args[0] =~ m/\*/) { +		$args[0] =~ s/(\*+)\s*/ $1/; +	    } +	    my @first_arg = split('\s+', shift @args); +	    unshift(@args, pop @first_arg); +	    $type = join " ", @first_arg; + +	    foreach $param (@args) { +		if ($param =~ m/^(\*+)\s*(.*)/) { +		    push_parameter($2, "$type $1", $file); +		} +		elsif ($param =~ m/(.*?):(\d+)/) { +		    push_parameter($1, "$type:$2", $file) +		} +		else { +		    push_parameter($param, $type, $file); +		} +	    } +	} +    } +} + +sub push_parameter($$$) { +	my $param = shift; +	my $type = shift; +	my $file = shift; + +	my $param_name = $param; +	$param_name =~ s/\[.*//; + +	if ($type eq "" && $param eq "...") +	{ +	    $type=""; +	    $param="..."; +	    $parameterdescs{"..."} = "variable arguments"; +	} +	elsif ($type eq "" && ($param eq "" or $param eq "void")) +	{ +	    $type=""; +	    $param="void"; +	    $parameterdescs{void} = "no arguments"; +	} +	if (defined $type && $type && !defined $parameterdescs{$param_name}) { +	    $parameterdescs{$param_name} = $undescribed; + +	    if (($type eq 'function') || ($type eq 'enum')) { +	        print STDERR "Warning(${file}:$.): Function parameter ". +		    "or member '$param' not " . +		    "described in '$declaration_name'\n"; +	    } +	    print STDERR "Warning(${file}:$.):". +	                 " No description found for parameter '$param'\n"; +	    ++$warnings; +        } + +	push @parameterlist, $param; +	$parametertypes{$param} = $type; +} + +## +# takes a function prototype and the name of the current file being +# processed and spits out all the details stored in the global +# arrays/hashes. +sub dump_function($$) { +    my $prototype = shift; +    my $file = shift; + +    $prototype =~ s/^static +//; +    $prototype =~ s/^extern +//; +    $prototype =~ s/^inline +//; +    $prototype =~ s/^__inline__ +//; +    $prototype =~ s/^#define +//; #ak added +    $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//; + +    # Yes, this truly is vile.  We are looking for: +    # 1. Return type (may be nothing if we're looking at a macro) +    # 2. Function name +    # 3. Function parameters. +    # +    # All the while we have to watch out for function pointer parameters +    # (which IIRC is what the two sections are for), C types (these +    # regexps don't even start to express all the possibilities), and +    # so on. +    # +    # If you mess with these regexps, it's a good idea to check that +    # the following functions' documentation still comes out right: +    # - parport_register_device (function pointer parameters) +    # - atomic_set (macro) +    # - pci_match_device (long return type) + +    if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || +	$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || +	$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || +	$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || +	$prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || +	$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || +	$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || +	$prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || +	$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || +	$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || +	$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || +	$prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || +	$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || +	$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  { +	$return_type = $1; +	$declaration_name = $2; +	my $args = $3; + +	create_parameterlist($args, ',', $file); +    } else { +	print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n"; +	++$errors; +	return; +    } + +    output_declaration($declaration_name,  +		       'function', +		       {'function' => $declaration_name, +			'module' => $modulename, +			'functiontype' => $return_type, +			'parameterlist' => \@parameterlist, +			'parameterdescs' => \%parameterdescs, +			'parametertypes' => \%parametertypes, +			'sectionlist' => \@sectionlist, +			'sections' => \%sections, +			'purpose' => $declaration_purpose +		       }); +} + +sub process_file($); + +# Read the file that maps relative names to absolute names for +# separate source and object directories and for shadow trees. +if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { +	my ($relname, $absname); +	while(<SOURCE_MAP>) { +		chop(); +		($relname, $absname) = (split())[0..1]; +		$relname =~ s:^/+::; +		$source_map{$relname} = $absname; +	} +	close(SOURCE_MAP); +} + +if ($filelist) { +	open(FLIST,"<$filelist") or die "Can't open file list $filelist"; +	while(<FLIST>) { +		chop; +		process_file($_); +	} +} + +foreach (@ARGV) { +    chomp; +    process_file($_); +} +if ($verbose && $errors) { +  print STDERR "$errors errors\n"; +} +if ($verbose && $warnings) { +  print STDERR "$warnings warnings\n"; +} + +exit($errors); + +sub reset_state { +    $function = ""; +    %constants = (); +    %parameterdescs = (); +    %parametertypes = (); +    @parameterlist = (); +    %sections = (); +    @sectionlist = (); +    $prototype = ""; +     +    $state = 0; +} + +sub process_state3_function($$) {  +    my $x = shift; +    my $file = shift; + +    if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#define/)) { +	# do nothing +    } +    elsif ($x =~ /([^\{]*)/) { +        $prototype .= $1; +    } +    if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) { +        $prototype =~ s@/\*.*?\*/@@gos;	# strip comments. +	$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. +	$prototype =~ s@^\s+@@gos; # strip leading spaces +	dump_function($prototype,$file); +	reset_state(); +    } +} + +sub process_state3_type($$) {  +    my $x = shift; +    my $file = shift; + +    $x =~ s@/\*.*?\*/@@gos;	# strip comments. +    $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. +    $x =~ s@^\s+@@gos; # strip leading spaces +    $x =~ s@\s+$@@gos; # strip trailing spaces +    if ($x =~ /^#/) { +	# To distinguish preprocessor directive from regular declaration later. +	$x .= ";"; +    } + +    while (1) { +        if ( $x =~ /([^{};]*)([{};])(.*)/ ) { +	    $prototype .= $1 . $2; +	    ($2 eq '{') && $brcount++; +	    ($2 eq '}') && $brcount--; +	    if (($2 eq ';') && ($brcount == 0)) { +	        dump_declaration($prototype,$file); +		reset_state(); +	        last; +	    } +	    $x = $3; +        } else { +	    $prototype .= $x; +	    last; +	} +    } +} + +# replace <, >, and & +sub xml_escape($) { +	my $text = shift; +	$text =~ s/\&/\\\\\\amp;/g; +	$text =~ s/\</\\\\\\lt;/g; +	$text =~ s/\>/\\\\\\gt;/g; +	return $text; +} + +sub process_file($) { +    my ($file) = "$ENV{'SRCTREE'}@_"; +    my $identifier; +    my $func; +    my $initial_section_counter = $section_counter; + +    if (defined($source_map{$file})) { +	$file = $source_map{$file}; +    } + +    if (!open(IN,"<$file")) { +	print STDERR "Error: Cannot open file $file\n"; +	++$errors; +	return; +    } + +    $section_counter = 0; +    while (<IN>) { +	if ($state == 0) { +	    if (/$doc_start/o) { +		$state = 1;		# next line is always the function name +	    } +	} elsif ($state == 1) {	# this line is the function name (always) +	    if (/$doc_block/o) { +		$state = 4; +		$contents = ""; +		if ( $1 eq "" ) { +			$section = $section_intro; +		} else { +			$section = $1; +		} +            } +	    elsif (/$doc_decl/o) { +		$identifier = $1; +		if (/\s*([\w\s]+?)\s*-/) { +		    $identifier = $1; +		} + +		$state = 2; +		if (/-(.*)/) { +		    $declaration_purpose = xml_escape($1); +		} else { +		    $declaration_purpose = ""; +		} +		if ($identifier =~ m/^struct/) { +		    $decl_type = 'struct'; +		} elsif ($identifier =~ m/^union/) { +		    $decl_type = 'union'; +		} elsif ($identifier =~ m/^enum/) { +		    $decl_type = 'enum'; +		} elsif ($identifier =~ m/^typedef/) { +		    $decl_type = 'typedef'; +		} else { +		    $decl_type = 'function'; +		} + +		if ($verbose) { +		    print STDERR "Info(${file}:$.): Scanning doc for $identifier\n"; +		} +	    } else { +		print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.", +		" - I thought it was a doc line\n"; +		++$warnings; +		$state = 0; +	    } +	} elsif ($state == 2) {	# look for head: lines, and include content +	    if (/$doc_sect/o) { +		$newsection = $1; +		$newcontents = $2; + +		if ($contents ne "") { +		    dump_section($section, xml_escape($contents)); +		    $section = $section_default; +		} + +		$contents = $newcontents; +		if ($contents ne "") { +		    $contents .= "\n"; +		} +		$section = $newsection; +	    } elsif (/$doc_end/) { + +		if ($contents ne "") { +		    dump_section($section, xml_escape($contents)); +		    $section = $section_default; +		    $contents = ""; +		} + +		$prototype = ""; +		$state = 3; +		$brcount = 0; +#	    print STDERR "end of doc comment, looking for prototype\n"; +	    } elsif (/$doc_content/) { +		# miguel-style comment kludge, look for blank lines after +		# @parameter line to signify start of description +		if ($1 eq "" &&  +			($section =~ m/^@/ || $section eq $section_context)) { +		    dump_section($section, xml_escape($contents)); +		    $section = $section_default; +		    $contents = ""; +		} else { +		    $contents .= $1."\n"; +		} +	    } else { +		# i dont know - bad line?  ignore. +		print STDERR "Warning(${file}:$.): bad line: $_";  +		++$warnings; +	    } +	} elsif ($state == 3) {	# scanning for function { (end of prototype) +	    if ($decl_type eq 'function') { +	        process_state3_function($_, $file); +	    } else { +	        process_state3_type($_, $file); +	    } +	} elsif ($state == 4) { +		# Documentation block +	        if (/$doc_block/) { +			dump_section($section, $contents); +			output_intro({'sectionlist' => \@sectionlist, +				      'sections' => \%sections }); +			$contents = ""; +			$function = ""; +			%constants = (); +			%parameterdescs = (); +			%parametertypes = (); +			@parameterlist = (); +			%sections = (); +			@sectionlist = (); +			$prototype = ""; +			if ( $1 eq "" ) { +				$section = $section_intro; +			} else { +				$section = $1; +			} +                } +		elsif (/$doc_end/) +		{ +			dump_section($section, $contents); +			output_intro({'sectionlist' => \@sectionlist, +				      'sections' => \%sections }); +			$contents = ""; +			$function = ""; +			%constants = (); +			%parameterdescs = (); +			%parametertypes = (); +			@parameterlist = (); +			%sections = (); +			@sectionlist = (); +			$prototype = ""; +			$state = 0; +		} +		elsif (/$doc_content/) +		{ +			if ( $1 eq "" ) +			{ +				$contents .= $blankline; +			} +			else +			{ +				$contents .= $1 . "\n"; +			}	 +        	} +          } +    } +    if ($initial_section_counter == $section_counter) { +	print STDERR "Warning(${file}): no structured comments found\n"; +	if ($output_mode eq "xml") { +	    # The template wants at least one RefEntry here; make one. +	    print "<refentry>\n"; +	    print " <refnamediv>\n"; +	    print "  <refname>\n"; +	    print "   ${file}\n"; +	    print "  </refname>\n"; +	    print "  <refpurpose>\n"; +	    print "   Document generation inconsistency\n"; +	    print "  </refpurpose>\n"; +	    print " </refnamediv>\n"; +	    print " <refsect1>\n"; +	    print "  <title>\n"; +	    print "   Oops\n"; +	    print "  </title>\n"; +	    print "  <warning>\n"; +	    print "   <para>\n"; +	    print "    The template for this document tried to insert\n"; +	    print "    the structured comment from the file\n"; +	    print "    <filename>${file}</filename> at this point,\n"; +	    print "    but none was found.\n"; +	    print "    This dummy section is inserted to allow\n"; +	    print "    generation to continue.\n"; +	    print "   </para>\n"; +	    print "  </warning>\n"; +	    print " </refsect1>\n"; +	    print "</refentry>\n"; +	} +    } +} diff --git a/scripts/ksymoops/README b/scripts/ksymoops/README new file mode 100644 index 000000000000..f6cb06e3f30e --- /dev/null +++ b/scripts/ksymoops/README @@ -0,0 +1,8 @@ +ksymoops has been removed from the kernel.  It was always meant to be a +free standing utility, not linked to any particular kernel version. +The latest version can be found in +ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops together +with patches to other utilities in order to give more accurate Oops +debugging. + +Keith Owens <kaos@ocs.com.au> Sat Jun 19 10:30:34 EST 1999 diff --git a/scripts/lxdialog/BIG.FAT.WARNING b/scripts/lxdialog/BIG.FAT.WARNING new file mode 100644 index 000000000000..a8999d82bdb3 --- /dev/null +++ b/scripts/lxdialog/BIG.FAT.WARNING @@ -0,0 +1,4 @@ +This is NOT the official version of dialog.  This version has been +significantly modified from the original.  It is for use by the Linux +kernel configuration script.  Please do not bother Savio Lam with  +questions about this program. diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile new file mode 100644 index 000000000000..a45a13fb26ed --- /dev/null +++ b/scripts/lxdialog/Makefile @@ -0,0 +1,42 @@ +HOST_EXTRACFLAGS := -DLOCALE  +ifeq ($(shell uname),SunOS) +HOST_LOADLIBES   := -lcurses +else +HOST_LOADLIBES   := -lncurses +endif + +ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h)) +        HOST_EXTRACFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>" +else +ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h)) +        HOST_EXTRACFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>" +else +ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h)) +        HOST_EXTRACFLAGS += -DCURSES_LOC="<ncurses.h>" +else +	HOST_EXTRACFLAGS += -DCURSES_LOC="<curses.h>" +endif +endif +endif + +hostprogs-y	:= lxdialog +always		:= ncurses $(hostprogs-y) + +lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \ +		 util.o lxdialog.o msgbox.o + +.PHONY: $(obj)/ncurses +$(obj)/ncurses: +	@echo "main() {}" > lxtemp.c +	@if $(HOSTCC) lxtemp.c  $(HOST_LOADLIBES); then \ +		rm -f lxtemp.c a.out; \ +	else \ +		rm -f lxtemp.c; \ +		echo -e "\007" ;\ +		echo ">> Unable to find the Ncurses libraries." ;\ +		echo ">>" ;\ +		echo ">> You must install ncurses-devel in order" ;\ +		echo ">> to use 'make menuconfig'" ;\ +		echo ;\ +		exit 1 ;\ +	fi diff --git a/scripts/lxdialog/checklist.c b/scripts/lxdialog/checklist.c new file mode 100644 index 000000000000..7aba17c72e64 --- /dev/null +++ b/scripts/lxdialog/checklist.c @@ -0,0 +1,373 @@ +/* + *  checklist.c -- implements the checklist box + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *     Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension + *     Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static int list_width, check_x, item_x, checkflag; + +/* + * Print list item + */ +static void +print_item (WINDOW * win, const char *item, int status, +	    int choice, int selected) +{ +    int i; + +    /* Clear 'residue' of last item */ +    wattrset (win, menubox_attr); +    wmove (win, choice, 0); +    for (i = 0; i < list_width; i++) +	waddch (win, ' '); + +    wmove (win, choice, check_x); +    wattrset (win, selected ? check_selected_attr : check_attr); +    if (checkflag == FLAG_CHECK) +	wprintw (win, "[%c]", status ? 'X' : ' '); +    else +	wprintw (win, "(%c)", status ? 'X' : ' '); + +    wattrset (win, selected ? tag_selected_attr : tag_attr); +    mvwaddch(win, choice, item_x, item[0]); +    wattrset (win, selected ? item_selected_attr : item_attr); +    waddstr (win, (char *)item+1); +    if (selected) { +    	wmove (win, choice, check_x+1); +    	wrefresh (win); +    } +} + +/* + * Print the scroll indicators. + */ +static void +print_arrows (WINDOW * win, int choice, int item_no, int scroll, +		int y, int x, int height) +{ +    wmove(win, y, x); + +    if (scroll > 0) { +	wattrset (win, uarrow_attr); +	waddch (win, ACS_UARROW); +	waddstr (win, "(-)"); +    } +    else { +	wattrset (win, menubox_attr); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +    } + +   y = y + height + 1; +   wmove(win, y, x); + +   if ((height < item_no) && (scroll + choice < item_no - 1)) { +	wattrset (win, darrow_attr); +	waddch (win, ACS_DARROW); +	waddstr (win, "(+)"); +    } +    else { +	wattrset (win, menubox_border_attr); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +   } +} + +/* + *  Display the termination buttons + */ +static void +print_buttons( WINDOW *dialog, int height, int width, int selected) +{ +    int x = width / 2 - 11; +    int y = height - 2; + +    print_button (dialog, "Select", y, x, selected == 0); +    print_button (dialog, " Help ", y, x + 14, selected == 1); + +    wmove(dialog, y, x+1 + 14*selected); +    wrefresh (dialog); +} + +/* + * Display a dialog box with a list of options that can be turned on or off + * The `flag' parameter is used to select between radiolist and checklist. + */ +int +dialog_checklist (const char *title, const char *prompt, int height, int width, +	int list_height, int item_no, const char * const * items, int flag) +	 +{ +    int i, x, y, box_x, box_y; +    int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; +    WINDOW *dialog, *list; + +    checkflag = flag; + +    /* Allocate space for storing item on/off status */ +    if ((status = malloc (sizeof (int) * item_no)) == NULL) { +	endwin (); +	fprintf (stderr, +		 "\nCan't allocate memory in dialog_checklist().\n"); +	exit (-1); +    } + +    /* Initializes status */ +    for (i = 0; i < item_no; i++) { +	status[i] = !strcasecmp (items[i * 3 + 2], "on"); +	if ((!choice && status[i]) || !strcasecmp (items[i * 3 + 2], "selected")) +            choice = i + 1; +    } +    if (choice) +	    choice--; + +    max_choice = MIN (list_height, item_no); + +    /* center dialog box on screen */ +    x = (COLS - width) / 2; +    y = (LINES - height) / 2; + +    draw_shadow (stdscr, y, x, height, width); + +    dialog = newwin (height, width, y, x); +    keypad (dialog, TRUE); + +    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); +    wattrset (dialog, border_attr); +    mvwaddch (dialog, height-3, 0, ACS_LTEE); +    for (i = 0; i < width - 2; i++) +	waddch (dialog, ACS_HLINE); +    wattrset (dialog, dialog_attr); +    waddch (dialog, ACS_RTEE); + +    if (title != NULL && strlen(title) >= width-2 ) { +	/* truncate long title -- mec */ +	char * title2 = malloc(width-2+1); +	memcpy( title2, title, width-2 ); +	title2[width-2] = '\0'; +	title = title2; +    } + +    if (title != NULL) { +	wattrset (dialog, title_attr); +	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); +	waddstr (dialog, (char *)title); +	waddch (dialog, ' '); +    } + +    wattrset (dialog, dialog_attr); +    print_autowrap (dialog, prompt, width - 2, 1, 3); + +    list_width = width - 6; +    box_y = height - list_height - 5; +    box_x = (width - list_width) / 2 - 1; + +    /* create new window for the list */ +    list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1); + +    keypad (list, TRUE); + +    /* draw a box around the list items */ +    draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2, +	      menubox_border_attr, menubox_attr); + +    /* Find length of longest item in order to center checklist */ +    check_x = 0; +    for (i = 0; i < item_no; i++)  +	check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4); + +    check_x = (list_width - check_x) / 2; +    item_x = check_x + 4; + +    if (choice >= list_height) { +	scroll = choice - list_height + 1; +	choice -= scroll; +    } + +    /* Print the list */ +    for (i = 0; i < max_choice; i++) { +	print_item (list, items[(scroll+i) * 3 + 1], +		    status[i+scroll], i, i == choice); +    } + +    print_arrows(dialog, choice, item_no, scroll, +			box_y, box_x + check_x + 5, list_height); + +    print_buttons(dialog, height, width, 0); + +    wnoutrefresh (list); +    wnoutrefresh (dialog); +    doupdate (); + +    while (key != ESC) { +	key = wgetch (dialog); + +    	for (i = 0; i < max_choice; i++) +            if (toupper(key) == toupper(items[(scroll+i)*3+1][0])) +                break; + + +	if ( i < max_choice || key == KEY_UP || key == KEY_DOWN ||  +	    key == '+' || key == '-' ) { +	    if (key == KEY_UP || key == '-') { +		if (!choice) { +		    if (!scroll) +			continue; +		    /* Scroll list down */ +		    if (list_height > 1) { +			/* De-highlight current first item */ +			print_item (list, items[scroll * 3 + 1], +					status[scroll], 0, FALSE); +			scrollok (list, TRUE); +			wscrl (list, -1); +			scrollok (list, FALSE); +		    } +		    scroll--; +		    print_item (list, items[scroll * 3 + 1], +				status[scroll], 0, TRUE); +		    wnoutrefresh (list); + +    		    print_arrows(dialog, choice, item_no, scroll, +				box_y, box_x + check_x + 5, list_height); + +		    wrefresh (dialog); + +		    continue;	/* wait for another key press */ +		} else +		    i = choice - 1; +	    } else if (key == KEY_DOWN || key == '+') { +		if (choice == max_choice - 1) { +		    if (scroll + choice >= item_no - 1) +			continue; +		    /* Scroll list up */ +		    if (list_height > 1) { +			/* De-highlight current last item before scrolling up */ +			print_item (list, items[(scroll + max_choice - 1) * 3 + 1], +				    status[scroll + max_choice - 1], +				    max_choice - 1, FALSE); +			scrollok (list, TRUE); +			wscrl (list, 1); +			scrollok (list, FALSE); +		    } +		    scroll++; +		    print_item (list, items[(scroll + max_choice - 1) * 3 + 1], +				status[scroll + max_choice - 1], +				max_choice - 1, TRUE); +		    wnoutrefresh (list); + +    		    print_arrows(dialog, choice, item_no, scroll, +				box_y, box_x + check_x + 5, list_height); + +		    wrefresh (dialog); + +		    continue;	/* wait for another key press */ +		} else +		    i = choice + 1; +	    } +	    if (i != choice) { +		/* De-highlight current item */ +		print_item (list, items[(scroll + choice) * 3 + 1], +			    status[scroll + choice], choice, FALSE); +		/* Highlight new item */ +		choice = i; +		print_item (list, items[(scroll + choice) * 3 + 1], +			    status[scroll + choice], choice, TRUE); +		wnoutrefresh (list); +		wrefresh (dialog); +	    } +	    continue;		/* wait for another key press */ +	} +	switch (key) { +	case 'H': +	case 'h': +	case '?': +	    fprintf (stderr, "%s", items[(scroll + choice) * 3]); +	    delwin (dialog); +	    free (status); +	    return 1; +	case TAB: +	case KEY_LEFT: +	case KEY_RIGHT: +	    button = ((key == KEY_LEFT ? --button : ++button) < 0) +			? 1 : (button > 1 ? 0 : button); + +	    print_buttons(dialog, height, width, button); +	    wrefresh (dialog); +	    break; +	case 'S': +	case 's': +	case ' ': +	case '\n': +	    if (!button) { +		if (flag == FLAG_CHECK) { +		    status[scroll + choice] = !status[scroll + choice]; +		    wmove (list, choice, check_x); +		    wattrset (list, check_selected_attr); +		    wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' '); +		} else { +		    if (!status[scroll + choice]) { +			for (i = 0; i < item_no; i++) +			    status[i] = 0; +			status[scroll + choice] = 1; +			for (i = 0; i < max_choice; i++) +			    print_item (list, items[(scroll + i) * 3 + 1], +					status[scroll + i], i, i == choice); +		    } +		} +		wnoutrefresh (list); +		wrefresh (dialog); +             +		for (i = 0; i < item_no; i++) { +		    if (status[i]) { +			if (flag == FLAG_CHECK) { +			    fprintf (stderr, "\"%s\" ", items[i * 3]); +			} else { +			    fprintf (stderr, "%s", items[i * 3]); +			} + +		    } +		} +            } else +		fprintf (stderr, "%s", items[(scroll + choice) * 3]); +	    delwin (dialog); +	    free (status); +	    return button; +	case 'X': +	case 'x': +	    key = ESC; +	case ESC: +	    break; +	} + +	/* Now, update everything... */ +	doupdate (); +    } +     + +    delwin (dialog); +    free (status); +    return -1;			/* ESC pressed */ +} diff --git a/scripts/lxdialog/colors.h b/scripts/lxdialog/colors.h new file mode 100644 index 000000000000..25c59528a251 --- /dev/null +++ b/scripts/lxdialog/colors.h @@ -0,0 +1,155 @@ +/* + *  colors.h -- color attribute definitions + * + *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* + *   Default color definitions + * + *   *_FG = foreground + *   *_BG = background + *   *_HL = highlight? + */ +#define SCREEN_FG                    COLOR_CYAN +#define SCREEN_BG                    COLOR_BLUE +#define SCREEN_HL                    TRUE + +#define SHADOW_FG                    COLOR_BLACK +#define SHADOW_BG                    COLOR_BLACK +#define SHADOW_HL                    TRUE + +#define DIALOG_FG                    COLOR_BLACK +#define DIALOG_BG                    COLOR_WHITE +#define DIALOG_HL                    FALSE + +#define TITLE_FG                     COLOR_YELLOW +#define TITLE_BG                     COLOR_WHITE +#define TITLE_HL                     TRUE + +#define BORDER_FG                    COLOR_WHITE +#define BORDER_BG                    COLOR_WHITE +#define BORDER_HL                    TRUE + +#define BUTTON_ACTIVE_FG             COLOR_WHITE +#define BUTTON_ACTIVE_BG             COLOR_BLUE +#define BUTTON_ACTIVE_HL             TRUE + +#define BUTTON_INACTIVE_FG           COLOR_BLACK +#define BUTTON_INACTIVE_BG           COLOR_WHITE +#define BUTTON_INACTIVE_HL           FALSE + +#define BUTTON_KEY_ACTIVE_FG         COLOR_WHITE +#define BUTTON_KEY_ACTIVE_BG         COLOR_BLUE +#define BUTTON_KEY_ACTIVE_HL         TRUE + +#define BUTTON_KEY_INACTIVE_FG       COLOR_RED +#define BUTTON_KEY_INACTIVE_BG       COLOR_WHITE +#define BUTTON_KEY_INACTIVE_HL       FALSE + +#define BUTTON_LABEL_ACTIVE_FG       COLOR_YELLOW +#define BUTTON_LABEL_ACTIVE_BG       COLOR_BLUE +#define BUTTON_LABEL_ACTIVE_HL       TRUE + +#define BUTTON_LABEL_INACTIVE_FG     COLOR_BLACK +#define BUTTON_LABEL_INACTIVE_BG     COLOR_WHITE +#define BUTTON_LABEL_INACTIVE_HL     TRUE + +#define INPUTBOX_FG                  COLOR_BLACK +#define INPUTBOX_BG                  COLOR_WHITE +#define INPUTBOX_HL                  FALSE + +#define INPUTBOX_BORDER_FG           COLOR_BLACK +#define INPUTBOX_BORDER_BG           COLOR_WHITE +#define INPUTBOX_BORDER_HL           FALSE + +#define SEARCHBOX_FG                 COLOR_BLACK +#define SEARCHBOX_BG                 COLOR_WHITE +#define SEARCHBOX_HL                 FALSE + +#define SEARCHBOX_TITLE_FG           COLOR_YELLOW +#define SEARCHBOX_TITLE_BG           COLOR_WHITE +#define SEARCHBOX_TITLE_HL           TRUE + +#define SEARCHBOX_BORDER_FG          COLOR_WHITE +#define SEARCHBOX_BORDER_BG          COLOR_WHITE +#define SEARCHBOX_BORDER_HL          TRUE + +#define POSITION_INDICATOR_FG        COLOR_YELLOW +#define POSITION_INDICATOR_BG        COLOR_WHITE +#define POSITION_INDICATOR_HL        TRUE + +#define MENUBOX_FG                   COLOR_BLACK +#define MENUBOX_BG                   COLOR_WHITE +#define MENUBOX_HL                   FALSE + +#define MENUBOX_BORDER_FG            COLOR_WHITE +#define MENUBOX_BORDER_BG            COLOR_WHITE +#define MENUBOX_BORDER_HL            TRUE + +#define ITEM_FG                      COLOR_BLACK +#define ITEM_BG                      COLOR_WHITE +#define ITEM_HL                      FALSE + +#define ITEM_SELECTED_FG             COLOR_WHITE +#define ITEM_SELECTED_BG             COLOR_BLUE +#define ITEM_SELECTED_HL             TRUE + +#define TAG_FG                       COLOR_YELLOW +#define TAG_BG                       COLOR_WHITE +#define TAG_HL                       TRUE + +#define TAG_SELECTED_FG              COLOR_YELLOW +#define TAG_SELECTED_BG              COLOR_BLUE +#define TAG_SELECTED_HL              TRUE + +#define TAG_KEY_FG                   COLOR_YELLOW +#define TAG_KEY_BG                   COLOR_WHITE +#define TAG_KEY_HL                   TRUE + +#define TAG_KEY_SELECTED_FG          COLOR_YELLOW +#define TAG_KEY_SELECTED_BG          COLOR_BLUE +#define TAG_KEY_SELECTED_HL          TRUE + +#define CHECK_FG                     COLOR_BLACK +#define CHECK_BG                     COLOR_WHITE +#define CHECK_HL                     FALSE + +#define CHECK_SELECTED_FG            COLOR_WHITE +#define CHECK_SELECTED_BG            COLOR_BLUE +#define CHECK_SELECTED_HL            TRUE + +#define UARROW_FG                    COLOR_GREEN +#define UARROW_BG                    COLOR_WHITE +#define UARROW_HL                    TRUE + +#define DARROW_FG                    COLOR_GREEN +#define DARROW_BG                    COLOR_WHITE +#define DARROW_HL                    TRUE + +/* End of default color definitions */ + +#define C_ATTR(x,y)                  ((x ? A_BOLD : 0) | COLOR_PAIR((y))) +#define COLOR_NAME_LEN               10 +#define COLOR_COUNT                  8 + +/* + * Global variables + */ + +extern int color_table[][3]; diff --git a/scripts/lxdialog/dialog.h b/scripts/lxdialog/dialog.h new file mode 100644 index 000000000000..c571548daa82 --- /dev/null +++ b/scripts/lxdialog/dialog.h @@ -0,0 +1,187 @@ + +/* + *  dialog.h -- common declarations for all dialog modules + * + *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#ifdef __sun__ +#define CURS_MACROS +#endif +#include CURSES_LOC + +/* + * Colors in ncurses 1.9.9e do not work properly since foreground and + * background colors are OR'd rather than separately masked.  This version + * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible + * with standard curses.  The simplest fix (to make this work with standard + * curses) uses the wbkgdset() function, not used in the original hack. + * Turn it off if we're building with 1.9.9e, since it just confuses things. + */ +#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) +#define OLD_NCURSES 1 +#undef  wbkgdset +#define wbkgdset(w,p) /*nothing*/ +#else +#define OLD_NCURSES 0 +#endif + +#define TR(params) _tracef params + +#define ESC 27 +#define TAB 9 +#define MAX_LEN 2048 +#define BUF_SIZE (10*1024) +#define MIN(x,y) (x < y ? x : y) +#define MAX(x,y) (x > y ? x : y) + + +#ifndef ACS_ULCORNER +#define ACS_ULCORNER '+' +#endif +#ifndef ACS_LLCORNER +#define ACS_LLCORNER '+' +#endif +#ifndef ACS_URCORNER +#define ACS_URCORNER '+' +#endif +#ifndef ACS_LRCORNER +#define ACS_LRCORNER '+' +#endif +#ifndef ACS_HLINE +#define ACS_HLINE '-' +#endif +#ifndef ACS_VLINE +#define ACS_VLINE '|' +#endif +#ifndef ACS_LTEE +#define ACS_LTEE '+' +#endif +#ifndef ACS_RTEE +#define ACS_RTEE '+' +#endif +#ifndef ACS_UARROW +#define ACS_UARROW '^' +#endif +#ifndef ACS_DARROW +#define ACS_DARROW 'v' +#endif + +/*  + * Attribute names + */ +#define screen_attr                   attributes[0] +#define shadow_attr                   attributes[1] +#define dialog_attr                   attributes[2] +#define title_attr                    attributes[3] +#define border_attr                   attributes[4] +#define button_active_attr            attributes[5] +#define button_inactive_attr          attributes[6] +#define button_key_active_attr        attributes[7] +#define button_key_inactive_attr      attributes[8] +#define button_label_active_attr      attributes[9] +#define button_label_inactive_attr    attributes[10] +#define inputbox_attr                 attributes[11] +#define inputbox_border_attr          attributes[12] +#define searchbox_attr                attributes[13] +#define searchbox_title_attr          attributes[14] +#define searchbox_border_attr         attributes[15] +#define position_indicator_attr       attributes[16] +#define menubox_attr                  attributes[17] +#define menubox_border_attr           attributes[18] +#define item_attr                     attributes[19] +#define item_selected_attr            attributes[20] +#define tag_attr                      attributes[21] +#define tag_selected_attr             attributes[22] +#define tag_key_attr                  attributes[23] +#define tag_key_selected_attr         attributes[24] +#define check_attr                    attributes[25] +#define check_selected_attr           attributes[26] +#define uarrow_attr                   attributes[27] +#define darrow_attr                   attributes[28] + +/* number of attributes */ +#define ATTRIBUTE_COUNT               29 + +/* + * Global variables + */ +extern bool use_colors; +extern bool use_shadow; + +extern chtype attributes[]; + +extern const char *backtitle; + +/* + * Function prototypes + */ +extern void create_rc (const char *filename); +extern int parse_rc (void); + + +void init_dialog (void); +void end_dialog (void); +void attr_clear (WINDOW * win, int height, int width, chtype attr); +void dialog_clear (void); +void color_setup (void); +void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x); +void print_button (WINDOW * win, const char *label, int y, int x, int selected); +void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box, +		chtype border); +void draw_shadow (WINDOW * win, int y, int x, int height, int width); + +int first_alpha (const char *string, const char *exempt); +int dialog_yesno (const char *title, const char *prompt, int height, int width); +int dialog_msgbox (const char *title, const char *prompt, int height, +		int width, int pause); +int dialog_textbox (const char *title, const char *file, int height, int width); +int dialog_menu (const char *title, const char *prompt, int height, int width, +		int menu_height, const char *choice, int item_no,  +		const char * const * items); +int dialog_checklist (const char *title, const char *prompt, int height, +		int width, int list_height, int item_no, +		const char * const * items, int flag); +extern unsigned char dialog_input_result[]; +int dialog_inputbox (const char *title, const char *prompt, int height, +		int width, const char *init); + +/* + * This is the base for fictitious keys, which activate + * the buttons. + * + * Mouse-generated keys are the following: + *   -- the first 32 are used as numbers, in addition to '0'-'9' + *   -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') + *   -- uppercase chars are used to invoke the button (M_EVENT + 'O') + */ +#define M_EVENT (KEY_MAX+1) + + +/* + * The `flag' parameter in checklist is used to select between + * radiolist and checklist + */ +#define FLAG_CHECK 1 +#define FLAG_RADIO 0 diff --git a/scripts/lxdialog/inputbox.c b/scripts/lxdialog/inputbox.c new file mode 100644 index 000000000000..fa7bebc693b9 --- /dev/null +++ b/scripts/lxdialog/inputbox.c @@ -0,0 +1,240 @@ +/* + *  inputbox.c -- implements the input box + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +unsigned char dialog_input_result[MAX_LEN + 1]; + +/* + *  Print the termination buttons + */ +static void +print_buttons(WINDOW *dialog, int height, int width, int selected) +{ +    int x = width / 2 - 11; +    int y = height - 2; + +    print_button (dialog, "  Ok  ", y, x, selected==0); +    print_button (dialog, " Help ", y, x + 14, selected==1); + +    wmove(dialog, y, x+1+14*selected); +    wrefresh(dialog); +} + +/* + * Display a dialog box for inputing a string + */ +int +dialog_inputbox (const char *title, const char *prompt, int height, int width, +		 const char *init) +{ +    int i, x, y, box_y, box_x, box_width; +    int input_x = 0, scroll = 0, key = 0, button = -1; +    unsigned char *instr = dialog_input_result; +    WINDOW *dialog; + +    /* center dialog box on screen */ +    x = (COLS - width) / 2; +    y = (LINES - height) / 2; + + +    draw_shadow (stdscr, y, x, height, width); + +    dialog = newwin (height, width, y, x); +    keypad (dialog, TRUE); + +    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); +    wattrset (dialog, border_attr); +    mvwaddch (dialog, height-3, 0, ACS_LTEE); +    for (i = 0; i < width - 2; i++) +	waddch (dialog, ACS_HLINE); +    wattrset (dialog, dialog_attr); +    waddch (dialog, ACS_RTEE); + +    if (title != NULL && strlen(title) >= width-2 ) { +	/* truncate long title -- mec */ +	char * title2 = malloc(width-2+1); +	memcpy( title2, title, width-2 ); +	title2[width-2] = '\0'; +	title = title2; +    } + +    if (title != NULL) { +	wattrset (dialog, title_attr); +	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); +	waddstr (dialog, (char *)title); +	waddch (dialog, ' '); +    } + +    wattrset (dialog, dialog_attr); +    print_autowrap (dialog, prompt, width - 2, 1, 3); + +    /* Draw the input field box */ +    box_width = width - 6; +    getyx (dialog, y, x); +    box_y = y + 2; +    box_x = (width - box_width) / 2; +    draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2, +	      border_attr, dialog_attr); + +    print_buttons(dialog, height, width, 0); + +    /* Set up the initial value */ +    wmove (dialog, box_y, box_x); +    wattrset (dialog, inputbox_attr); + +    if (!init) +	instr[0] = '\0'; +    else +	strcpy (instr, init); + +    input_x = strlen (instr); + +    if (input_x >= box_width) { +	scroll = input_x - box_width + 1; +	input_x = box_width - 1; +	for (i = 0; i < box_width - 1; i++) +	    waddch (dialog, instr[scroll + i]); +    } else +	waddstr (dialog, instr); + +    wmove (dialog, box_y, box_x + input_x); + +    wrefresh (dialog); + +    while (key != ESC) { +	key = wgetch (dialog); + +	if (button == -1) {	/* Input box selected */ +	    switch (key) { +	    case TAB: +	    case KEY_UP: +	    case KEY_DOWN: +		break; +	    case KEY_LEFT: +		continue; +	    case KEY_RIGHT: +		continue; +	    case KEY_BACKSPACE: +	    case 127: +		if (input_x || scroll) { +		    wattrset (dialog, inputbox_attr); +		    if (!input_x) { +			scroll = scroll < box_width - 1 ? +			    0 : scroll - (box_width - 1); +			wmove (dialog, box_y, box_x); +			for (i = 0; i < box_width; i++) +			    waddch (dialog, instr[scroll + input_x + i] ? +				    instr[scroll + input_x + i] : ' '); +			input_x = strlen (instr) - scroll; +		    } else +			input_x--; +		    instr[scroll + input_x] = '\0'; +		    mvwaddch (dialog, box_y, input_x + box_x, ' '); +		    wmove (dialog, box_y, input_x + box_x); +		    wrefresh (dialog); +		} +		continue; +	    default: +		if (key < 0x100 && isprint (key)) { +		    if (scroll + input_x < MAX_LEN) { +			wattrset (dialog, inputbox_attr); +			instr[scroll + input_x] = key; +			instr[scroll + input_x + 1] = '\0'; +			if (input_x == box_width - 1) { +			    scroll++; +			    wmove (dialog, box_y, box_x); +			    for (i = 0; i < box_width - 1; i++) +				waddch (dialog, instr[scroll + i]); +			} else { +			    wmove (dialog, box_y, input_x++ + box_x); +			    waddch (dialog, key); +			} +			wrefresh (dialog); +		    } else +			flash ();	/* Alarm user about overflow */ +		    continue; +		} +	    } +	} +	switch (key) { +	case 'O': +	case 'o': +	    delwin (dialog); +	    return 0; +	case 'H': +	case 'h': +	    delwin (dialog); +	    return 1; +	case KEY_UP: +	case KEY_LEFT: +	    switch (button) { +	    case -1: +		button = 1;	/* Indicates "Cancel" button is selected */ +		print_buttons(dialog, height, width, 1); +		break; +	    case 0: +		button = -1;	/* Indicates input box is selected */ +		print_buttons(dialog, height, width, 0); +		wmove (dialog, box_y, box_x + input_x); +		wrefresh (dialog); +		break; +	    case 1: +		button = 0;	/* Indicates "OK" button is selected */ +		print_buttons(dialog, height, width, 0); +		break; +	    } +	    break; +	case TAB: +	case KEY_DOWN: +	case KEY_RIGHT: +	    switch (button) { +	    case -1: +		button = 0;	/* Indicates "OK" button is selected */ +		print_buttons(dialog, height, width, 0); +		break; +	    case 0: +		button = 1;	/* Indicates "Cancel" button is selected */ +		print_buttons(dialog, height, width, 1); +		break; +	    case 1: +		button = -1;	/* Indicates input box is selected */ +		print_buttons(dialog, height, width, 0); +		wmove (dialog, box_y, box_x + input_x); +		wrefresh (dialog); +		break; +	    } +	    break; +	case ' ': +	case '\n': +	    delwin (dialog); +	    return (button == -1 ? 0 : button); +	case 'X': +	case 'x': +	    key = ESC; +	case ESC: +	    break; +	} +    } + +    delwin (dialog); +    return -1;			/* ESC pressed */ +} diff --git a/scripts/lxdialog/lxdialog.c b/scripts/lxdialog/lxdialog.c new file mode 100644 index 000000000000..f283a8545426 --- /dev/null +++ b/scripts/lxdialog/lxdialog.c @@ -0,0 +1,226 @@ +/* + *  dialog - Display simple dialog boxes from shell scripts + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void Usage (const char *name); + +typedef int (jumperFn) (const char *title, int argc, const char * const * argv); + +struct Mode { +    char *name; +    int argmin, argmax, argmod; +    jumperFn *jumper; +}; + +jumperFn j_menu, j_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox; +jumperFn j_msgbox, j_infobox; + +static struct Mode modes[] = +{ +    {"--menu", 9, 0, 3, j_menu}, +    {"--checklist", 9, 0, 3, j_checklist}, +    {"--radiolist", 9, 0, 3, j_radiolist}, +    {"--yesno",    5,5,1, j_yesno}, +    {"--textbox",  5,5,1, j_textbox}, +    {"--inputbox", 5, 6, 1, j_inputbox}, +    {"--msgbox", 5, 5, 1, j_msgbox}, +    {"--infobox", 5, 5, 1, j_infobox}, +    {NULL, 0, 0, 0, NULL} +}; + +static struct Mode *modePtr; + +#ifdef LOCALE +#include <locale.h> +#endif + +int +main (int argc, const char * const * argv) +{ +    int offset = 0, opt_clear = 0, end_common_opts = 0, retval; +    const char *title = NULL; + +#ifdef LOCALE +    (void) setlocale (LC_ALL, ""); +#endif + +#ifdef TRACE +    trace(TRACE_CALLS|TRACE_UPDATE); +#endif +    if (argc < 2) { +	Usage (argv[0]); +	exit (-1); +    } + +    while (offset < argc - 1 && !end_common_opts) {	/* Common options */ +	if (!strcmp (argv[offset + 1], "--title")) { +	    if (argc - offset < 3 || title != NULL) { +		Usage (argv[0]); +		exit (-1); +	    } else { +		title = argv[offset + 2]; +		offset += 2; +	    } +        } else if (!strcmp (argv[offset + 1], "--backtitle")) { +            if (backtitle != NULL) { +                Usage (argv[0]); +                exit (-1); +            } else { +                backtitle = argv[offset + 2]; +                offset += 2; +            } +	} else if (!strcmp (argv[offset + 1], "--clear")) { +	    if (opt_clear) {		/* Hey, "--clear" can't appear twice! */ +		Usage (argv[0]); +		exit (-1); +	    } else if (argc == 2) {	/* we only want to clear the screen */ +		init_dialog (); +		refresh ();	/* init_dialog() will clear the screen for us */ +		end_dialog (); +		return 0; +	    } else { +		opt_clear = 1; +		offset++; +	    } +	} else			/* no more common options */ +	    end_common_opts = 1; +    } + +    if (argc - 1 == offset) {	/* no more options */ +	Usage (argv[0]); +	exit (-1); +    } +    /* use a table to look for the requested mode, to avoid code duplication */ + +    for (modePtr = modes; modePtr->name; modePtr++)	/* look for the mode */ +	if (!strcmp (argv[offset + 1], modePtr->name)) +	    break; + +    if (!modePtr->name) +	Usage (argv[0]); +    if (argc - offset < modePtr->argmin) +	Usage (argv[0]); +    if (modePtr->argmax && argc - offset > modePtr->argmax) +	Usage (argv[0]); + + + +    init_dialog (); +    retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset); + +    if (opt_clear) {		/* clear screen before exit */ +	attr_clear (stdscr, LINES, COLS, screen_attr); +	refresh (); +    } +    end_dialog(); + +    exit (retval); +} + +/* + * Print program usage + */ +static void +Usage (const char *name) +{ +    fprintf (stderr, "\ +\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\ +\n  patched by Stuart Herbert (S.Herbert@shef.ac.uk)\ +\n  modified/gutted for use as a Linux kernel config tool by \ +\n  William Roadcap (roadcapw@cfw.com)\ +\n\ +\n* Display dialog boxes from shell scripts *\ +\n\ +\nUsage: %s --clear\ +\n       %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\ +\n\ +\nBox options:\ +\n\ +\n  --menu      <text> <height> <width> <menu height> <tag1> <item1>...\ +\n  --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\ +\n  --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\ +\n  --textbox   <file> <height> <width>\ +\n  --inputbox  <text> <height> <width> [<init>]\ +\n  --yesno     <text> <height> <width>\ +\n", name, name); +    exit (-1); +} + +/* + * These are the program jumpers + */ + +int +j_menu (const char *t, int ac, const char * const * av) +{ +    return dialog_menu (t, av[2], atoi (av[3]), atoi (av[4]), +			atoi (av[5]), av[6], (ac - 6) / 2, av + 7); +} + +int +j_checklist (const char *t, int ac, const char * const * av) +{ +    return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]), +	atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_CHECK); +} + +int +j_radiolist (const char *t, int ac, const char * const * av) +{ +    return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]), +	atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_RADIO); +} + +int +j_textbox (const char *t, int ac, const char * const * av) +{ +    return dialog_textbox (t, av[2], atoi (av[3]), atoi (av[4])); +} + +int +j_yesno (const char *t, int ac, const char * const * av) +{ +    return dialog_yesno (t, av[2], atoi (av[3]), atoi (av[4])); +} + +int +j_inputbox (const char *t, int ac, const char * const * av) +{ +    int ret = dialog_inputbox (t, av[2], atoi (av[3]), atoi (av[4]), +                            ac == 6 ? av[5] : (char *) NULL); +    if (ret == 0) +        fprintf(stderr, dialog_input_result); +    return ret; +} + +int +j_msgbox (const char *t, int ac, const char * const * av) +{ +    return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 1); +} + +int +j_infobox (const char *t, int ac, const char * const * av) +{ +    return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 0); +} + diff --git a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c new file mode 100644 index 000000000000..91d82ba17f8d --- /dev/null +++ b/scripts/lxdialog/menubox.c @@ -0,0 +1,445 @@ +/* + *  menubox.c -- implements the menu box + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + *  Changes by Clifford Wolf (god@clifford.at) + * + *  [ 1998-06-13 ] + * + *    *)  A bugfix for the Page-Down problem + * + *    *)  Formerly when I used Page Down and Page Up, the cursor would be set  + *        to the first position in the menu box.  Now lxdialog is a bit + *        smarter and works more like other menu systems (just have a look at + *        it). + * + *    *)  Formerly if I selected something my scrolling would be broken because + *        lxdialog is re-invoked by the Menuconfig shell script, can't + *        remember the last scrolling position, and just sets it so that the + *        cursor is at the bottom of the box.  Now it writes the temporary file + *        lxdialog.scrltmp which contains this information. The file is + *        deleted by lxdialog if the user leaves a submenu or enters a new + *        one, but it would be nice if Menuconfig could make another "rm -f" + *        just to be sure.  Just try it out - you will recognise a difference! + * + *  [ 1998-06-14 ] + * + *    *)  Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files + *        and menus change their size on the fly. + * + *    *)  If for some reason the last scrolling position is not saved by + *        lxdialog, it sets the scrolling so that the selected item is in the + *        middle of the menu box, not at the bottom. + * + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. + * This fixes a bug in Menuconfig where using ' ' to descend into menus + * would leave mis-synchronized lxdialog.scrltmp files lying around, + * fscanf would read in 'scroll', and eventually that value would get used. + */ + +#include "dialog.h" + +static int menu_width, item_x; + +/* + * Print menu item + */ +static void +print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey) +{ +    int j; +    char menu_item[menu_width+1]; + +    strncpy(menu_item, item, menu_width); +    menu_item[menu_width] = 0; +    j = first_alpha(menu_item, "YyNnMmHh"); + +    /* Clear 'residue' of last item */ +    wattrset (win, menubox_attr); +    wmove (win, choice, 0); +#if OLD_NCURSES +    { +        int i; +        for (i = 0; i < menu_width; i++) +	    waddch (win, ' '); +    } +#else +    wclrtoeol(win); +#endif +    wattrset (win, selected ? item_selected_attr : item_attr); +    mvwaddstr (win, choice, item_x, menu_item); +    if (hotkey) { +    	wattrset (win, selected ? tag_key_selected_attr : tag_key_attr); +    	mvwaddch(win, choice, item_x+j, menu_item[j]); +    } +    if (selected) { +	wmove (win, choice, item_x+1); +	wrefresh (win); +    } +} + +/* + * Print the scroll indicators. + */ +static void +print_arrows (WINDOW * win, int item_no, int scroll, +		int y, int x, int height) +{ +    int cur_y, cur_x; + +    getyx(win, cur_y, cur_x); + +    wmove(win, y, x); + +    if (scroll > 0) { +	wattrset (win, uarrow_attr); +	waddch (win, ACS_UARROW); +	waddstr (win, "(-)"); +    } +    else { +	wattrset (win, menubox_attr); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +    } + +   y = y + height + 1; +   wmove(win, y, x); + +   if ((height < item_no) && (scroll + height < item_no)) { +	wattrset (win, darrow_attr); +	waddch (win, ACS_DARROW); +	waddstr (win, "(+)"); +    } +    else { +	wattrset (win, menubox_border_attr); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +	waddch (win, ACS_HLINE); +   } + +   wmove(win, cur_y, cur_x); +} + +/* + * Display the termination buttons. + */ +static void +print_buttons (WINDOW *win, int height, int width, int selected) +{ +    int x = width / 2 - 16; +    int y = height - 2; + +    print_button (win, "Select", y, x, selected == 0); +    print_button (win, " Exit ", y, x + 12, selected == 1); +    print_button (win, " Help ", y, x + 24, selected == 2); + +    wmove(win, y, x+1+12*selected); +    wrefresh (win); +} + +/* + * Display a menu for choosing among a number of options + */ +int +dialog_menu (const char *title, const char *prompt, int height, int width, +		int menu_height, const char *current, int item_no, +		const char * const * items) + +{ +    int i, j, x, y, box_x, box_y; +    int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice; +    WINDOW *dialog, *menu; +    FILE *f; + +    max_choice = MIN (menu_height, item_no); + +    /* center dialog box on screen */ +    x = (COLS - width) / 2; +    y = (LINES - height) / 2; + +    draw_shadow (stdscr, y, x, height, width); + +    dialog = newwin (height, width, y, x); +    keypad (dialog, TRUE); + +    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); +    wattrset (dialog, border_attr); +    mvwaddch (dialog, height - 3, 0, ACS_LTEE); +    for (i = 0; i < width - 2; i++) +	waddch (dialog, ACS_HLINE); +    wattrset (dialog, dialog_attr); +    wbkgdset (dialog, dialog_attr & A_COLOR); +    waddch (dialog, ACS_RTEE); + +    if (title != NULL && strlen(title) >= width-2 ) { +	/* truncate long title -- mec */ +	char * title2 = malloc(width-2+1); +	memcpy( title2, title, width-2 ); +	title2[width-2] = '\0'; +	title = title2; +    } + +    if (title != NULL) { +	wattrset (dialog, title_attr); +	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); +	waddstr (dialog, (char *)title); +	waddch (dialog, ' '); +    } + +    wattrset (dialog, dialog_attr); +    print_autowrap (dialog, prompt, width - 2, 1, 3); + +    menu_width = width - 6; +    box_y = height - menu_height - 5; +    box_x = (width - menu_width) / 2 - 1; + +    /* create new window for the menu */ +    menu = subwin (dialog, menu_height, menu_width, +		y + box_y + 1, x + box_x + 1); +    keypad (menu, TRUE); + +    /* draw a box around the menu items */ +    draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2, +	      menubox_border_attr, menubox_attr); + +    /* +     * Find length of longest item in order to center menu. +     * Set 'choice' to default item.  +     */ +    item_x = 0; +    for (i = 0; i < item_no; i++) { +	item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2)); +	if (strcmp(current, items[i*2]) == 0) choice = i; +    } + +    item_x = (menu_width - item_x) / 2; + +    /* get the scroll info from the temp file */ +    if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) { +	if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) && +	     (scroll+max_choice > choice) && (scroll >= 0) && +	     (scroll+max_choice <= item_no) ) { +	    first_item = scroll; +	    choice = choice - scroll; +	    fclose(f); +	} else { +	    scroll=0; +	    remove("lxdialog.scrltmp"); +	    fclose(f); +	    f=NULL; +	} +    } +    if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) { +	if (choice >= item_no-max_choice/2) +	    scroll = first_item = item_no-max_choice; +	else +	    scroll = first_item = choice - max_choice/2; +	choice = choice - scroll; +    } + +    /* Print the menu */ +    for (i=0; i < max_choice; i++) { +	print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice, +                    (items[(first_item + i)*2][0] != ':')); +    } + +    wnoutrefresh (menu); + +    print_arrows(dialog, item_no, scroll, +		 box_y, box_x+item_x+1, menu_height); + +    print_buttons (dialog, height, width, 0); +    wmove (menu, choice, item_x+1); +    wrefresh (menu); + +    while (key != ESC) { +	key = wgetch(menu); + +	if (key < 256 && isalpha(key)) key = tolower(key); + +	if (strchr("ynmh", key)) +		i = max_choice; +	else { +        for (i = choice+1; i < max_choice; i++) { +		j = first_alpha(items[(scroll+i)*2+1], "YyNnMmHh"); +		if (key == tolower(items[(scroll+i)*2+1][j])) +                	break; +	} +	if (i == max_choice) +       		for (i = 0; i < max_choice; i++) { +			j = first_alpha(items[(scroll+i)*2+1], "YyNnMmHh"); +			if (key == tolower(items[(scroll+i)*2+1][j])) +                		break; +		} +	} + +	if (i < max_choice ||  +            key == KEY_UP || key == KEY_DOWN || +            key == '-' || key == '+' || +            key == KEY_PPAGE || key == KEY_NPAGE) { + +            print_item (menu, items[(scroll+choice)*2+1], choice, FALSE, +                       (items[(scroll+choice)*2][0] != ':')); + +	    if (key == KEY_UP || key == '-') { +                if (choice < 2 && scroll) { +	            /* Scroll menu down */ +                    scrollok (menu, TRUE); +                    wscrl (menu, -1); +                    scrollok (menu, FALSE); + +                    scroll--; + +                    print_item (menu, items[scroll * 2 + 1], 0, FALSE, +                               (items[scroll*2][0] != ':')); +		} else +		    choice = MAX(choice - 1, 0); + +	    } else if (key == KEY_DOWN || key == '+')  { + +		print_item (menu, items[(scroll+choice)*2+1], choice, FALSE, +                                (items[(scroll+choice)*2][0] != ':')); + +                if ((choice > max_choice-3) && +                    (scroll + max_choice < item_no) +                   ) { +		    /* Scroll menu up */ +		    scrollok (menu, TRUE); +		    wscrl (menu, 1); +                    scrollok (menu, FALSE); + +                    scroll++; + +                    print_item (menu, items[(scroll+max_choice-1)*2+1], +                               max_choice-1, FALSE, +                               (items[(scroll+max_choice-1)*2][0] != ':')); +                } else +                    choice = MIN(choice+1, max_choice-1); + +	    } else if (key == KEY_PPAGE) { +	        scrollok (menu, TRUE); +                for (i=0; (i < max_choice); i++) { +                    if (scroll > 0) { +                	wscrl (menu, -1); +                	scroll--; +                	print_item (menu, items[scroll * 2 + 1], 0, FALSE, +                	(items[scroll*2][0] != ':')); +                    } else { +                        if (choice > 0) +                            choice--; +                    } +                } +                scrollok (menu, FALSE); + +            } else if (key == KEY_NPAGE) { +                for (i=0; (i < max_choice); i++) { +                    if (scroll+max_choice < item_no) { +			scrollok (menu, TRUE); +			wscrl (menu, 1); +			scrollok (menu, FALSE); +                	scroll++; +                	print_item (menu, items[(scroll+max_choice-1)*2+1], +			            max_choice-1, FALSE, +			            (items[(scroll+max_choice-1)*2][0] != ':')); +		    } else { +			if (choice+1 < max_choice) +			    choice++; +		    } +                } + +            } else +                choice = i; + +            print_item (menu, items[(scroll+choice)*2+1], choice, TRUE, +                       (items[(scroll+choice)*2][0] != ':')); + +            print_arrows(dialog, item_no, scroll, +                         box_y, box_x+item_x+1, menu_height); + +            wnoutrefresh (dialog); +            wrefresh (menu); + +	    continue;		/* wait for another key press */ +        } + +	switch (key) { +	case KEY_LEFT: +	case TAB: +	case KEY_RIGHT: +	    button = ((key == KEY_LEFT ? --button : ++button) < 0) +			? 2 : (button > 2 ? 0 : button); + +	    print_buttons(dialog, height, width, button); +	    wrefresh (menu); +	    break; +	case ' ': +	case 's': +	case 'y': +	case 'n': +	case 'm': +	case '/': +	    /* save scroll info */ +	    if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) { +		fprintf(f,"%d\n",scroll); +		fclose(f); +	    } +	    delwin (dialog); +            fprintf(stderr, "%s\n", items[(scroll + choice) * 2]); +            switch (key) { +            case 's': return 3; +            case 'y': return 3; +            case 'n': return 4; +            case 'm': return 5; +            case ' ': return 6; +            case '/': return 7; +            } +	    return 0; +	case 'h': +	case '?': +	    button = 2; +	case '\n': +	    delwin (dialog); +	    if (button == 2)  +            	fprintf(stderr, "%s \"%s\"\n",  +			items[(scroll + choice) * 2], +			items[(scroll + choice) * 2 + 1] + +			first_alpha(items[(scroll + choice) * 2 + 1],"")); +	    else +            	fprintf(stderr, "%s\n", items[(scroll + choice) * 2]); + +	    remove("lxdialog.scrltmp"); +	    return button; +	case 'e': +	case 'x': +	    key = ESC; +	case ESC: +	    break; +	} +    } + +    delwin (dialog); +    remove("lxdialog.scrltmp"); +    return -1;			/* ESC pressed */ +} diff --git a/scripts/lxdialog/msgbox.c b/scripts/lxdialog/msgbox.c new file mode 100644 index 000000000000..93692e1fbcc2 --- /dev/null +++ b/scripts/lxdialog/msgbox.c @@ -0,0 +1,85 @@ +/* + *  msgbox.c -- implements the message box and info box + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display a message box. Program will pause and display an "OK" button + * if the parameter 'pause' is non-zero. + */ +int +dialog_msgbox (const char *title, const char *prompt, int height, int width, +		int pause) +{ +    int i, x, y, key = 0; +    WINDOW *dialog; + +    /* center dialog box on screen */ +    x = (COLS - width) / 2; +    y = (LINES - height) / 2; + +    draw_shadow (stdscr, y, x, height, width); + +    dialog = newwin (height, width, y, x); +    keypad (dialog, TRUE); + +    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); + +    if (title != NULL && strlen(title) >= width-2 ) { +	/* truncate long title -- mec */ +	char * title2 = malloc(width-2+1); +	memcpy( title2, title, width-2 ); +	title2[width-2] = '\0'; +	title = title2; +    } + +    if (title != NULL) { +	wattrset (dialog, title_attr); +	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); +	waddstr (dialog, (char *)title); +	waddch (dialog, ' '); +    } +    wattrset (dialog, dialog_attr); +    print_autowrap (dialog, prompt, width - 2, 1, 2); + +    if (pause) { +	wattrset (dialog, border_attr); +	mvwaddch (dialog, height - 3, 0, ACS_LTEE); +	for (i = 0; i < width - 2; i++) +	    waddch (dialog, ACS_HLINE); +	wattrset (dialog, dialog_attr); +	waddch (dialog, ACS_RTEE); + +	print_button (dialog, "  Ok  ", +		      height - 2, width / 2 - 4, TRUE); + +	wrefresh (dialog); +	while (key != ESC && key != '\n' && key != ' ' && +               key != 'O' && key != 'o' && key != 'X' && key != 'x') +	    key = wgetch (dialog); +    } else { +	key = '\n'; +	wrefresh (dialog); +    } + +    delwin (dialog); +    return key == ESC ? -1 : 0; +} diff --git a/scripts/lxdialog/textbox.c b/scripts/lxdialog/textbox.c new file mode 100644 index 000000000000..ed23df2d096a --- /dev/null +++ b/scripts/lxdialog/textbox.c @@ -0,0 +1,556 @@ +/* + *  textbox.c -- implements the text box + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void back_lines (int n); +static void print_page (WINDOW * win, int height, int width); +static void print_line (WINDOW * win, int row, int width); +static char *get_line (void); +static void print_position (WINDOW * win, int height, int width); + +static int hscroll, fd, file_size, bytes_read; +static int begin_reached = 1, end_reached, page_length; +static char *buf, *page; + +/* + * Display text from a file in a dialog box. + */ +int +dialog_textbox (const char *title, const char *file, int height, int width) +{ +    int i, x, y, cur_x, cur_y, fpos, key = 0; +    int passed_end; +    char search_term[MAX_LEN + 1]; +    WINDOW *dialog, *text; + +    search_term[0] = '\0';	/* no search term entered yet */ + +    /* Open input file for reading */ +    if ((fd = open (file, O_RDONLY)) == -1) { +	endwin (); +	fprintf (stderr, +		 "\nCan't open input file in dialog_textbox().\n"); +	exit (-1); +    } +    /* Get file size. Actually, 'file_size' is the real file size - 1, +       since it's only the last byte offset from the beginning */ +    if ((file_size = lseek (fd, 0, SEEK_END)) == -1) { +	endwin (); +	fprintf (stderr, "\nError getting file size in dialog_textbox().\n"); +	exit (-1); +    } +    /* Restore file pointer to beginning of file after getting file size */ +    if (lseek (fd, 0, SEEK_SET) == -1) { +	endwin (); +	fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n"); +	exit (-1); +    } +    /* Allocate space for read buffer */ +    if ((buf = malloc (BUF_SIZE + 1)) == NULL) { +	endwin (); +	fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n"); +	exit (-1); +    } +    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { +	endwin (); +	fprintf (stderr, "\nError reading file in dialog_textbox().\n"); +	exit (-1); +    } +    buf[bytes_read] = '\0';	/* mark end of valid data */ +    page = buf;			/* page is pointer to start of page to be displayed */ + +    /* center dialog box on screen */ +    x = (COLS - width) / 2; +    y = (LINES - height) / 2; + + +    draw_shadow (stdscr, y, x, height, width); + +    dialog = newwin (height, width, y, x); +    keypad (dialog, TRUE); + +    /* Create window for text region, used for scrolling text */ +    text = subwin (dialog, height - 4, width - 2, y + 1, x + 1); +    wattrset (text, dialog_attr); +    wbkgdset (text, dialog_attr & A_COLOR); + +    keypad (text, TRUE); + +    /* register the new window, along with its borders */ +    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); + +    wattrset (dialog, border_attr); +    mvwaddch (dialog, height-3, 0, ACS_LTEE); +    for (i = 0; i < width - 2; i++) +	waddch (dialog, ACS_HLINE); +    wattrset (dialog, dialog_attr); +    wbkgdset (dialog, dialog_attr & A_COLOR); +    waddch (dialog, ACS_RTEE); + +    if (title != NULL && strlen(title) >= width-2 ) { +	/* truncate long title -- mec */ +	char * title2 = malloc(width-2+1); +	memcpy( title2, title, width-2 ); +	title2[width-2] = '\0'; +	title = title2; +    } + +    if (title != NULL) { +	wattrset (dialog, title_attr); +	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); +	waddstr (dialog, (char *)title); +	waddch (dialog, ' '); +    } +    print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE); +    wnoutrefresh (dialog); +    getyx (dialog, cur_y, cur_x);	/* Save cursor position */ + +    /* Print first page of text */ +    attr_clear (text, height - 4, width - 2, dialog_attr); +    print_page (text, height - 4, width - 2); +    print_position (dialog, height, width); +    wmove (dialog, cur_y, cur_x);	/* Restore cursor position */ +    wrefresh (dialog); + +    while ((key != ESC) && (key != '\n')) { +	key = wgetch (dialog); +	switch (key) { +	case 'E':		/* Exit */ +	case 'e': +	case 'X': +	case 'x': +	    delwin (dialog); +	    free (buf); +	    close (fd); +	    return 0; +	case 'g':		/* First page */ +	case KEY_HOME: +	    if (!begin_reached) { +		begin_reached = 1; +		/* First page not in buffer? */ +		if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { +		    endwin (); +		    fprintf (stderr, +		      "\nError moving file pointer in dialog_textbox().\n"); +		    exit (-1); +		} +		if (fpos > bytes_read) {	/* Yes, we have to read it in */ +		    if (lseek (fd, 0, SEEK_SET) == -1) { +			endwin (); +			fprintf (stderr, "\nError moving file pointer in " +				 "dialog_textbox().\n"); +			exit (-1); +		    } +		    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { +			endwin (); +			fprintf (stderr, +			     "\nError reading file in dialog_textbox().\n"); +			exit (-1); +		    } +		    buf[bytes_read] = '\0'; +		} +		page = buf; +		print_page (text, height - 4, width - 2); +		print_position (dialog, height, width); +		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */ +		wrefresh (dialog); +	    } +	    break; +	case 'G':		/* Last page */ +	case KEY_END: + +	    end_reached = 1; +	    /* Last page not in buffer? */ +	    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { +		endwin (); +		fprintf (stderr, +		      "\nError moving file pointer in dialog_textbox().\n"); +		exit (-1); +	    } +	    if (fpos < file_size) {	/* Yes, we have to read it in */ +		if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) { +		    endwin (); +		    fprintf (stderr, +		      "\nError moving file pointer in dialog_textbox().\n"); +		    exit (-1); +		} +		if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { +		    endwin (); +		    fprintf (stderr, +			     "\nError reading file in dialog_textbox().\n"); +		    exit (-1); +		} +		buf[bytes_read] = '\0'; +	    } +	    page = buf + bytes_read; +	    back_lines (height - 4); +	    print_page (text, height - 4, width - 2); +	    print_position (dialog, height, width); +	    wmove (dialog, cur_y, cur_x);	/* Restore cursor position */ +	    wrefresh (dialog); +	    break; +	case 'K':		/* Previous line */ +	case 'k': +	case KEY_UP: +	    if (!begin_reached) { +		back_lines (page_length + 1); + +		/* We don't call print_page() here but use scrolling to ensure +		   faster screen update. However, 'end_reached' and +		   'page_length' should still be updated, and 'page' should +		   point to start of next page. This is done by calling +		   get_line() in the following 'for' loop. */ +		scrollok (text, TRUE); +		wscrl (text, -1);	/* Scroll text region down one line */ +		scrollok (text, FALSE); +		page_length = 0; +		passed_end = 0; +		for (i = 0; i < height - 4; i++) { +		    if (!i) { +			/* print first line of page */ +			print_line (text, 0, width - 2); +			wnoutrefresh (text); +		    } else +			/* Called to update 'end_reached' and 'page' */ +			get_line (); +		    if (!passed_end) +			page_length++; +		    if (end_reached && !passed_end) +			passed_end = 1; +		} + +		print_position (dialog, height, width); +		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */ +		wrefresh (dialog); +	    } +	    break; +	case 'B':		/* Previous page */ +	case 'b': +	case KEY_PPAGE: +	    if (begin_reached) +		break; +	    back_lines (page_length + height - 4); +	    print_page (text, height - 4, width - 2); +	    print_position (dialog, height, width); +	    wmove (dialog, cur_y, cur_x); +	    wrefresh (dialog); +	    break; +	case 'J':		/* Next line */ +	case 'j': +	case KEY_DOWN: +	    if (!end_reached) { +		begin_reached = 0; +		scrollok (text, TRUE); +		scroll (text);	/* Scroll text region up one line */ +		scrollok (text, FALSE); +		print_line (text, height - 5, width - 2); +		wnoutrefresh (text); +		print_position (dialog, height, width); +		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */ +		wrefresh (dialog); +	    } +	    break; +	case KEY_NPAGE:		/* Next page */ +	case ' ': +	    if (end_reached) +		break; + +	    begin_reached = 0; +	    print_page (text, height - 4, width - 2); +	    print_position (dialog, height, width); +	    wmove (dialog, cur_y, cur_x); +	    wrefresh (dialog); +	    break; +	case '0':		/* Beginning of line */ +	case 'H':		/* Scroll left */ +	case 'h': +	case KEY_LEFT: +	    if (hscroll <= 0) +		break; + +	    if (key == '0') +		hscroll = 0; +	    else +		hscroll--; +	    /* Reprint current page to scroll horizontally */ +	    back_lines (page_length); +	    print_page (text, height - 4, width - 2); +	    wmove (dialog, cur_y, cur_x); +	    wrefresh (dialog); +	    break; +	case 'L':		/* Scroll right */ +	case 'l': +	case KEY_RIGHT: +	    if (hscroll >= MAX_LEN) +		break; +	    hscroll++; +	    /* Reprint current page to scroll horizontally */ +	    back_lines (page_length); +	    print_page (text, height - 4, width - 2); +	    wmove (dialog, cur_y, cur_x); +	    wrefresh (dialog); +	    break; +	case ESC: +	    break; +	} +    } + +    delwin (dialog); +    free (buf); +    close (fd); +    return -1;			/* ESC pressed */ +} + +/* + * Go back 'n' lines in text file. Called by dialog_textbox(). + * 'page' will be updated to point to the desired line in 'buf'. + */ +static void +back_lines (int n) +{ +    int i, fpos; + +    begin_reached = 0; +    /* We have to distinguish between end_reached and !end_reached +       since at end of file, the line is not ended by a '\n'. +       The code inside 'if' basically does a '--page' to move one +       character backward so as to skip '\n' of the previous line */ +    if (!end_reached) { +	/* Either beginning of buffer or beginning of file reached? */ +	if (page == buf) { +	    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { +		endwin (); +		fprintf (stderr, "\nError moving file pointer in " +			 "back_lines().\n"); +		exit (-1); +	    } +	    if (fpos > bytes_read) {	/* Not beginning of file yet */ +		/* We've reached beginning of buffer, but not beginning of +		   file yet, so read previous part of file into buffer. +		   Note that we only move backward for BUF_SIZE/2 bytes, +		   but not BUF_SIZE bytes to avoid re-reading again in +		   print_page() later */ +		/* Really possible to move backward BUF_SIZE/2 bytes? */ +		if (fpos < BUF_SIZE / 2 + bytes_read) { +		    /* No, move less then */ +		    if (lseek (fd, 0, SEEK_SET) == -1) { +			endwin (); +			fprintf (stderr, "\nError moving file pointer in " +				 "back_lines().\n"); +			exit (-1); +		    } +		    page = buf + fpos - bytes_read; +		} else {	/* Move backward BUF_SIZE/2 bytes */ +		    if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) +			== -1) { +			endwin (); +			fprintf (stderr, "\nError moving file pointer " +				 "in back_lines().\n"); +			exit (-1); +		    } +		    page = buf + BUF_SIZE / 2; +		} +		if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { +		    endwin (); +		    fprintf (stderr, "\nError reading file in back_lines().\n"); +		    exit (-1); +		} +		buf[bytes_read] = '\0'; +	    } else {		/* Beginning of file reached */ +		begin_reached = 1; +		return; +	    } +	} +	if (*(--page) != '\n') {	/* '--page' here */ +	    /* Something's wrong... */ +	    endwin (); +	    fprintf (stderr, "\nInternal error in back_lines().\n"); +	    exit (-1); +	} +    } +    /* Go back 'n' lines */ +    for (i = 0; i < n; i++) +	do { +	    if (page == buf) { +		if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { +		    endwin (); +		    fprintf (stderr, +			  "\nError moving file pointer in back_lines().\n"); +		    exit (-1); +		} +		if (fpos > bytes_read) { +		    /* Really possible to move backward BUF_SIZE/2 bytes? */ +		    if (fpos < BUF_SIZE / 2 + bytes_read) { +			/* No, move less then */ +			if (lseek (fd, 0, SEEK_SET) == -1) { +			    endwin (); +			    fprintf (stderr, "\nError moving file pointer " +				     "in back_lines().\n"); +			    exit (-1); +			} +			page = buf + fpos - bytes_read; +		    } else {	/* Move backward BUF_SIZE/2 bytes */ +			if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), +				   SEEK_CUR) == -1) { +			    endwin (); +			    fprintf (stderr, "\nError moving file pointer" +				     " in back_lines().\n"); +			    exit (-1); +			} +			page = buf + BUF_SIZE / 2; +		    } +		    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { +			endwin (); +			fprintf (stderr, "\nError reading file in " +				 "back_lines().\n"); +			exit (-1); +		    } +		    buf[bytes_read] = '\0'; +		} else {	/* Beginning of file reached */ +		    begin_reached = 1; +		    return; +		} +	    } +	} while (*(--page) != '\n'); +    page++; +} + +/* + * Print a new page of text. Called by dialog_textbox(). + */ +static void +print_page (WINDOW * win, int height, int width) +{ +    int i, passed_end = 0; + +    page_length = 0; +    for (i = 0; i < height; i++) { +	print_line (win, i, width); +	if (!passed_end) +	    page_length++; +	if (end_reached && !passed_end) +	    passed_end = 1; +    } +    wnoutrefresh (win); +} + +/* + * Print a new line of text. Called by dialog_textbox() and print_page(). + */ +static void +print_line (WINDOW * win, int row, int width) +{ +    int y, x; +    char *line; + +    line = get_line (); +    line += MIN (strlen (line), hscroll);	/* Scroll horizontally */ +    wmove (win, row, 0);	/* move cursor to correct line */ +    waddch (win, ' '); +    waddnstr (win, line, MIN (strlen (line), width - 2)); + +    getyx (win, y, x); +    /* Clear 'residue' of previous line */ +#if OLD_NCURSES +    { +        int i; +        for (i = 0; i < width - x; i++) +	    waddch (win, ' '); +    } +#else +    wclrtoeol(win); +#endif +} + +/* + * Return current line of text. Called by dialog_textbox() and print_line(). + * 'page' should point to start of current line before calling, and will be + * updated to point to start of next line. + */ +static char * +get_line (void) +{ +    int i = 0, fpos; +    static char line[MAX_LEN + 1]; + +    end_reached = 0; +    while (*page != '\n') { +	if (*page == '\0') { +	    /* Either end of file or end of buffer reached */ +	    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { +		endwin (); +		fprintf (stderr, "\nError moving file pointer in " +			 "get_line().\n"); +		exit (-1); +	    } +	    if (fpos < file_size) {	/* Not end of file yet */ +		/* We've reached end of buffer, but not end of file yet, +		   so read next part of file into buffer */ +		if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { +		    endwin (); +		    fprintf (stderr, "\nError reading file in get_line().\n"); +		    exit (-1); +		} +		buf[bytes_read] = '\0'; +		page = buf; +	    } else { +		if (!end_reached) +		    end_reached = 1; +		break; +	    } +	} else if (i < MAX_LEN) +	    line[i++] = *(page++); +	else { +	    /* Truncate lines longer than MAX_LEN characters */ +	    if (i == MAX_LEN) +		line[i++] = '\0'; +	    page++; +	} +    } +    if (i <= MAX_LEN) +	line[i] = '\0'; +    if (!end_reached) +	page++;			/* move pass '\n' */ + +    return line; +} + +/* + * Print current position + */ +static void +print_position (WINDOW * win, int height, int width) +{ +    int fpos, percent; + +    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { +	endwin (); +	fprintf (stderr, "\nError moving file pointer in print_position().\n"); +	exit (-1); +    } +    wattrset (win, position_indicator_attr); +    wbkgdset (win, position_indicator_attr & A_COLOR); +    percent = !file_size ? +	100 : ((fpos - bytes_read + page - buf) * 100) / file_size; +    wmove (win, height - 3, width - 9); +    wprintw (win, "(%3d%%)", percent); +} diff --git a/scripts/lxdialog/util.c b/scripts/lxdialog/util.c new file mode 100644 index 000000000000..e7bce9be69c3 --- /dev/null +++ b/scripts/lxdialog/util.c @@ -0,0 +1,359 @@ +/* + *  util.c + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + + +/* use colors by default? */ +bool use_colors = 1; + +const char *backtitle = NULL; + +const char *dialog_result; + +/*  + * Attribute values, default is for mono display + */ +chtype attributes[] = +{ +    A_NORMAL,			/* screen_attr */ +    A_NORMAL,			/* shadow_attr */ +    A_NORMAL,			/* dialog_attr */ +    A_BOLD,			/* title_attr */ +    A_NORMAL,			/* border_attr */ +    A_REVERSE,			/* button_active_attr */ +    A_DIM,			/* button_inactive_attr */ +    A_REVERSE,			/* button_key_active_attr */ +    A_BOLD,			/* button_key_inactive_attr */ +    A_REVERSE,			/* button_label_active_attr */ +    A_NORMAL,			/* button_label_inactive_attr */ +    A_NORMAL,			/* inputbox_attr */ +    A_NORMAL,			/* inputbox_border_attr */ +    A_NORMAL,			/* searchbox_attr */ +    A_BOLD,			/* searchbox_title_attr */ +    A_NORMAL,			/* searchbox_border_attr */ +    A_BOLD,			/* position_indicator_attr */ +    A_NORMAL,			/* menubox_attr */ +    A_NORMAL,			/* menubox_border_attr */ +    A_NORMAL,			/* item_attr */ +    A_REVERSE,			/* item_selected_attr */ +    A_BOLD,			/* tag_attr */ +    A_REVERSE,			/* tag_selected_attr */ +    A_BOLD,			/* tag_key_attr */ +    A_REVERSE,			/* tag_key_selected_attr */ +    A_BOLD,			/* check_attr */ +    A_REVERSE,			/* check_selected_attr */ +    A_BOLD,			/* uarrow_attr */ +    A_BOLD			/* darrow_attr */ +}; + + +#include "colors.h" + +/* + * Table of color values + */ +int color_table[][3] = +{ +    {SCREEN_FG, SCREEN_BG, SCREEN_HL}, +    {SHADOW_FG, SHADOW_BG, SHADOW_HL}, +    {DIALOG_FG, DIALOG_BG, DIALOG_HL}, +    {TITLE_FG, TITLE_BG, TITLE_HL}, +    {BORDER_FG, BORDER_BG, BORDER_HL}, +    {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL}, +    {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL}, +    {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL}, +    {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL}, +    {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL}, +    {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG, +     BUTTON_LABEL_INACTIVE_HL}, +    {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL}, +    {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL}, +    {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL}, +    {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL}, +    {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL}, +    {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL}, +    {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL}, +    {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL}, +    {ITEM_FG, ITEM_BG, ITEM_HL}, +    {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL}, +    {TAG_FG, TAG_BG, TAG_HL}, +    {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL}, +    {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL}, +    {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL}, +    {CHECK_FG, CHECK_BG, CHECK_HL}, +    {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL}, +    {UARROW_FG, UARROW_BG, UARROW_HL}, +    {DARROW_FG, DARROW_BG, DARROW_HL}, +};				/* color_table */ + +/* + * Set window to attribute 'attr' + */ +void +attr_clear (WINDOW * win, int height, int width, chtype attr) +{ +    int i, j; + +    wattrset (win, attr); +    for (i = 0; i < height; i++) { +	wmove (win, i, 0); +	for (j = 0; j < width; j++) +	    waddch (win, ' '); +    } +    touchwin (win); +} + +void dialog_clear (void) +{ +    attr_clear (stdscr, LINES, COLS, screen_attr); +    /* Display background title if it exists ... - SLH */ +    if (backtitle != NULL) { +        int i; + +        wattrset (stdscr, screen_attr); +        mvwaddstr (stdscr, 0, 1, (char *)backtitle); +        wmove (stdscr, 1, 1); +        for (i = 1; i < COLS - 1; i++) +            waddch (stdscr, ACS_HLINE); +    } +    wnoutrefresh (stdscr); +} + +/* + * Do some initialization for dialog + */ +void +init_dialog (void) +{ +    initscr ();			/* Init curses */ +    keypad (stdscr, TRUE); +    cbreak (); +    noecho (); + + +    if (use_colors)	/* Set up colors */ +	color_setup (); + + +    dialog_clear (); +} + +/* + * Setup for color display + */ +void +color_setup (void) +{ +    int i; + +    if (has_colors ()) {	/* Terminal supports color? */ +	start_color (); + +	/* Initialize color pairs */ +	for (i = 0; i < ATTRIBUTE_COUNT; i++) +	    init_pair (i + 1, color_table[i][0], color_table[i][1]); + +	/* Setup color attributes */ +	for (i = 0; i < ATTRIBUTE_COUNT; i++) +	    attributes[i] = C_ATTR (color_table[i][2], i + 1); +    } +} + +/* + * End using dialog functions. + */ +void +end_dialog (void) +{ +    endwin (); +} + + +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are replaced by spaces.  We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + */ +void +print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x) +{ +    int newl, cur_x, cur_y; +    int i, prompt_len, room, wlen; +    char tempstr[MAX_LEN + 1], *word, *sp, *sp2; + +    strcpy (tempstr, prompt); + +    prompt_len = strlen(tempstr); +	 +    /* +     * Remove newlines +     */ +    for(i=0; i<prompt_len; i++) { +	if(tempstr[i] == '\n') tempstr[i] = ' '; +    } + +    if (prompt_len <= width - x * 2) {	/* If prompt is short */ +	wmove (win, y, (width - prompt_len) / 2); +	waddstr (win, tempstr); +    } else { +	cur_x = x; +	cur_y = y; +	newl = 1; +	word = tempstr; +	while (word && *word) { +	    sp = index(word, ' '); +	    if (sp) +	        *sp++ = 0; + +	    /* Wrap to next line if either the word does not fit, +	       or it is the first word of a new sentence, and it is +	       short, and the next word does not fit. */ +	    room = width - cur_x; +	    wlen = strlen(word); +	    if (wlen > room || +	       (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room +		     && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) { +		cur_y++; +		cur_x = x; +	    } +	    wmove (win, cur_y, cur_x); +	    waddstr (win, word); +	    getyx (win, cur_y, cur_x); +	    cur_x++; +	    if (sp && *sp == ' ') { +	        cur_x++;	/* double space */ +		while (*++sp == ' '); +		newl = 1; +	    } else +	        newl = 0; +	    word = sp; +	} +    } +} + +/* + * Print a button + */ +void +print_button (WINDOW * win, const char *label, int y, int x, int selected) +{ +    int i, temp; + +    wmove (win, y, x); +    wattrset (win, selected ? button_active_attr : button_inactive_attr); +    waddstr (win, "<"); +    temp = strspn (label, " "); +    label += temp; +    wattrset (win, selected ? button_label_active_attr +	      : button_label_inactive_attr); +    for (i = 0; i < temp; i++) +	waddch (win, ' '); +    wattrset (win, selected ? button_key_active_attr +	      : button_key_inactive_attr); +    waddch (win, label[0]); +    wattrset (win, selected ? button_label_active_attr +	      : button_label_inactive_attr); +    waddstr (win, (char *)label + 1); +    wattrset (win, selected ? button_active_attr : button_inactive_attr); +    waddstr (win, ">"); +    wmove (win, y, x + temp + 1); +} + +/* + * Draw a rectangular box with line drawing characters + */ +void +draw_box (WINDOW * win, int y, int x, int height, int width, +	  chtype box, chtype border) +{ +    int i, j; + +    wattrset (win, 0); +    for (i = 0; i < height; i++) { +	wmove (win, y + i, x); +	for (j = 0; j < width; j++) +	    if (!i && !j) +		waddch (win, border | ACS_ULCORNER); +	    else if (i == height - 1 && !j) +		waddch (win, border | ACS_LLCORNER); +	    else if (!i && j == width - 1) +		waddch (win, box | ACS_URCORNER); +	    else if (i == height - 1 && j == width - 1) +		waddch (win, box | ACS_LRCORNER); +	    else if (!i) +		waddch (win, border | ACS_HLINE); +	    else if (i == height - 1) +		waddch (win, box | ACS_HLINE); +	    else if (!j) +		waddch (win, border | ACS_VLINE); +	    else if (j == width - 1) +		waddch (win, box | ACS_VLINE); +	    else +		waddch (win, box | ' '); +    } +} + +/* + * Draw shadows along the right and bottom edge to give a more 3D look + * to the boxes + */ +void +draw_shadow (WINDOW * win, int y, int x, int height, int width) +{ +    int i; + +    if (has_colors ()) {	/* Whether terminal supports color? */ +	wattrset (win, shadow_attr); +	wmove (win, y + height, x + 2); +	for (i = 0; i < width; i++) +	    waddch (win, winch (win) & A_CHARTEXT); +	for (i = y + 1; i < y + height + 1; i++) { +	    wmove (win, i, x + width); +	    waddch (win, winch (win) & A_CHARTEXT); +	    waddch (win, winch (win) & A_CHARTEXT); +	} +	wnoutrefresh (win); +    } +} + +/* + *  Return the position of the first alphabetic character in a string. + */ +int +first_alpha(const char *string, const char *exempt) +{ +	int i, in_paren=0, c; + +	for (i = 0; i < strlen(string); i++) { +		c = tolower(string[i]); + +		if (strchr("<[(", c)) ++in_paren; +		if (strchr(">])", c) && in_paren > 0) --in_paren; + +		if ((! in_paren) && isalpha(c) &&  +		     strchr(exempt, c) == 0) +			return i; +	} + +	return 0; +} diff --git a/scripts/lxdialog/yesno.c b/scripts/lxdialog/yesno.c new file mode 100644 index 000000000000..11fcc25f5159 --- /dev/null +++ b/scripts/lxdialog/yesno.c @@ -0,0 +1,118 @@ +/* + *  yesno.c -- implements the yes/no box + * + *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display termination buttons + */ +static void +print_buttons(WINDOW *dialog, int height, int width, int selected) +{ +    int x = width / 2 - 10; +    int y = height - 2; + +    print_button (dialog, " Yes ", y, x, selected == 0); +    print_button (dialog, "  No  ", y, x + 13, selected == 1); + +    wmove(dialog, y, x+1 + 13*selected ); +    wrefresh (dialog); +} + +/* + * Display a dialog box with two buttons - Yes and No + */ +int +dialog_yesno (const char *title, const char *prompt, int height, int width) +{ +    int i, x, y, key = 0, button = 0; +    WINDOW *dialog; + +    /* center dialog box on screen */ +    x = (COLS - width) / 2; +    y = (LINES - height) / 2; + +    draw_shadow (stdscr, y, x, height, width); + +    dialog = newwin (height, width, y, x); +    keypad (dialog, TRUE); + +    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); +    wattrset (dialog, border_attr); +    mvwaddch (dialog, height-3, 0, ACS_LTEE); +    for (i = 0; i < width - 2; i++) +	waddch (dialog, ACS_HLINE); +    wattrset (dialog, dialog_attr); +    waddch (dialog, ACS_RTEE); + +    if (title != NULL && strlen(title) >= width-2 ) { +	/* truncate long title -- mec */ +	char * title2 = malloc(width-2+1); +	memcpy( title2, title, width-2 ); +	title2[width-2] = '\0'; +	title = title2; +    } + +    if (title != NULL) { +	wattrset (dialog, title_attr); +	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); +	waddstr (dialog, (char *)title); +	waddch (dialog, ' '); +    } + +    wattrset (dialog, dialog_attr); +    print_autowrap (dialog, prompt, width - 2, 1, 3); + +    print_buttons(dialog, height, width, 0); + +    while (key != ESC) { +	key = wgetch (dialog); +	switch (key) { +	case 'Y': +	case 'y': +	    delwin (dialog); +	    return 0; +	case 'N': +	case 'n': +	    delwin (dialog); +	    return 1; + +	case TAB: +	case KEY_LEFT: +	case KEY_RIGHT: +	    button = ((key == KEY_LEFT ? --button : ++button) < 0) +			? 1 : (button > 1 ? 0 : button); + +	    print_buttons(dialog, height, width, button); +	    wrefresh (dialog); +	    break; +	case ' ': +	case '\n': +	    delwin (dialog); +	    return button; +	case ESC: +	    break; +	} +    } + +    delwin (dialog); +    return -1;			/* ESC pressed */ +} diff --git a/scripts/makelst b/scripts/makelst new file mode 100755 index 000000000000..34bd72391238 --- /dev/null +++ b/scripts/makelst @@ -0,0 +1,31 @@ +#!/bin/bash +# A script to dump mixed source code & assembly +# with correct relocations from System.map +# Requires the following lines in Rules.make. +# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)  +#            William Stearns <wstearns@pobox.com> +#%.lst: %.c +#	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $< +#	$(TOPDIR)/scripts/makelst $*.o $(TOPDIR)/System.map $(OBJDUMP) +# +#    Copyright (C) 2000 IBM Corporation +#    Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)  +# + +t1=`$3 --syms $1 | grep .text | grep " F " | head -n 1` +if [ -n "$t1" ]; then +  t2=`echo $t1 | gawk '{ print $6 }'` +  if [ ! -r $2 ]; then +    echo "No System.map" >&2 +    t7=0 +  else +    t3=`grep $t2 $2` +    t4=`echo $t3 | gawk '{ print $1 }'` +    t5=`echo $t1 | gawk '{ print $1 }'` +    t6=`echo $t4 - $t5 | tr a-f A-F` +    t7=`( echo  ibase=16 ; echo $t6 ) | bc` +  fi +else +  t7=0 +fi +$3 -r --source --adjust-vma=$t7 $1 diff --git a/scripts/makeman b/scripts/makeman new file mode 100755 index 000000000000..db3af647ee17 --- /dev/null +++ b/scripts/makeman @@ -0,0 +1,185 @@ +#!/usr/bin/perl + +use strict; + +## Copyright (C) Michael Still (mikal@stillhq.com) +## Released under the terms of the GNU GPL +## +## A script to make or install the manpages extracted by split-man +## +## Arguements: $1 -- the word "convert" or "install" +##             $2 -- the directory containing the SGML files for the manpages +##             $3 -- the filename which contained the sgmldoc output +##                     (I need this so I know which manpages to convert) + +my($LISTING, $GENERATED, $INPUT, $OUTPUT, $front, $mode, $filename, $tmpdir); + +if($ARGV[0] eq ""){ +  die "Usage: makeman [convert | install] <dir> <file>\n"; +} + +if( ! -d "$ARGV[1]" ){ +  die "Output directory \"$ARGV[1]\" does not exist\n"; +} + +if($ENV{"TMPDIR"} ne ""){ +  $tmpdir = $ENV{"TMPDIR"}; +} +else{ +  $tmpdir = "/tmp"; +} + +if($ARGV[0] eq "convert"){ +  open LISTING, "grep \"<refentrytitle>\" $ARGV[2] |"; +  while(<LISTING>){ +    s/<\/.*$//; +    s/^.*>//; +    s/\.sgml//; +    s/struct //; +    s/typedef //; + +    chomp; +    $filename = $_; +    print "Processing $filename\n"; + +    # Open the input file to extract the front matter, generate the man page, +    # and open it, and the rearrange everything until it is happy +    open INPUT, "< $ARGV[1]/$filename.sgml"; +    $front = ""; +    $mode = 0; + +    # The modes used here are: +    #                                                         mode = 0 +    # <!-- BEGINFRONTTAG --> +    # <!-- <bookinfo>                                         mode = 1 +    # <!--   <legalnotice>                                    mode = 2 +    # <!--     ...GPL or whatever... +    # <!--   </legalnotice>                                   mode = 4 +    # <!-- </bookinfo>                                        mode = 3 +    # <!-- ENDFRONTTAG --> +    # +    # ...doco... + +    # I know that some of the if statements in this while loop are in a funny +    # order, but that is deliberate... +    while(<INPUT>){ +      if($mode > 0){ +	s/<!-- //; +	s/ -->//; +	s/<docinfo>//i; +	s<\/docinfo>//i; +	s/^[ \t]*//i; +      } + +      if($mode == 2){ +	if(/<para>/i){ +	} +	elsif(/<\/para>/i){ +	  $front = "$front.\\\" \n"; +	} +	elsif(/<\/legalnotice>/i){ +	  $mode = 4; +	} +	elsif(/^[ \t]*$/){ +	} +	else{ +	  $front = "$front.\\\"     $_"; +	} +      } + +      if($mode == 1){ +	if(/<title>(.*)<\/title>/i){ +	  $front = "$front.\\\" This documentation was generated from the book titled \"$1\", which is part of the Linux kernel source.\n.\\\" \n"; +	} +	elsif(/<legalnotice>/i){ +	  $front = "$front.\\\" This documentation comes with the following legal notice:\n.\\\" \n"; +	  $mode = 2; +	} + +	elsif(/<author>/i){ +	  $front = "$front.\\\" Documentation by: "; +	} +	elsif(/<firstname>(.*)<\/firstname>/i){ +	  $front = "$front$1 "; +	} +	elsif(/<surname>(.*)<\/surname>/i){ +	  $front = "$front$1 "; +	} +	elsif(/<email>(.*)<\/email>/i){ +	  $front = "$front($1)"; +	} +	elsif(/\/author>/i){ +	  $front = "$front\n"; +	} + +	elsif(/<copyright>/i){ +	  $front = "$front.\\\" Documentation copyright: "; +	} +	elsif(/<holder>(.*)<\/holder>/i){ +	  $front = "$front$1 "; +	} +	elsif(/<year>(.*)<\/year>/i){ +	  $front = "$front$1 "; +	} +	elsif(/\/copyright>/i){ +	  $front = "$front\n"; +	} + +	elsif(/^[ \t]*$/ +	      || /<affiliation>/i +	      || /<\/affiliation>/i +	      || /<address>/i +	      || /<\/address>/i +	      || /<authorgroup>/i +	      || /<\/authorgroup>/i +	      || /<\/legalnotice>/i +              || /<date>/i +              || /<\/date>/i +              || /<edition>/i +              || /<\/edition>/i +	      || /<pubdate>/i +	      || /<\/pubdate>/i){ +	} +	else{ +	  print "Unknown tag in manpage conversion: $_"; +	  } +      } + +      if($mode == 0){ +	if(/<bookinfo>/i){ +	  $mode = 1; +	} +      } + +      if($mode == 4){ +	if(/<\/bookinfo>/i){ +	  $mode = 3; +	} +      } +    } +    close INPUT; + +    system("cd $ARGV[1]; docbook2man $filename.sgml; mv $filename.9 $tmpdir/$$.9\n"); +    open GENERATED, "< $tmpdir/$$.9"; +    open OUTPUT, "> $ARGV[1]/$filename.9"; + +    print OUTPUT "$front"; +    print OUTPUT ".\\\" For comments on the formatting of this manpage, please contact Michael Still <mikal\@stillhq.com>\n\n"; +    while(<GENERATED>){ +      print OUTPUT "$_"; +    } +    close OUTPUT; +    close GENERATED; + +    system("gzip -f $ARGV[1]/$filename.9\n"); +    unlink("$tmpdir/$$.9"); +  } +} +elsif($ARGV[0] eq "install"){ +  system("mkdir -p /usr/local/man/man9/; install $ARGV[1]/*.9.gz /usr/local/man/man9/"); +} +else{ +  die "Usage: makeman [convert | install] <dir> <file>\n"; +} + +print "Done\n"; diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h new file mode 100755 index 000000000000..8d118d181950 --- /dev/null +++ b/scripts/mkcompile_h @@ -0,0 +1,78 @@ +TARGET=$1 +ARCH=$2 +SMP=$3 +CC=$4 + +# If compile.h exists already and we don't own autoconf.h +# (i.e. we're not the same user who did make *config), don't +# modify compile.h +# So "sudo make install" won't change the "compiled by <user>" +# do "compiled by root" + +if [ -r $TARGET -a ! -O include/linux/autoconf.h ]; then +  echo "  SKIPPED $TARGET" +  exit 0 +fi + +# Do not expand names +set -f + +if [ -r .version ]; then +  VERSION=`cat .version` +else +  VERSION=0 +  echo 0 > .version +fi + + +UTS_VERSION="#$VERSION" +if [ -n "$SMP" ] ; then UTS_VERSION="$UTS_VERSION SMP"; fi +UTS_VERSION="$UTS_VERSION `LC_ALL=C LANG=C date`" + +# Truncate to maximum length + +UTS_LEN=64 +UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/" + +# Generate a temporary compile.h + +( echo /\* This file is auto generated, version $VERSION \*/ + +  echo \#define UTS_MACHINE \"$ARCH\" + +  echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\" + +  echo \#define LINUX_COMPILE_TIME \"`LC_ALL=C LANG=C date +%T`\" +  echo \#define LINUX_COMPILE_BY \"`whoami`\" +  echo \#define LINUX_COMPILE_HOST \"`hostname | $UTS_TRUNCATE`\" + +  if [ -x /bin/dnsdomainname ]; then +    echo \#define LINUX_COMPILE_DOMAIN \"`dnsdomainname | $UTS_TRUNCATE`\" +  elif [ -x /bin/domainname ]; then +    echo \#define LINUX_COMPILE_DOMAIN \"`domainname | $UTS_TRUNCATE`\" +  else +    echo \#define LINUX_COMPILE_DOMAIN +  fi + +  echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\" +) > .tmpcompile + +# Only replace the real compile.h if the new one is different, +# in order to preserve the timestamp and avoid unnecessary +# recompilations. +# We don't consider the file changed if only the date/time changed. +# A kernel config change will increase the generation number, thus +# causing compile.h to be updated (including date/time) due to the  +# changed comment in the +# first line. + +if [ -r $TARGET ] && \ +      grep -v 'UTS_VERSION\|LINUX_COMPILE_TIME' $TARGET > .tmpver.1 && \ +      grep -v 'UTS_VERSION\|LINUX_COMPILE_TIME' .tmpcompile > .tmpver.2 && \ +      cmp -s .tmpver.1 .tmpver.2; then +   rm -f .tmpcompile +else +   echo "  UPD     $TARGET" +   mv -f .tmpcompile $TARGET +fi +rm -f .tmpver.1 .tmpver.2 diff --git a/scripts/mkmakefile b/scripts/mkmakefile new file mode 100644 index 000000000000..c4d621b30d0d --- /dev/null +++ b/scripts/mkmakefile @@ -0,0 +1,31 @@ +#!/bin/sh +# Generates a small Makefile used in the root of the output +# directory, to allow make to be started from there. +# The Makefile also allow for more convinient build of external modules + +# Usage +# $1 - Kernel src directory +# $2 - Output directory +# $3 - version +# $4 - patchlevel + + +cat << EOF +# Automatically generated by $0: don't edit + +VERSION = $3 +PATCHLEVEL = $4 + +KERNELSRC    := $1 +KERNELOUTPUT := $2 + +MAKEFLAGS += --no-print-directory + +all: +	\$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) + +%:: +	\$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$@ + +EOF + diff --git a/scripts/mksysmap b/scripts/mksysmap new file mode 100644 index 000000000000..a6430e05972d --- /dev/null +++ b/scripts/mksysmap @@ -0,0 +1,44 @@ +#!/bin/sh -x +# Based on the vmlinux file create the System.map file +# System.map is used by module-init tools and some debugging +# tools to retreive the actual addresses of symbols in the kernel. +# +# Usage +# mksysmap vmlinux System.map + + +##### +# Generate System.map (actual filename passed as second argument) + +# $NM produces the following output: +# f0081e80 T alloc_vfsmnt + +#   The second row specify the type of the symbol: +#   A = Absolute +#   B = Uninitialised data (.bss) +#   C = Comon symbol +#   D = Initialised data +#   G = Initialised data for small objects +#   I = Indirect reference to another symbol +#   N = Debugging symbol +#   R = Read only +#   S = Uninitialised data for small objects +#   T = Text code symbol +#   U = Undefined symbol +#   V = Weak symbol +#   W = Weak symbol +#   Corresponding small letters are local symbols + +# For System.map filter away: +#   a - local absolute symbols +#   U - undefined global symbols +#   w - local weak symbols + +# readprofile starts reading symbols when _stext is found, and +# continue until it finds a symbol which is not either of 'T', 't', +# 'W' or 'w'. __crc_ are 'A' and placed in the middle +# so we just ignore them to let readprofile continue to work. +# (At least sparc64 has __crc_ in the middle). + +$NM -n $1 | grep -v '\( [aUw] \)\|\(__crc_\)\|\( \$[adt]\)' > $2 + diff --git a/scripts/mkuboot.sh b/scripts/mkuboot.sh new file mode 100755 index 000000000000..52a17ab97eb0 --- /dev/null +++ b/scripts/mkuboot.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# +# Build U-Boot image when `mkimage' tool is available. +# + +MKIMAGE=$(type -path mkimage) + +if [ -z "${MKIMAGE}" ]; then +	# Doesn't exist +	echo '"mkimage" command not found - U-Boot images will not be built' >&2 +	exit 0; +fi + +# Call "mkimage" to create U-Boot image +${MKIMAGE} "$@" diff --git a/scripts/mkversion b/scripts/mkversion new file mode 100644 index 000000000000..c12addc9c7ef --- /dev/null +++ b/scripts/mkversion @@ -0,0 +1,6 @@ +if [ ! -f .version ] +then +    echo 1 +else +    expr 0`cat .version` + 1 +fi diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile new file mode 100644 index 000000000000..11d69c35e5b4 --- /dev/null +++ b/scripts/mod/Makefile @@ -0,0 +1,16 @@ +hostprogs-y	:= modpost mk_elfconfig +always		:= $(hostprogs-y) empty.o + +modpost-objs	:= modpost.o file2alias.o sumversion.o + +# dependencies on generated files need to be listed explicitly + +$(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o: $(obj)/elfconfig.h + +quiet_cmd_elfconfig = MKELF   $@ +      cmd_elfconfig = $(obj)/mk_elfconfig $(ARCH) < $< > $@ + +$(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE +	$(call if_changed,elfconfig) + +targets += elfconfig.h diff --git a/scripts/mod/empty.c b/scripts/mod/empty.c new file mode 100644 index 000000000000..49839cc4ff26 --- /dev/null +++ b/scripts/mod/empty.c @@ -0,0 +1 @@ +/* empty file to figure out endianness / word size */ diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c new file mode 100644 index 000000000000..d54b52d3bb6f --- /dev/null +++ b/scripts/mod/file2alias.c @@ -0,0 +1,308 @@ +/* Simple code to turn various tables in an ELF file into alias definitions. + * This deals with kernel datastructures where they should be + * dealt with: in the kernel source. + * + * Copyright 2002-2003  Rusty Russell, IBM Corporation + *           2003       Kai Germaschewski + * + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#include "modpost.h" + +/* We use the ELF typedefs for kernel_ulong_t but bite the bullet and + * use either stdint.h or inttypes.h for the rest. */ +#if KERNEL_ELFCLASS == ELFCLASS32 +typedef Elf32_Addr	kernel_ulong_t; +#else +typedef Elf64_Addr	kernel_ulong_t; +#endif +#ifdef __sun__ +#include <inttypes.h> +#else +#include <stdint.h> +#endif + +typedef uint32_t	__u32; +typedef uint16_t	__u16; +typedef unsigned char	__u8; + +/* Big exception to the "don't include kernel headers into userspace, which + * even potentially has different endianness and word sizes, since  + * we handle those differences explicitly below */ +#include "../../include/linux/mod_devicetable.h" + +#define ADD(str, sep, cond, field)                              \ +do {                                                            \ +        strcat(str, sep);                                       \ +        if (cond)                                               \ +                sprintf(str + strlen(str),                      \ +                        sizeof(field) == 1 ? "%02X" :           \ +                        sizeof(field) == 2 ? "%04X" :           \ +                        sizeof(field) == 4 ? "%08X" : "",       \ +                        field);                                 \ +        else                                                    \ +                sprintf(str + strlen(str), "*");                \ +} while(0) + +/* Looks like "usb:vNpNdlNdhNdcNdscNdpNicNiscNipN" */ +static int do_usb_entry(const char *filename, +			struct usb_device_id *id, char *alias) +{ +	id->match_flags = TO_NATIVE(id->match_flags); +	id->idVendor = TO_NATIVE(id->idVendor); +	id->idProduct = TO_NATIVE(id->idProduct); +	id->bcdDevice_lo = TO_NATIVE(id->bcdDevice_lo); +	id->bcdDevice_hi = TO_NATIVE(id->bcdDevice_hi); + +	/* +	 * Some modules (visor) have empty slots as placeholder for +	 * run-time specification that results in catch-all alias +	 */ +	if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass)) +		return 1; + +	strcpy(alias, "usb:"); +	ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR, +	    id->idVendor); +	ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT, +	    id->idProduct); +	ADD(alias, "dl", id->match_flags&USB_DEVICE_ID_MATCH_DEV_LO, +	    id->bcdDevice_lo); +	ADD(alias, "dh", id->match_flags&USB_DEVICE_ID_MATCH_DEV_HI, +	    id->bcdDevice_hi); +	ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS, +	    id->bDeviceClass); +	ADD(alias, "dsc", +	    id->match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS, +	    id->bDeviceSubClass); +	ADD(alias, "dp", +	    id->match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL, +	    id->bDeviceProtocol); +	ADD(alias, "ic", +	    id->match_flags&USB_DEVICE_ID_MATCH_INT_CLASS, +	    id->bInterfaceClass); +	ADD(alias, "isc", +	    id->match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS, +	    id->bInterfaceSubClass); +	ADD(alias, "ip", +	    id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, +	    id->bInterfaceProtocol); +	return 1; +} + +/* Looks like: ieee1394:venNmoNspNverN */ +static int do_ieee1394_entry(const char *filename, +			     struct ieee1394_device_id *id, char *alias) +{ +	id->match_flags = TO_NATIVE(id->match_flags); +	id->vendor_id = TO_NATIVE(id->vendor_id); +	id->model_id = TO_NATIVE(id->model_id); +	id->specifier_id = TO_NATIVE(id->specifier_id); +	id->version = TO_NATIVE(id->version); + +	strcpy(alias, "ieee1394:"); +	ADD(alias, "ven", id->match_flags & IEEE1394_MATCH_VENDOR_ID, +	    id->vendor_id); +	ADD(alias, "mo", id->match_flags & IEEE1394_MATCH_MODEL_ID, +	    id->model_id); +	ADD(alias, "sp", id->match_flags & IEEE1394_MATCH_SPECIFIER_ID, +	    id->specifier_id); +	ADD(alias, "ver", id->match_flags & IEEE1394_MATCH_VERSION, +	    id->version); + +	return 1; +} + +/* Looks like: pci:vNdNsvNsdNbcNscNiN. */ +static int do_pci_entry(const char *filename, +			struct pci_device_id *id, char *alias) +{ +	/* Class field can be divided into these three. */ +	unsigned char baseclass, subclass, interface, +		baseclass_mask, subclass_mask, interface_mask; + +	id->vendor = TO_NATIVE(id->vendor); +	id->device = TO_NATIVE(id->device); +	id->subvendor = TO_NATIVE(id->subvendor); +	id->subdevice = TO_NATIVE(id->subdevice); +	id->class = TO_NATIVE(id->class); +	id->class_mask = TO_NATIVE(id->class_mask); + +	strcpy(alias, "pci:"); +	ADD(alias, "v", id->vendor != PCI_ANY_ID, id->vendor); +	ADD(alias, "d", id->device != PCI_ANY_ID, id->device); +	ADD(alias, "sv", id->subvendor != PCI_ANY_ID, id->subvendor); +	ADD(alias, "sd", id->subdevice != PCI_ANY_ID, id->subdevice); + +	baseclass = (id->class) >> 16; +	baseclass_mask = (id->class_mask) >> 16; +	subclass = (id->class) >> 8; +	subclass_mask = (id->class_mask) >> 8; +	interface = id->class; +	interface_mask = id->class_mask; + +	if ((baseclass_mask != 0 && baseclass_mask != 0xFF) +	    || (subclass_mask != 0 && subclass_mask != 0xFF) +	    || (interface_mask != 0 && interface_mask != 0xFF)) { +		fprintf(stderr, +			"*** Warning: Can't handle masks in %s:%04X\n", +			filename, id->class_mask); +		return 0; +	} + +	ADD(alias, "bc", baseclass_mask == 0xFF, baseclass); +	ADD(alias, "sc", subclass_mask == 0xFF, subclass); +	ADD(alias, "i", interface_mask == 0xFF, interface); +	return 1; +} + +/* looks like: "ccw:tNmNdtNdmN" */  +static int do_ccw_entry(const char *filename, +			struct ccw_device_id *id, char *alias) +{ +	id->match_flags = TO_NATIVE(id->match_flags); +	id->cu_type = TO_NATIVE(id->cu_type); +	id->cu_model = TO_NATIVE(id->cu_model); +	id->dev_type = TO_NATIVE(id->dev_type); +	id->dev_model = TO_NATIVE(id->dev_model); + +	strcpy(alias, "ccw:"); +	ADD(alias, "t", id->match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE, +	    id->cu_type); +	ADD(alias, "m", id->match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL, +	    id->cu_model); +	ADD(alias, "dt", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE, +	    id->dev_type); +	ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE, +	    id->dev_model); +	return 1; +} + +/* Looks like: "serio:tyNprNidNexN" */ +static int do_serio_entry(const char *filename, +			  struct serio_device_id *id, char *alias) +{ +	id->type = TO_NATIVE(id->type); +	id->proto = TO_NATIVE(id->proto); +	id->id = TO_NATIVE(id->id); +	id->extra = TO_NATIVE(id->extra); + +	strcpy(alias, "serio:"); +	ADD(alias, "ty", id->type != SERIO_ANY, id->type); +	ADD(alias, "pr", id->proto != SERIO_ANY, id->proto); +	ADD(alias, "id", id->id != SERIO_ANY, id->id); +	ADD(alias, "ex", id->extra != SERIO_ANY, id->extra); + +	return 1; +} + +/* looks like: "pnp:dD" */ +static int do_pnp_entry(const char *filename, +			struct pnp_device_id *id, char *alias) +{ +	sprintf(alias, "pnp:d%s", id->id); +	return 1; +} + +/* looks like: "pnp:cCdD..." */ +static int do_pnp_card_entry(const char *filename, +			struct pnp_card_device_id *id, char *alias) +{ +	int i; + +	sprintf(alias, "pnp:c%s", id->id); +	for (i = 0; i < PNP_MAX_DEVICES; i++) { +		if (! *id->devs[i].id) +			break; +		sprintf(alias + strlen(alias), "d%s", id->devs[i].id); +	} +	return 1; +} + +/* Ignore any prefix, eg. v850 prepends _ */ +static inline int sym_is(const char *symbol, const char *name) +{ +	const char *match; + +	match = strstr(symbol, name); +	if (!match) +		return 0; +	return match[strlen(symbol)] == '\0'; +} + +static void do_table(void *symval, unsigned long size, +		     unsigned long id_size, +		     void *function, +		     struct module *mod) +{ +	unsigned int i; +	char alias[500]; +	int (*do_entry)(const char *, void *entry, char *alias) = function; + +	if (size % id_size || size < id_size) { +		fprintf(stderr, "*** Warning: %s ids %lu bad size " +			"(each on %lu)\n", mod->name, size, id_size); +	} +	/* Leave last one: it's the terminator. */ +	size -= id_size; + +	for (i = 0; i < size; i += id_size) { +		if (do_entry(mod->name, symval+i, alias)) { +			/* Always end in a wildcard, for future extension */ +			if (alias[strlen(alias)-1] != '*') +				strcat(alias, "*"); +			buf_printf(&mod->dev_table_buf, +				   "MODULE_ALIAS(\"%s\");\n", alias); +		} +	} +} + +/* Create MODULE_ALIAS() statements. + * At this time, we cannot write the actual output C source yet, + * so we write into the mod->dev_table_buf buffer. */ +void handle_moddevtable(struct module *mod, struct elf_info *info, +			Elf_Sym *sym, const char *symname) +{ +	void *symval; + +	/* We're looking for a section relative symbol */ +	if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum) +		return; + +	symval = (void *)info->hdr +		+ info->sechdrs[sym->st_shndx].sh_offset +		+ sym->st_value; + +	if (sym_is(symname, "__mod_pci_device_table")) +		do_table(symval, sym->st_size, sizeof(struct pci_device_id), +			 do_pci_entry, mod); +	else if (sym_is(symname, "__mod_usb_device_table")) +		do_table(symval, sym->st_size, sizeof(struct usb_device_id), +			 do_usb_entry, mod); +	else if (sym_is(symname, "__mod_ieee1394_device_table")) +		do_table(symval, sym->st_size, sizeof(struct ieee1394_device_id), +			 do_ieee1394_entry, mod); +	else if (sym_is(symname, "__mod_ccw_device_table")) +		do_table(symval, sym->st_size, sizeof(struct ccw_device_id), +			 do_ccw_entry, mod); +	else if (sym_is(symname, "__mod_serio_device_table")) +		do_table(symval, sym->st_size, sizeof(struct serio_device_id), +			 do_serio_entry, mod); +	else if (sym_is(symname, "__mod_pnp_device_table")) +		do_table(symval, sym->st_size, sizeof(struct pnp_device_id), +			 do_pnp_entry, mod); +	else if (sym_is(symname, "__mod_pnp_card_device_table")) +		do_table(symval, sym->st_size, sizeof(struct pnp_card_device_id), +			 do_pnp_card_entry, mod); +} + +/* Now add out buffered information to the generated C source */ +void add_moddevtable(struct buffer *buf, struct module *mod) +{ +	buf_printf(buf, "\n"); +	buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos); +	free(mod->dev_table_buf.p); +} diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c new file mode 100644 index 000000000000..de2aabf89fb3 --- /dev/null +++ b/scripts/mod/mk_elfconfig.c @@ -0,0 +1,65 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <elf.h> + +int +main(int argc, char **argv) +{ +	unsigned char ei[EI_NIDENT];	 +	union { short s; char c[2]; } endian_test; + +	if (argc != 2) { +		fprintf(stderr, "Error: no arch\n"); +	} +	if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) { +		fprintf(stderr, "Error: input truncated\n"); +		return 1; +	} +	if (memcmp(ei, ELFMAG, SELFMAG) != 0) { +		fprintf(stderr, "Error: not ELF\n"); +		return 1; +	} +	switch (ei[EI_CLASS]) { +	case ELFCLASS32: +		printf("#define KERNEL_ELFCLASS ELFCLASS32\n"); +		break; +	case ELFCLASS64: +		printf("#define KERNEL_ELFCLASS ELFCLASS64\n"); +		break; +	default: +		abort(); +	} +	switch (ei[EI_DATA]) { +	case ELFDATA2LSB: +		printf("#define KERNEL_ELFDATA ELFDATA2LSB\n"); +		break; +	case ELFDATA2MSB: +		printf("#define KERNEL_ELFDATA ELFDATA2MSB\n"); +		break; +	default: +		abort(); +	} + +	if (sizeof(unsigned long) == 4) { +		printf("#define HOST_ELFCLASS ELFCLASS32\n"); +	} else if (sizeof(unsigned long) == 8) { +		printf("#define HOST_ELFCLASS ELFCLASS64\n"); +	} + +	endian_test.s = 0x0102; +	if (memcmp(endian_test.c, "\x01\x02", 2) == 0) +		printf("#define HOST_ELFDATA ELFDATA2MSB\n"); +	else if (memcmp(endian_test.c, "\x02\x01", 2) == 0) +		printf("#define HOST_ELFDATA ELFDATA2LSB\n"); +	else +		abort(); + +	if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)) +		printf("#define MODULE_SYMBOL_PREFIX \"_\"\n"); +	else  +		printf("#define MODULE_SYMBOL_PREFIX \"\"\n"); + +	return 0; +} + diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c new file mode 100644 index 000000000000..9b9f94c915d2 --- /dev/null +++ b/scripts/mod/modpost.c @@ -0,0 +1,797 @@ +/* Postprocess module symbol versions + * + * Copyright 2003       Kai Germaschewski + * Copyright 2002-2004  Rusty Russell, IBM Corporation + * + * Based in part on module-init-tools/depmod.c,file2alias + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * Usage: modpost vmlinux module1.o module2.o ... + */ + +#include <ctype.h> +#include "modpost.h" + +/* Are we using CONFIG_MODVERSIONS? */ +int modversions = 0; +/* Warn about undefined symbols? (do so if we have vmlinux) */ +int have_vmlinux = 0; +/* Is CONFIG_MODULE_SRCVERSION_ALL set? */ +static int all_versions = 0; + +void +fatal(const char *fmt, ...) +{ +	va_list arglist; + +	fprintf(stderr, "FATAL: "); + +	va_start(arglist, fmt); +	vfprintf(stderr, fmt, arglist); +	va_end(arglist); + +	exit(1); +} + +void +warn(const char *fmt, ...) +{ +	va_list arglist; + +	fprintf(stderr, "WARNING: "); + +	va_start(arglist, fmt); +	vfprintf(stderr, fmt, arglist); +	va_end(arglist); +} + +void *do_nofail(void *ptr, const char *expr) +{ +	if (!ptr) { +		fatal("modpost: Memory allocation failure: %s.\n", expr); +	} +	return ptr; +} + +/* A list of all modules we processed */ + +static struct module *modules; + +struct module * +find_module(char *modname) +{ +	struct module *mod; + +	for (mod = modules; mod; mod = mod->next) +		if (strcmp(mod->name, modname) == 0) +			break; +	return mod; +} + +struct module * +new_module(char *modname) +{ +	struct module *mod; +	char *p, *s; +	 +	mod = NOFAIL(malloc(sizeof(*mod))); +	memset(mod, 0, sizeof(*mod)); +	p = NOFAIL(strdup(modname)); + +	/* strip trailing .o */ +	if ((s = strrchr(p, '.')) != NULL) +		if (strcmp(s, ".o") == 0) +			*s = '\0'; + +	/* add to list */ +	mod->name = p; +	mod->next = modules; +	modules = mod; + +	return mod; +} + +/* A hash of all exported symbols, + * struct symbol is also used for lists of unresolved symbols */ + +#define SYMBOL_HASH_SIZE 1024 + +struct symbol { +	struct symbol *next; +	struct module *module; +	unsigned int crc; +	int crc_valid; +	unsigned int weak:1; +	char name[0]; +}; + +static struct symbol *symbolhash[SYMBOL_HASH_SIZE]; + +/* This is based on the hash agorithm from gdbm, via tdb */ +static inline unsigned int tdb_hash(const char *name) +{ +	unsigned value;	/* Used to compute the hash value.  */ +	unsigned   i;	/* Used to cycle through random values. */ + +	/* Set the initial value from the key size. */ +	for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++) +		value = (value + (((unsigned char *)name)[i] << (i*5 % 24))); + +	return (1103515243 * value + 12345); +} + +/* Allocate a new symbols for use in the hash of exported symbols or + * the list of unresolved symbols per module */ + +struct symbol * +alloc_symbol(const char *name, unsigned int weak, struct symbol *next) +{ +	struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); + +	memset(s, 0, sizeof(*s)); +	strcpy(s->name, name); +	s->weak = weak; +	s->next = next; +	return s; +} + +/* For the hash of exported symbols */ + +void +new_symbol(const char *name, struct module *module, unsigned int *crc) +{ +	unsigned int hash; +	struct symbol *new; + +	hash = tdb_hash(name) % SYMBOL_HASH_SIZE; +	new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); +	new->module = module; +	if (crc) { +		new->crc = *crc; +		new->crc_valid = 1; +	} +} + +struct symbol * +find_symbol(const char *name) +{ +	struct symbol *s; + +	/* For our purposes, .foo matches foo.  PPC64 needs this. */ +	if (name[0] == '.') +		name++; + +	for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s=s->next) { +		if (strcmp(s->name, name) == 0) +			return s; +	} +	return NULL; +} + +/* Add an exported symbol - it may have already been added without a + * CRC, in this case just update the CRC */ +void +add_exported_symbol(const char *name, struct module *module, unsigned int *crc) +{ +	struct symbol *s = find_symbol(name); + +	if (!s) { +		new_symbol(name, module, crc); +		return; +	} +	if (crc) { +		s->crc = *crc; +		s->crc_valid = 1; +	} +} + +void * +grab_file(const char *filename, unsigned long *size) +{ +	struct stat st; +	void *map; +	int fd; + +	fd = open(filename, O_RDONLY); +	if (fd < 0 || fstat(fd, &st) != 0) +		return NULL; + +	*size = st.st_size; +	map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); +	close(fd); + +	if (map == MAP_FAILED) +		return NULL; +	return map; +} + +/* +   Return a copy of the next line in a mmap'ed file. +   spaces in the beginning of the line is trimmed away. +   Return a pointer to a static buffer. +*/ +char* +get_next_line(unsigned long *pos, void *file, unsigned long size) +{ +	static char line[4096]; +	int skip = 1; +	size_t len = 0; +	signed char *p = (signed char *)file + *pos; +	char *s = line; + +	for (; *pos < size ; (*pos)++) +	{ +		if (skip && isspace(*p)) { +			p++; +			continue; +		} +		skip = 0; +		if (*p != '\n' && (*pos < size)) { +			len++; +			*s++ = *p++; +			if (len > 4095) +				break; /* Too long, stop */ +		} else { +			/* End of string */ +			*s = '\0'; +			return line; +		} +	} +	/* End of buffer */ +	return NULL; +} + +void +release_file(void *file, unsigned long size) +{ +	munmap(file, size); +} + +void +parse_elf(struct elf_info *info, const char *filename) +{ +	unsigned int i; +	Elf_Ehdr *hdr = info->hdr; +	Elf_Shdr *sechdrs; +	Elf_Sym  *sym; + +	hdr = grab_file(filename, &info->size); +	if (!hdr) { +		perror(filename); +		abort(); +	} +	info->hdr = hdr; +	if (info->size < sizeof(*hdr)) +		goto truncated; + +	/* Fix endianness in ELF header */ +	hdr->e_shoff    = TO_NATIVE(hdr->e_shoff); +	hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); +	hdr->e_shnum    = TO_NATIVE(hdr->e_shnum); +	hdr->e_machine  = TO_NATIVE(hdr->e_machine); +	sechdrs = (void *)hdr + hdr->e_shoff; +	info->sechdrs = sechdrs; + +	/* Fix endianness in section headers */ +	for (i = 0; i < hdr->e_shnum; i++) { +		sechdrs[i].sh_type   = TO_NATIVE(sechdrs[i].sh_type); +		sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); +		sechdrs[i].sh_size   = TO_NATIVE(sechdrs[i].sh_size); +		sechdrs[i].sh_link   = TO_NATIVE(sechdrs[i].sh_link); +		sechdrs[i].sh_name   = TO_NATIVE(sechdrs[i].sh_name); +	} +	/* Find symbol table. */ +	for (i = 1; i < hdr->e_shnum; i++) { +		const char *secstrings +			= (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + +		if (sechdrs[i].sh_offset > info->size) +			goto truncated; +		if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) { +			info->modinfo = (void *)hdr + sechdrs[i].sh_offset; +			info->modinfo_len = sechdrs[i].sh_size; +		} +		if (sechdrs[i].sh_type != SHT_SYMTAB) +			continue; + +		info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; +		info->symtab_stop  = (void *)hdr + sechdrs[i].sh_offset  +			                         + sechdrs[i].sh_size; +		info->strtab       = (void *)hdr +  +			             sechdrs[sechdrs[i].sh_link].sh_offset; +	} +	if (!info->symtab_start) { +		fprintf(stderr, "modpost: %s no symtab?\n", filename); +		abort(); +	} +	/* Fix endianness in symbols */ +	for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { +		sym->st_shndx = TO_NATIVE(sym->st_shndx); +		sym->st_name  = TO_NATIVE(sym->st_name); +		sym->st_value = TO_NATIVE(sym->st_value); +		sym->st_size  = TO_NATIVE(sym->st_size); +	} +	return; + + truncated: +	fprintf(stderr, "modpost: %s is truncated.\n", filename); +	abort(); +} + +void +parse_elf_finish(struct elf_info *info) +{ +	release_file(info->hdr, info->size); +} + +#define CRC_PFX     MODULE_SYMBOL_PREFIX "__crc_" +#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_" + +void +handle_modversions(struct module *mod, struct elf_info *info, +		   Elf_Sym *sym, const char *symname) +{ +	unsigned int crc; + +	switch (sym->st_shndx) { +	case SHN_COMMON: +		fprintf(stderr, "*** Warning: \"%s\" [%s] is COMMON symbol\n", +			symname, mod->name); +		break; +	case SHN_ABS: +		/* CRC'd symbol */ +		if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { +			crc = (unsigned int) sym->st_value; +			add_exported_symbol(symname + strlen(CRC_PFX), +					    mod, &crc); +		} +		break; +	case SHN_UNDEF: +		/* undefined symbol */ +		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL && +		    ELF_ST_BIND(sym->st_info) != STB_WEAK) +			break; +		/* ignore global offset table */ +		if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0) +			break; +		/* ignore __this_module, it will be resolved shortly */ +		if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0) +			break; +#ifdef STT_REGISTER +		if (info->hdr->e_machine == EM_SPARC || +		    info->hdr->e_machine == EM_SPARCV9) { +			/* Ignore register directives. */ +			if (ELF_ST_TYPE(sym->st_info) == STT_REGISTER) +				break; +		} +#endif +		 +		if (memcmp(symname, MODULE_SYMBOL_PREFIX, +			   strlen(MODULE_SYMBOL_PREFIX)) == 0) +			mod->unres = alloc_symbol(symname + +						  strlen(MODULE_SYMBOL_PREFIX), +						  ELF_ST_BIND(sym->st_info) == STB_WEAK, +						  mod->unres); +		break; +	default: +		/* All exported symbols */ +		if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { +			add_exported_symbol(symname + strlen(KSYMTAB_PFX), +					    mod, NULL); +		} +		if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) +			mod->has_init = 1; +		if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0) +			mod->has_cleanup = 1; +		break; +	} +} + +int +is_vmlinux(const char *modname) +{ +	const char *myname; + +	if ((myname = strrchr(modname, '/'))) +		myname++; +	else +		myname = modname; + +	return strcmp(myname, "vmlinux") == 0; +} + +/* Parse tag=value strings from .modinfo section */ +static char *next_string(char *string, unsigned long *secsize) +{ +	/* Skip non-zero chars */ +	while (string[0]) { +		string++; +		if ((*secsize)-- <= 1) +			return NULL; +	} + +	/* Skip any zero padding. */ +	while (!string[0]) { +		string++; +		if ((*secsize)-- <= 1) +			return NULL; +	} +	return string; +} + +static char *get_modinfo(void *modinfo, unsigned long modinfo_len, +			 const char *tag) +{ +	char *p; +	unsigned int taglen = strlen(tag); +	unsigned long size = modinfo_len; + +	for (p = modinfo; p; p = next_string(p, &size)) { +		if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') +			return p + taglen + 1; +	} +	return NULL; +} + +void +read_symbols(char *modname) +{ +	const char *symname; +	char *version; +	struct module *mod; +	struct elf_info info = { }; +	Elf_Sym *sym; + +	parse_elf(&info, modname); + +	mod = new_module(modname); + +	/* When there's no vmlinux, don't print warnings about +	 * unresolved symbols (since there'll be too many ;) */ +	if (is_vmlinux(modname)) { +		unsigned int fake_crc = 0; +		have_vmlinux = 1; +		add_exported_symbol("struct_module", mod, &fake_crc); +		mod->skip = 1; +	} + +	for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { +		symname = info.strtab + sym->st_name; + +		handle_modversions(mod, &info, sym, symname); +		handle_moddevtable(mod, &info, sym, symname); +	} + +	version = get_modinfo(info.modinfo, info.modinfo_len, "version"); +	if (version) +		maybe_frob_rcs_version(modname, version, info.modinfo, +				       version - (char *)info.hdr); +	if (version || (all_versions && !is_vmlinux(modname))) +		get_src_version(modname, mod->srcversion, +				sizeof(mod->srcversion)-1); + +	parse_elf_finish(&info); + +	/* Our trick to get versioning for struct_module - it's +	 * never passed as an argument to an exported function, so +	 * the automatic versioning doesn't pick it up, but it's really +	 * important anyhow */ +	if (modversions) +		mod->unres = alloc_symbol("struct_module", 0, mod->unres); +} + +#define SZ 500 + +/* We first write the generated file into memory using the + * following helper, then compare to the file on disk and + * only update the later if anything changed */ + +void __attribute__((format(printf, 2, 3))) +buf_printf(struct buffer *buf, const char *fmt, ...) +{ +	char tmp[SZ]; +	int len; +	va_list ap; +	 +	va_start(ap, fmt); +	len = vsnprintf(tmp, SZ, fmt, ap); +	if (buf->size - buf->pos < len + 1) { +		buf->size += 128; +		buf->p = realloc(buf->p, buf->size); +	} +	strncpy(buf->p + buf->pos, tmp, len + 1); +	buf->pos += len; +	va_end(ap); +} + +void +buf_write(struct buffer *buf, const char *s, int len) +{ +	if (buf->size - buf->pos < len) { +		buf->size += len; +		buf->p = realloc(buf->p, buf->size); +	} +	strncpy(buf->p + buf->pos, s, len); +	buf->pos += len; +} + +/* Header for the generated file */ + +void +add_header(struct buffer *b, struct module *mod) +{ +	buf_printf(b, "#include <linux/module.h>\n"); +	buf_printf(b, "#include <linux/vermagic.h>\n"); +	buf_printf(b, "#include <linux/compiler.h>\n"); +	buf_printf(b, "\n"); +	buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n"); +	buf_printf(b, "\n"); +	buf_printf(b, "#undef unix\n"); /* We have a module called "unix" */ +	buf_printf(b, "struct module __this_module\n"); +	buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); +	buf_printf(b, " .name = __stringify(KBUILD_MODNAME),\n"); +	if (mod->has_init) +		buf_printf(b, " .init = init_module,\n"); +	if (mod->has_cleanup) +		buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n" +			      " .exit = cleanup_module,\n" +			      "#endif\n"); +	buf_printf(b, "};\n"); +} + +/* Record CRCs for unresolved symbols */ + +void +add_versions(struct buffer *b, struct module *mod) +{ +	struct symbol *s, *exp; + +	for (s = mod->unres; s; s = s->next) { +		exp = find_symbol(s->name); +		if (!exp || exp->module == mod) { +			if (have_vmlinux && !s->weak) +				fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " +				"undefined!\n",	s->name, mod->name); +			continue; +		} +		s->module = exp->module; +		s->crc_valid = exp->crc_valid; +		s->crc = exp->crc; +	} + +	if (!modversions) +		return; + +	buf_printf(b, "\n"); +	buf_printf(b, "static const struct modversion_info ____versions[]\n"); +	buf_printf(b, "__attribute_used__\n"); +	buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n"); + +	for (s = mod->unres; s; s = s->next) { +		if (!s->module) { +			continue; +		} +		if (!s->crc_valid) { +			fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " +				"has no CRC!\n", +				s->name, mod->name); +			continue; +		} +		buf_printf(b, "\t{ %#8x, \"%s\" },\n", s->crc, s->name); +	} + +	buf_printf(b, "};\n"); +} + +void +add_depends(struct buffer *b, struct module *mod, struct module *modules) +{ +	struct symbol *s; +	struct module *m; +	int first = 1; + +	for (m = modules; m; m = m->next) { +		m->seen = is_vmlinux(m->name); +	} + +	buf_printf(b, "\n"); +	buf_printf(b, "static const char __module_depends[]\n"); +	buf_printf(b, "__attribute_used__\n"); +	buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n"); +	buf_printf(b, "\"depends="); +	for (s = mod->unres; s; s = s->next) { +		if (!s->module) +			continue; + +		if (s->module->seen) +			continue; + +		s->module->seen = 1; +		buf_printf(b, "%s%s", first ? "" : ",", +			   strrchr(s->module->name, '/') + 1); +		first = 0; +	} +	buf_printf(b, "\";\n"); +} + +void +add_srcversion(struct buffer *b, struct module *mod) +{ +	if (mod->srcversion[0]) { +		buf_printf(b, "\n"); +		buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n", +			   mod->srcversion); +	} +} + +void +write_if_changed(struct buffer *b, const char *fname) +{ +	char *tmp; +	FILE *file; +	struct stat st; + +	file = fopen(fname, "r"); +	if (!file) +		goto write; + +	if (fstat(fileno(file), &st) < 0) +		goto close_write; + +	if (st.st_size != b->pos) +		goto close_write; + +	tmp = NOFAIL(malloc(b->pos)); +	if (fread(tmp, 1, b->pos, file) != b->pos) +		goto free_write; + +	if (memcmp(tmp, b->p, b->pos) != 0) +		goto free_write; + +	free(tmp); +	fclose(file); +	return; + + free_write: +	free(tmp); + close_write: +	fclose(file); + write: +	file = fopen(fname, "w"); +	if (!file) { +		perror(fname); +		exit(1); +	} +	if (fwrite(b->p, 1, b->pos, file) != b->pos) { +		perror(fname); +		exit(1); +	} +	fclose(file); +} + +void +read_dump(const char *fname) +{ +	unsigned long size, pos = 0; +	void *file = grab_file(fname, &size); +	char *line; + +        if (!file) +		/* No symbol versions, silently ignore */ +		return; + +	while ((line = get_next_line(&pos, file, size))) { +		char *symname, *modname, *d; +		unsigned int crc; +		struct module *mod; + +		if (!(symname = strchr(line, '\t'))) +			goto fail; +		*symname++ = '\0'; +		if (!(modname = strchr(symname, '\t'))) +			goto fail; +		*modname++ = '\0'; +		if (strchr(modname, '\t')) +			goto fail; +		crc = strtoul(line, &d, 16); +		if (*symname == '\0' || *modname == '\0' || *d != '\0') +			goto fail; + +		if (!(mod = find_module(modname))) { +			if (is_vmlinux(modname)) { +				have_vmlinux = 1; +			} +			mod = new_module(NOFAIL(strdup(modname))); +			mod->skip = 1; +		} +		add_exported_symbol(symname, mod, &crc); +	} +	return; +fail: +	fatal("parse error in symbol dump file\n"); +} + +void +write_dump(const char *fname) +{ +	struct buffer buf = { }; +	struct symbol *symbol; +	int n; + +	for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { +		symbol = symbolhash[n]; +		while (symbol) { +			symbol = symbol->next; +		} +	} + +	for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { +		symbol = symbolhash[n]; +		while (symbol) { +			buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc, +				symbol->name, symbol->module->name); +			symbol = symbol->next; +		} +	} +	write_if_changed(&buf, fname); +} + +int +main(int argc, char **argv) +{ +	struct module *mod; +	struct buffer buf = { }; +	char fname[SZ]; +	char *dump_read = NULL, *dump_write = NULL; +	int opt; + +	while ((opt = getopt(argc, argv, "i:mo:a")) != -1) { +		switch(opt) { +			case 'i': +				dump_read = optarg; +				break; +			case 'm': +				modversions = 1; +				break; +			case 'o': +				dump_write = optarg; +				break; +			case 'a': +				all_versions = 1; +				break; +			default: +				exit(1); +		} +	} + +	if (dump_read) +		read_dump(dump_read); + +	while (optind < argc) { +		read_symbols(argv[optind++]); +	} + +	for (mod = modules; mod; mod = mod->next) { +		if (mod->skip) +			continue; + +		buf.pos = 0; + +		add_header(&buf, mod); +		add_versions(&buf, mod); +		add_depends(&buf, mod, modules); +		add_moddevtable(&buf, mod); +		add_srcversion(&buf, mod); + +		sprintf(fname, "%s.mod.c", mod->name); +		write_if_changed(&buf, fname); +	} + +	if (dump_write) +		write_dump(dump_write); + +	return 0; +} + diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h new file mode 100644 index 000000000000..7334d839145d --- /dev/null +++ b/scripts/mod/modpost.h @@ -0,0 +1,107 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <unistd.h> +#include <elf.h> + +#include "elfconfig.h" + +#if KERNEL_ELFCLASS == ELFCLASS32 + +#define Elf_Ehdr    Elf32_Ehdr  +#define Elf_Shdr    Elf32_Shdr  +#define Elf_Sym     Elf32_Sym +#define ELF_ST_BIND ELF32_ST_BIND +#define ELF_ST_TYPE ELF32_ST_TYPE + +#else + +#define Elf_Ehdr    Elf64_Ehdr  +#define Elf_Shdr    Elf64_Shdr  +#define Elf_Sym     Elf64_Sym +#define ELF_ST_BIND ELF64_ST_BIND +#define ELF_ST_TYPE ELF64_ST_TYPE + +#endif + +#if KERNEL_ELFDATA != HOST_ELFDATA + +static inline void __endian(const void *src, void *dest, unsigned int size) +{ +	unsigned int i; +	for (i = 0; i < size; i++) +		((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; +} + + + +#define TO_NATIVE(x)						\ +({								\ +	typeof(x) __x;						\ +	__endian(&(x), &(__x), sizeof(__x));			\ +	__x;							\ +}) + +#else /* endianness matches */ + +#define TO_NATIVE(x) (x) + +#endif + +#define NOFAIL(ptr)   do_nofail((ptr), #ptr) +void *do_nofail(void *ptr, const char *expr); + +struct buffer { +	char *p; +	int pos; +	int size; +}; + +void __attribute__((format(printf, 2, 3))) +buf_printf(struct buffer *buf, const char *fmt, ...); + +void +buf_write(struct buffer *buf, const char *s, int len); + +struct module { +	struct module *next; +	const char *name; +	struct symbol *unres; +	int seen; +	int skip; +	int has_init; +	int has_cleanup; +	struct buffer dev_table_buf; +	char	     srcversion[25]; +}; + +struct elf_info { +	unsigned long size; +	Elf_Ehdr     *hdr; +	Elf_Shdr     *sechdrs; +	Elf_Sym      *symtab_start; +	Elf_Sym      *symtab_stop; +	const char   *strtab; +	char	     *modinfo; +	unsigned int modinfo_len; +}; + +void handle_moddevtable(struct module *mod, struct elf_info *info, +			Elf_Sym *sym, const char *symname); + +void add_moddevtable(struct buffer *buf, struct module *mod); + +void maybe_frob_rcs_version(const char *modfilename, +			    char *version, +			    void *modinfo, +			    unsigned long modinfo_offset); +void get_src_version(const char *modname, char sum[], unsigned sumlen); + +void *grab_file(const char *filename, unsigned long *size); +char* get_next_line(unsigned long *pos, void *file, unsigned long size); +void release_file(void *file, unsigned long size); diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c new file mode 100644 index 000000000000..1112347245c0 --- /dev/null +++ b/scripts/mod/sumversion.c @@ -0,0 +1,498 @@ +#include <netinet/in.h> +#ifdef __sun__ +#include <inttypes.h> +#else +#include <stdint.h> +#endif +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include "modpost.h" + +/* + * Stolen form Cryptographic API. + * + * MD4 Message Digest Algorithm (RFC1320). + * + * Implementation derived from Andrew Tridgell and Steve French's + * CIFS MD4 implementation, and the cryptoapi implementation + * originally based on the public domain implementation written + * by Colin Plumb in 1993. + * + * Copyright (c) Andrew Tridgell 1997-1998. + * Modified by Steve French (sfrench@us.ibm.com) 2002 + * Copyright (c) Cryptoapi developers. + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#define MD4_DIGEST_SIZE		16 +#define MD4_HMAC_BLOCK_SIZE	64 +#define MD4_BLOCK_WORDS		16 +#define MD4_HASH_WORDS		4 + +struct md4_ctx { +	uint32_t hash[MD4_HASH_WORDS]; +	uint32_t block[MD4_BLOCK_WORDS]; +	uint64_t byte_count; +}; + +static inline uint32_t lshift(uint32_t x, unsigned int s) +{ +	x &= 0xFFFFFFFF; +	return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); +} + +static inline uint32_t F(uint32_t x, uint32_t y, uint32_t z) +{ +	return (x & y) | ((~x) & z); +} + +static inline uint32_t G(uint32_t x, uint32_t y, uint32_t z) +{ +	return (x & y) | (x & z) | (y & z); +} + +static inline uint32_t H(uint32_t x, uint32_t y, uint32_t z) +{ +	return x ^ y ^ z; +} + +#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s)) +#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (uint32_t)0x5A827999,s)) +#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (uint32_t)0x6ED9EBA1,s)) + +/* XXX: this stuff can be optimized */ +static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words) +{ +	while (words--) { +		*buf = ntohl(*buf); +		buf++; +	} +} + +static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words) +{ +	while (words--) { +		*buf = htonl(*buf); +		buf++; +	} +} + +static void md4_transform(uint32_t *hash, uint32_t const *in) +{ +	uint32_t a, b, c, d; + +	a = hash[0]; +	b = hash[1]; +	c = hash[2]; +	d = hash[3]; + +	ROUND1(a, b, c, d, in[0], 3); +	ROUND1(d, a, b, c, in[1], 7); +	ROUND1(c, d, a, b, in[2], 11); +	ROUND1(b, c, d, a, in[3], 19); +	ROUND1(a, b, c, d, in[4], 3); +	ROUND1(d, a, b, c, in[5], 7); +	ROUND1(c, d, a, b, in[6], 11); +	ROUND1(b, c, d, a, in[7], 19); +	ROUND1(a, b, c, d, in[8], 3); +	ROUND1(d, a, b, c, in[9], 7); +	ROUND1(c, d, a, b, in[10], 11); +	ROUND1(b, c, d, a, in[11], 19); +	ROUND1(a, b, c, d, in[12], 3); +	ROUND1(d, a, b, c, in[13], 7); +	ROUND1(c, d, a, b, in[14], 11); +	ROUND1(b, c, d, a, in[15], 19); + +	ROUND2(a, b, c, d,in[ 0], 3); +	ROUND2(d, a, b, c, in[4], 5); +	ROUND2(c, d, a, b, in[8], 9); +	ROUND2(b, c, d, a, in[12], 13); +	ROUND2(a, b, c, d, in[1], 3); +	ROUND2(d, a, b, c, in[5], 5); +	ROUND2(c, d, a, b, in[9], 9); +	ROUND2(b, c, d, a, in[13], 13); +	ROUND2(a, b, c, d, in[2], 3); +	ROUND2(d, a, b, c, in[6], 5); +	ROUND2(c, d, a, b, in[10], 9); +	ROUND2(b, c, d, a, in[14], 13); +	ROUND2(a, b, c, d, in[3], 3); +	ROUND2(d, a, b, c, in[7], 5); +	ROUND2(c, d, a, b, in[11], 9); +	ROUND2(b, c, d, a, in[15], 13); + +	ROUND3(a, b, c, d,in[ 0], 3); +	ROUND3(d, a, b, c, in[8], 9); +	ROUND3(c, d, a, b, in[4], 11); +	ROUND3(b, c, d, a, in[12], 15); +	ROUND3(a, b, c, d, in[2], 3); +	ROUND3(d, a, b, c, in[10], 9); +	ROUND3(c, d, a, b, in[6], 11); +	ROUND3(b, c, d, a, in[14], 15); +	ROUND3(a, b, c, d, in[1], 3); +	ROUND3(d, a, b, c, in[9], 9); +	ROUND3(c, d, a, b, in[5], 11); +	ROUND3(b, c, d, a, in[13], 15); +	ROUND3(a, b, c, d, in[3], 3); +	ROUND3(d, a, b, c, in[11], 9); +	ROUND3(c, d, a, b, in[7], 11); +	ROUND3(b, c, d, a, in[15], 15); + +	hash[0] += a; +	hash[1] += b; +	hash[2] += c; +	hash[3] += d; +} + +static inline void md4_transform_helper(struct md4_ctx *ctx) +{ +	le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(uint32_t)); +	md4_transform(ctx->hash, ctx->block); +} + +static void md4_init(struct md4_ctx *mctx) +{ +	mctx->hash[0] = 0x67452301; +	mctx->hash[1] = 0xefcdab89; +	mctx->hash[2] = 0x98badcfe; +	mctx->hash[3] = 0x10325476; +	mctx->byte_count = 0; +} + +static void md4_update(struct md4_ctx *mctx, +		       const unsigned char *data, unsigned int len) +{ +	const uint32_t avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); + +	mctx->byte_count += len; + +	if (avail > len) { +		memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), +		       data, len); +		return; +	} + +	memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), +	       data, avail); + +	md4_transform_helper(mctx); +	data += avail; +	len -= avail; + +	while (len >= sizeof(mctx->block)) { +		memcpy(mctx->block, data, sizeof(mctx->block)); +		md4_transform_helper(mctx); +		data += sizeof(mctx->block); +		len -= sizeof(mctx->block); +	} + +	memcpy(mctx->block, data, len); +} + +static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len) +{ +	const unsigned int offset = mctx->byte_count & 0x3f; +	char *p = (char *)mctx->block + offset; +	int padding = 56 - (offset + 1); + +	*p++ = 0x80; +	if (padding < 0) { +		memset(p, 0x00, padding + sizeof (uint64_t)); +		md4_transform_helper(mctx); +		p = (char *)mctx->block; +		padding = 56; +	} + +	memset(p, 0, padding); +	mctx->block[14] = mctx->byte_count << 3; +	mctx->block[15] = mctx->byte_count >> 29; +	le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - +	                  sizeof(uint64_t)) / sizeof(uint32_t)); +	md4_transform(mctx->hash, mctx->block); +	cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t)); + +	snprintf(out, len, "%08X%08X%08X%08X", +		 mctx->hash[0], mctx->hash[1], mctx->hash[2], mctx->hash[3]); +} + +static inline void add_char(unsigned char c, struct md4_ctx *md) +{ +	md4_update(md, &c, 1); +} + +static int parse_string(const char *file, unsigned long len, +			struct md4_ctx *md) +{ +	unsigned long i; + +	add_char(file[0], md); +	for (i = 1; i < len; i++) { +		add_char(file[i], md); +		if (file[i] == '"' && file[i-1] != '\\') +			break; +	} +	return i; +} + +static int parse_comment(const char *file, unsigned long len) +{ +	unsigned long i; + +	for (i = 2; i < len; i++) { +		if (file[i-1] == '*' && file[i] == '/') +			break; +	} +	return i; +} + +/* FIXME: Handle .s files differently (eg. # starts comments) --RR */ +static int parse_file(const signed char *fname, struct md4_ctx *md) +{ +	signed char *file; +	unsigned long i, len; + +	file = grab_file(fname, &len); +	if (!file) +		return 0; + +	for (i = 0; i < len; i++) { +		/* Collapse and ignore \ and CR. */ +		if (file[i] == '\\' && (i+1 < len) && file[i+1] == '\n') { +			i++; +			continue; +		} + +		/* Ignore whitespace */ +		if (isspace(file[i])) +			continue; + +		/* Handle strings as whole units */ +		if (file[i] == '"') { +			i += parse_string(file+i, len - i, md); +			continue; +		} + +		/* Comments: ignore */ +		if (file[i] == '/' && file[i+1] == '*') { +			i += parse_comment(file+i, len - i); +			continue; +		} + +		add_char(file[i], md); +	} +	release_file(file, len); +	return 1; +} + +/* We have dir/file.o.  Open dir/.file.o.cmd, look for deps_ line to + * figure out source file. */ +static int parse_source_files(const char *objfile, struct md4_ctx *md) +{ +	char *cmd, *file, *line, *dir; +	const char *base; +	unsigned long flen, pos = 0; +	int dirlen, ret = 0, check_files = 0; + +	cmd = NOFAIL(malloc(strlen(objfile) + sizeof("..cmd"))); + +	base = strrchr(objfile, '/'); +	if (base) { +		base++; +		dirlen = base - objfile; +		sprintf(cmd, "%.*s.%s.cmd", dirlen, objfile, base); +	} else { +		dirlen = 0; +		sprintf(cmd, ".%s.cmd", objfile); +	} +	dir = NOFAIL(malloc(dirlen + 1)); +	strncpy(dir, objfile, dirlen); +	dir[dirlen] = '\0'; + +	file = grab_file(cmd, &flen); +	if (!file) { +		fprintf(stderr, "Warning: could not find %s for %s\n", +			cmd, objfile); +		goto out; +	} + +	/* There will be a line like so: +		deps_drivers/net/dummy.o := \ +		  drivers/net/dummy.c \ +		    $(wildcard include/config/net/fastroute.h) \ +		  include/linux/config.h \ +		    $(wildcard include/config/h.h) \ +		  include/linux/module.h \ + +	   Sum all files in the same dir or subdirs. +	*/ +	while ((line = get_next_line(&pos, file, flen)) != NULL) { +		signed char* p = line; +		if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) { +			check_files = 1; +			continue; +		} +		if (!check_files) +			continue; + +		/* Continue until line does not end with '\' */ +		if ( *(p + strlen(p)-1) != '\\') +			break; +		/* Terminate line at first space, to get rid of final ' \' */ +		while (*p) { +                       if (isspace(*p)) { +				*p = '\0'; +				break; +			} +			p++; +		} + +		/* Check if this file is in same dir as objfile */ +		if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) { +			if (!parse_file(line, md)) { +				fprintf(stderr, +					"Warning: could not open %s: %s\n", +					line, strerror(errno)); +				goto out_file; +			} + +		} + +	} + +	/* Everyone parsed OK */ +	ret = 1; +out_file: +	release_file(file, flen); +out: +	free(dir); +	free(cmd); +	return ret; +} + +/* Calc and record src checksum. */ +void get_src_version(const char *modname, char sum[], unsigned sumlen) +{ +	void *file; +	unsigned long len; +	struct md4_ctx md; +	char *sources, *end, *fname; +	const char *basename; +	char filelist[strlen(getenv("MODVERDIR")) + strlen("/") + +		      strlen(modname) - strlen(".o") + strlen(".mod") + 1 ]; + +	/* Source files for module are in .tmp_versions/modname.mod, +	   after the first line. */ +	if (strrchr(modname, '/')) +		basename = strrchr(modname, '/') + 1; +	else +		basename = modname; +	sprintf(filelist, "%s/%.*s.mod", getenv("MODVERDIR"), +		(int) strlen(basename) - 2, basename); + +	file = grab_file(filelist, &len); +	if (!file) { +		fprintf(stderr, "Warning: could not find versions for %s\n", +			filelist); +		return; +	} + +	sources = strchr(file, '\n'); +	if (!sources) { +		fprintf(stderr, "Warning: malformed versions file for %s\n", +			modname); +		goto release; +	} + +	sources++; +	end = strchr(sources, '\n'); +	if (!end) { +		fprintf(stderr, "Warning: bad ending versions file for %s\n", +			modname); +		goto release; +	} +	*end = '\0'; + +	md4_init(&md); +	while ((fname = strsep(&sources, " ")) != NULL) { +		if (!*fname) +			continue; +		if (!parse_source_files(fname, &md)) +			goto release; +	} + +	md4_final_ascii(&md, sum, sumlen); +release: +	release_file(file, len); +} + +static void write_version(const char *filename, const char *sum, +			  unsigned long offset) +{ +	int fd; + +	fd = open(filename, O_RDWR); +	if (fd < 0) { +		fprintf(stderr, "Warning: changing sum in %s failed: %s\n", +			filename, strerror(errno)); +		return; +	} + +	if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { +		fprintf(stderr, "Warning: changing sum in %s:%lu failed: %s\n", +			filename, offset, strerror(errno)); +		goto out; +	} + +	if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) { +		fprintf(stderr, "Warning: writing sum in %s failed: %s\n", +			filename, strerror(errno)); +		goto out; +	} +out: +	close(fd); +} + +static int strip_rcs_crap(signed char *version) +{ +	unsigned int len, full_len; + +	if (strncmp(version, "$Revision", strlen("$Revision")) != 0) +		return 0; + +	/* Space for version string follows. */ +	full_len = strlen(version) + strlen(version + strlen(version) + 1) + 2; + +	/* Move string to start with version number: prefix will be +	 * $Revision$ or $Revision: */ +	len = strlen("$Revision"); +	if (version[len] == ':' || version[len] == '$') +		len++; +	while (isspace(version[len])) +		len++; +	memmove(version, version+len, full_len-len); +	full_len -= len; + +	/* Preserve up to next whitespace. */ +	len = 0; +	while (version[len] && !isspace(version[len])) +		len++; +	memmove(version + len, version + strlen(version), +		full_len - strlen(version)); +	return 1; +} + +/* Clean up RCS-style version numbers. */ +void maybe_frob_rcs_version(const char *modfilename, +			    char *version, +			    void *modinfo, +			    unsigned long version_offset) +{ +	if (strip_rcs_crap(version)) +		write_version(modfilename, version, version_offset); +} diff --git a/scripts/namespace.pl b/scripts/namespace.pl new file mode 100644 index 000000000000..88e30e82f1ca --- /dev/null +++ b/scripts/namespace.pl @@ -0,0 +1,454 @@ +#!/usr/bin/perl -w +# +#	namespace.pl.  Mon Aug 30 2004 +# +#	Perform a name space analysis on the linux kernel. +# +#	Copyright Keith Owens <kaos@ocs.com.au>.  GPL. +# +#	Invoke by changing directory to the top of the kernel object +#	tree then namespace.pl, no parameters. +# +#	Tuned for 2.1.x kernels with the new module handling, it will +#	work with 2.0 kernels as well. +# +#	Last change 2.6.9-rc1, adding support for separate source and object +#	trees. +# +#	The source must be compiled/assembled first, the object files +#	are the primary input to this script.  Incomplete or missing +#	objects will result in a flawed analysis.  Compile both vmlinux +#	and modules. +# +#	Even with complete objects, treat the result of the analysis +#	with caution.  Some external references are only used by +#	certain architectures, others with certain combinations of +#	configuration parameters.  Ideally the source should include +#	something like +# +#	#ifndef CONFIG_... +#	static +#	#endif +#	symbol_definition; +# +#	so the symbols are defined as static unless a particular +#	CONFIG_... requires it to be external. +# +#	A symbol that is suffixed with '(export only)' has these properties +# +#	* It is global. +#	* It is marked EXPORT_SYMBOL or EXPORT_SYMBOL_GPL, either in the same +#	  source file or a different source file. +#	* Given the current .config, nothing uses the symbol. +# +#	The symbol is a candidate for conversion to static, plus removal of the +#	export.  But be careful that a different .config might use the symbol. +# +# +#	Name space analysis and cleanup is an iterative process.  You cannot +#	expect to find all the problems in a single pass. +# +#	* Identify possibly unnecessary global declarations, verify that they +#	  really are unnecessary and change them to static. +#	* Compile and fix up gcc warnings about static, removing dead symbols +#	  as necessary. +#	* make clean and rebuild with different configs (especially +#	  CONFIG_MODULES=n) to see which symbols are being defined when the +#	  config does not require them.  These symbols bloat the kernel object +#	  for no good reason, which is frustrating for embedded systems. +#	* Wrap config sensitive symbols in #ifdef CONFIG_foo, as long as the +#	  code does not get too ugly. +#	* Repeat the name space analysis until you can live with with the +#	  result. +# + +require 5;	# at least perl 5 +use strict; +use File::Find; + +my $nm = "/usr/bin/nm -p"; +my $objdump = "/usr/bin/objdump -s -j .comment"; +my $srctree = ""; +my $objtree = ""; +$srctree = "$ENV{'srctree'}/" if (exists($ENV{'srctree'})); +$objtree = "$ENV{'objtree'}/" if (exists($ENV{'objtree'})); + +if ($#ARGV != -1) { +	print STDERR "usage: $0 takes no parameters\n"; +	die("giving up\n"); +} + +my %nmdata = ();	# nm data for each object +my %def = ();		# all definitions for each name +my %ksymtab = ();	# names that appear in __ksymtab_ +my %ref = ();		# $ref{$name} exists if there is a true external reference to $name +my %export = ();	# $export{$name} exists if there is an EXPORT_... of $name + +&find(\&linux_objects, '.');	# find the objects and do_nm on them +&list_multiply_defined(); +&resolve_external_references(); +&list_extra_externals(); + +exit(0); + +sub linux_objects +{ +	# Select objects, ignoring objects which are only created by +	# merging other objects.  Also ignore all of modules, scripts +	# and compressed.  Most conglomerate objects are handled by do_nm, +	# this list only contains the special cases.  These include objects +	# that are linked from just one other object and objects for which +	# there is really no permanent source file. +	my $basename = $_; +	$_ = $File::Find::name; +	s:^\./::; +	if (/.*\.o$/ && +		! ( +		m:/built-in.o$: +		|| m:arch/i386/kernel/vsyscall-syms.o$: +		|| m:arch/ia64/ia32/ia32.o$: +		|| m:arch/ia64/kernel/gate-syms.o$: +		|| m:arch/ia64/lib/__divdi3.o$: +		|| m:arch/ia64/lib/__divsi3.o$: +		|| m:arch/ia64/lib/__moddi3.o$: +		|| m:arch/ia64/lib/__modsi3.o$: +		|| m:arch/ia64/lib/__udivdi3.o$: +		|| m:arch/ia64/lib/__udivsi3.o$: +		|| m:arch/ia64/lib/__umoddi3.o$: +		|| m:arch/ia64/lib/__umodsi3.o$: +		|| m:arch/ia64/scripts/check_gas_for_hint.o$: +		|| m:arch/ia64/sn/kernel/xp.o$: +		|| m:boot/bbootsect.o$: +		|| m:boot/bsetup.o$: +		|| m:/bootsect.o$: +		|| m:/boot/setup.o$: +		|| m:/compressed/: +		|| m:drivers/cdrom/driver.o$: +		|| m:drivers/char/drm/tdfx_drv.o$: +		|| m:drivers/ide/ide-detect.o$: +		|| m:drivers/ide/pci/idedriver-pci.o$: +		|| m:drivers/media/media.o$: +		|| m:drivers/scsi/sd_mod.o$: +		|| m:drivers/video/video.o$: +		|| m:fs/devpts/devpts.o$: +		|| m:fs/exportfs/exportfs.o$: +		|| m:fs/hugetlbfs/hugetlbfs.o$: +		|| m:fs/msdos/msdos.o$: +		|| m:fs/nls/nls.o$: +		|| m:fs/ramfs/ramfs.o$: +		|| m:fs/romfs/romfs.o$: +		|| m:fs/vfat/vfat.o$: +		|| m:init/mounts.o$: +		|| m:^modules/: +		|| m:net/netlink/netlink.o$: +		|| m:net/sched/sched.o$: +		|| m:/piggy.o$: +		|| m:^scripts/: +		|| m:sound/.*/snd-: +		|| m:^.*/\.tmp_: +		|| m:^\.tmp_: +		|| m:/vmlinux-obj.o$: +		) +	) { +		do_nm($basename, $_); +	} +	$_ = $basename;		# File::Find expects $_ untouched (undocumented) +} + +sub do_nm +{ +	my ($basename, $fullname) = @_; +	my ($source, $type, $name); +	if (! -e $basename) { +		printf STDERR "$basename does not exist\n"; +		return; +	} +	if ($fullname !~ /\.o$/) { +		printf STDERR "$fullname is not an object file\n"; +		return; +	} +	($source = $fullname) =~ s/\.o$//; +	if (-e "$objtree$source.c" || -e "$objtree$source.S") { +		$source = "$objtree$source"; +	} else { +		$source = "$srctree$source"; +	} +	if (! -e "$source.c" && ! -e "$source.S") { +		# No obvious source, exclude the object if it is conglomerate +		if (! open(OBJDUMPDATA, "$objdump $basename|")) { +			printf STDERR "$objdump $fullname failed $!\n"; +			return; +		} +		my $comment; +		while (<OBJDUMPDATA>) { +			chomp(); +			if (/^In archive/) { +				# Archives are always conglomerate +				$comment = "GCC:GCC:"; +				last; +			} +			next if (! /^[ 0-9a-f]{5,} /); +			$comment .= substr($_, 43); +		} +		close(OBJDUMPDATA); +		if (!defined($comment) || $comment !~ /GCC\:.*GCC\:/m) { +			printf STDERR "No source file found for $fullname\n"; +		} +		return; +	} +	if (! open(NMDATA, "$nm $basename|")) { +		printf STDERR "$nm $fullname failed $!\n"; +		return; +	} +	my @nmdata; +	while (<NMDATA>) { +		chop; +		($type, $name) = (split(/ +/, $_, 3))[1..2]; +		# Expected types +		# A absolute symbol +		# B weak external reference to data that has been resolved +		# C global variable, uninitialised +		# D global variable, initialised +		# G global variable, initialised, small data section +		# R global array, initialised +		# S global variable, uninitialised, small bss +		# T global label/procedure +		# U external reference +		# W weak external reference to text that has been resolved +		# a assembler equate +		# b static variable, uninitialised +		# d static variable, initialised +		# g static variable, initialised, small data section +		# r static array, initialised +		# s static variable, uninitialised, small bss +		# t static label/procedures +		# w weak external reference to text that has not been resolved +		# ? undefined type, used a lot by modules +		if ($type !~ /^[ABCDGRSTUWabdgrstw?]$/) { +			printf STDERR "nm output for $fullname contains unknown type '$_'\n"; +		} +		elsif ($name =~ /\./) { +			# name with '.' is local static +		} +		else { +			$type = 'R' if ($type eq '?');	# binutils replaced ? with R at one point +			# binutils keeps changing the type for exported symbols, force it to R +			$type = 'R' if ($name =~ /^__ksymtab/ || $name =~ /^__kstrtab/); +			$name =~ s/_R[a-f0-9]{8}$//;	# module versions adds this +			if ($type =~ /[ABCDGRSTW]/ && +				$name ne 'init_module' && +				$name ne 'cleanup_module' && +				$name ne 'Using_Versions' && +				$name !~ /^Version_[0-9]+$/ && +				$name !~ /^__parm_/ && +				$name !~ /^__kstrtab/ && +				$name !~ /^__ksymtab/ && +				$name !~ /^__kcrctab_/ && +				$name !~ /^__exitcall_/ && +				$name !~ /^__initcall_/ && +				$name !~ /^__kdb_initcall_/ && +				$name !~ /^__kdb_exitcall_/ && +				$name !~ /^__module_/ && +				$name !~ /^__mod_/ && +				$name !~ /^__crc_/ && +				$name ne '__this_module' && +				$name ne 'kernel_version') { +				if (!exists($def{$name})) { +					$def{$name} = []; +				} +				push(@{$def{$name}}, $fullname); +			} +			push(@nmdata, "$type $name"); +			if ($name =~ /^__ksymtab_/) { +				$name = substr($name, 10); +				if (!exists($ksymtab{$name})) { +					$ksymtab{$name} = []; +				} +				push(@{$ksymtab{$name}}, $fullname); +			} +		} +	} +	close(NMDATA); +	if ($#nmdata < 0) { +		if ( +			$fullname ne "lib/brlock.o" +			&& $fullname ne "lib/dec_and_lock.o" +			&& $fullname ne "fs/xfs/xfs_macros.o" +			&& $fullname ne "drivers/ide/ide-probe-mini.o" +			&& $fullname ne "usr/initramfs_data.o" +			&& $fullname ne "drivers/acpi/executer/exdump.o" +			&& $fullname ne "drivers/acpi/resources/rsdump.o" +			&& $fullname ne "drivers/acpi/namespace/nsdumpdv.o" +			&& $fullname ne "drivers/acpi/namespace/nsdump.o" +			&& $fullname ne "arch/ia64/sn/kernel/sn2/io.o" +			&& $fullname ne "arch/ia64/kernel/gate-data.o" +			&& $fullname ne "drivers/ieee1394/oui.o" +			&& $fullname ne "security/capability.o" +			&& $fullname ne "sound/core/wrappers.o" +			&& $fullname ne "fs/ntfs/sysctl.o" +			&& $fullname ne "fs/jfs/jfs_debug.o" +		) { +			printf "No nm data for $fullname\n"; +		} +		return; +	} +	$nmdata{$fullname} = \@nmdata; +} + +sub drop_def +{ +	my ($object, $name) = @_; +	my $nmdata = $nmdata{$object}; +	my ($i, $j); +	for ($i = 0; $i <= $#{$nmdata}; ++$i) { +		if ($name eq (split(' ', $nmdata->[$i], 2))[1]) { +			splice(@{$nmdata{$object}}, $i, 1); +			my $def = $def{$name}; +			for ($j = 0; $j < $#{$def{$name}}; ++$j) { +				if ($def{$name}[$j] eq $object) { +					splice(@{$def{$name}}, $j, 1); +				} +			} +			last; +		} +	} +} + +sub list_multiply_defined +{ +	my ($name, $module); +	foreach $name (keys(%def)) { +		if ($#{$def{$name}} > 0) { +			# Special case for cond_syscall +			if ($#{$def{$name}} == 1 && $name =~ /^sys_/ && +			    ($def{$name}[0] eq "kernel/sys.o" || +			     $def{$name}[1] eq "kernel/sys.o")) { +				&drop_def("kernel/sys.o", $name); +				next; +			} +			# Special case for i386 entry code +			if ($#{$def{$name}} == 1 && $name =~ /^__kernel_/ && +			    $def{$name}[0] eq "arch/i386/kernel/vsyscall-int80.o" && +			    $def{$name}[1] eq "arch/i386/kernel/vsyscall-sysenter.o") { +				&drop_def("arch/i386/kernel/vsyscall-sysenter.o", $name); +				next; +			} +			printf "$name is multiply defined in :-\n"; +			foreach $module (@{$def{$name}}) { +				printf "\t$module\n"; +			} +		} +	} +} + +sub resolve_external_references +{ +	my ($object, $type, $name, $i, $j, $kstrtab, $ksymtab, $export); +	printf "\n"; +	foreach $object (keys(%nmdata)) { +		my $nmdata = $nmdata{$object}; +		for ($i = 0; $i <= $#{$nmdata}; ++$i) { +			($type, $name) = split(' ', $nmdata->[$i], 2); +			if ($type eq "U" || $type eq "w") { +				if (exists($def{$name}) || exists($ksymtab{$name})) { +					# add the owning object to the nmdata +					$nmdata->[$i] = "$type $name $object"; +					# only count as a reference if it is not EXPORT_... +					$kstrtab = "R __kstrtab_$name"; +					$ksymtab = "R __ksymtab_$name"; +					$export = 0; +					for ($j = 0; $j <= $#{$nmdata}; ++$j) { +						if ($nmdata->[$j] eq $kstrtab || +						    $nmdata->[$j] eq $ksymtab) { +							$export = 1; +							last; +						} +					} +					if ($export) { +						$export{$name} = ""; +					} +					else { +						$ref{$name} = "" +					} +				} +				elsif (    $name ne "mod_use_count_" +					&& $name ne "__initramfs_end" +					&& $name ne "__initramfs_start" +					&& $name ne "_einittext" +					&& $name ne "_sinittext" +					&& $name ne "kallsyms_names" +					&& $name ne "kallsyms_num_syms" +					&& $name ne "kallsyms_addresses" +					&& $name ne "__this_module" +					&& $name ne "_etext" +					&& $name ne "_edata" +					&& $name ne "_end" +					&& $name ne "__bss_start" +					&& $name ne "_text" +					&& $name ne "_stext" +					&& $name ne "__gp" +					&& $name ne "ia64_unw_start" +					&& $name ne "ia64_unw_end" +					&& $name ne "__init_begin" +					&& $name ne "__init_end" +					&& $name ne "__bss_stop" +					&& $name ne "__nosave_begin" +					&& $name ne "__nosave_end" +					&& $name ne "pg0" +					&& $name ne "__module_text_address" +					&& $name !~ /^__sched_text_/ +					&& $name !~ /^__start_/ +					&& $name !~ /^__end_/ +					&& $name !~ /^__stop_/ +					&& $name !~ /^__scheduling_functions_.*_here/ +					&& $name !~ /^__.*initcall_/ +					&& $name !~ /^__.*per_cpu_start/ +					&& $name !~ /^__.*per_cpu_end/ +					&& $name !~ /^__alt_instructions/ +					&& $name !~ /^__setup_/ +					&& $name !~ /^jiffies/ +					&& $name !~ /^__mod_timer/ +					&& $name !~ /^__mod_page_state/ +					&& $name !~ /^init_module/ +					&& $name !~ /^cleanup_module/ +				) { +					printf "Cannot resolve "; +					printf "weak " if ($type eq "w"); +					printf "reference to $name from $object\n"; +				} +			} +		} +	} +} + +sub list_extra_externals +{ +	my %noref = (); +	my ($name, @module, $module, $export); +	foreach $name (keys(%def)) { +		if (! exists($ref{$name})) { +			@module = @{$def{$name}}; +			foreach $module (@module) { +				if (! exists($noref{$module})) { +					$noref{$module} = []; +				} +				push(@{$noref{$module}}, $name); +			} +		} +	} +	if (%noref) { +		printf "\nExternally defined symbols with no external references\n"; +		foreach $module (sort(keys(%noref))) { +			printf "  $module\n"; +			foreach (sort(@{$noref{$module}})) { +				if (exists($export{$_})) { +					$export = " (export only)"; +				} +				else { +					$export = ""; +				} +				printf "    $_$export\n"; +			} +		} +	} +} diff --git a/scripts/package/Makefile b/scripts/package/Makefile new file mode 100644 index 000000000000..3b1f2eff2584 --- /dev/null +++ b/scripts/package/Makefile @@ -0,0 +1,89 @@ +# Makefile for the different targets used to generate full packages of a kernel +# It uses the generic clean infrastructure of kbuild + +# Ignore the following files/directories during tar operation +TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS + + +# RPM target +# --------------------------------------------------------------------------- +# The rpm target generates two rpm files: +# /usr/src/packages/SRPMS/kernel-2.6.7rc2-1.src.rpm +# /usr/src/packages/RPMS/i386/kernel-2.6.7rc2-1.<arch>.rpm +# The src.rpm files includes all source for the kernel being built +# The <arch>.rpm includes kernel configuration, modules etc. +# +# Process to create the rpm files +# a) clean the kernel +# b) Generate .spec file +# c) Build a tar ball, using symlink to make kernel version +#    first entry in the path +# d) and pack the result to a tar.gz file +# e) generate the rpm files, based on kernel.spec +# - Use /. to avoid tar packing just the symlink + +# Do we have rpmbuild, otherwise fall back to the older rpm +RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \ +	           else echo rpm; fi) + +# Remove hyphens since they have special meaning in RPM filenames +KERNELPATH := kernel-$(subst -,,$(KERNELRELEASE)) +MKSPEC     := $(srctree)/scripts/package/mkspec +PREV       := set -e; cd ..; + +# rpm-pkg +.PHONY: rpm-pkg rpm + +$(objtree)/kernel.spec: $(MKSPEC) $(srctree)/Makefile +	$(CONFIG_SHELL) $(MKSPEC) > $@ + +rpm-pkg rpm: $(objtree)/kernel.spec +	$(MAKE) clean +	$(PREV) ln -sf $(srctree) $(KERNELPATH) +	$(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. +	$(PREV) rm $(KERNELPATH) + +	set -e; \ +	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version +	set -e; \ +	mv -f $(objtree)/.tmp_version $(objtree)/.version + +	$(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz +	rm ../$(KERNELPATH).tar.gz + +clean-files := $(objtree)/kernel.spec + +# binrpm-pkg +.PHONY: binrpm-pkg +$(objtree)/binkernel.spec: $(MKSPEC) $(srctree)/Makefile +	$(CONFIG_SHELL) $(MKSPEC) prebuilt > $@ +	 +binrpm-pkg: $(objtree)/binkernel.spec +	$(MAKE) +	set -e; \ +	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version +	set -e; \ +	mv -f $(objtree)/.tmp_version $(objtree)/.version + +	$(RPM) --define "_builddir $(srctree)" --target $(UTS_MACHINE) -bb $< + +clean-files += $(objtree)/binkernel.spec + +# Deb target +# --------------------------------------------------------------------------- +# +.PHONY: deb-pkg +deb-pkg: +	$(MAKE) +	$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb + +clean-dirs += $(objtree)/debian/ + + +# Help text displayed when executing 'make help' +# --------------------------------------------------------------------------- +help: +	@echo  '  rpm-pkg         - Build the kernel as an RPM package' +	@echo  '  binrpm-pkg      - Build an rpm package containing the compiled kernel & modules' +	@echo  '  deb-pkg         - Build the kernel as an deb package' + diff --git a/scripts/package/builddeb b/scripts/package/builddeb new file mode 100644 index 000000000000..c279b6310f02 --- /dev/null +++ b/scripts/package/builddeb @@ -0,0 +1,79 @@ +#!/bin/sh +# +# builddeb 1.2 +# Copyright 2003 Wichert Akkerman <wichert@wiggy.net> +# +# Simple script to generate a deb package for a Linux kernel. All the +# complexity of what to do with a kernel after it is installer or removed +# is left to other scripts and packages: they can install scripts in the +# /etc/kernel/{pre,post}{inst,rm}.d/ directories that will be called on +# package install and removal. + +set -e + +# Some variables and settings used throughout the script +version=$KERNELRELEASE +tmpdir="$objtree/debian/tmp" + +# Setup the directory structure +rm -rf "$tmpdir" +mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot" + +# Build and install the kernel +cp System.map "$tmpdir/boot/System.map-$version" +cp .config "$tmpdir/boot/config-$version" +cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version" + +if grep -q '^CONFIG_MODULES=y' .config ; then +	INSTALL_MOD_PATH="$tmpdir" make modules_install +fi + +# Install the maintainer scripts +for script in postinst postrm preinst prerm ; do +	mkdir -p "$tmpdir/etc/kernel/$script.d" +	cat <<EOF > "$tmpdir/DEBIAN/$script" +#!/bin/sh + +set -e + +test -d /etc/kernel/$script.d && run-parts --arg="$version" /etc/kernel/$script.d +exit 0 +EOF +	chmod 755 "$tmpdir/DEBIAN/$script" +done + +name="Kernel Compiler <$(id -nu)@$(hostname -f)>" +# Generate a simple changelog template +cat <<EOF > debian/changelog +linux ($version) unstable; urgency=low + +  * A standard release + + -- $name  $(date -R) +EOF + +# Generate a control file +cat <<EOF > debian/control +Source: linux +Section: base +Priority: optional +Maintainer: $name +Standards-Version: 3.6.1 + +Package: linux-$version +Architecture: any +Description: Linux kernel, version $version + This package contains the Linux kernel, modules and corresponding other + files version $version. +EOF + +# Fix some ownership and permissions +chown -R root:root "$tmpdir" +chmod -R go-w "$tmpdir" + +# Perform the final magic +dpkg-gencontrol -isp +dpkg --build "$tmpdir" .. + +exit 0 + diff --git a/scripts/package/mkspec b/scripts/package/mkspec new file mode 100755 index 000000000000..6e7a58f145ad --- /dev/null +++ b/scripts/package/mkspec @@ -0,0 +1,82 @@ +#!/bin/sh +# +#	Output a simple RPM spec file that uses no fancy features requring +#	RPM v4. This is intended to work with any RPM distro. +# +#	The only gothic bit here is redefining install_post to avoid +#	stripping the symbols from files in the kernel which we want +# +#	Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net> +# + +# how we were called determines which rpms we build and how we build them +if [ "$1" = "prebuilt" ]; then +	PREBUILT=true +else +	PREBUILT=false +fi + +# starting to output the spec +if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then +	PROVIDES=kernel-drm +fi + +PROVIDES="$PROVIDES kernel-$KERNELRELEASE" +__KERNELRELEASE=`echo $KERNELRELEASE | sed -e "s/-//g"` + +echo "Name: kernel" +echo "Summary: The Linux Kernel" +echo "Version: $__KERNELRELEASE" +# we need to determine the NEXT version number so that uname and +# rpm -q will agree +echo "Release: `. $srctree/scripts/mkversion`" +echo "License: GPL" +echo "Group: System Environment/Kernel" +echo "Vendor: The Linux Community" +echo "URL: http://www.kernel.org" + +if ! $PREBUILT; then +echo "Source: kernel-$__KERNELRELEASE.tar.gz" +fi + +echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root" +echo "Provides: $PROVIDES" +echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :" +echo "%define debug_package %{nil}" +echo "" +echo "%description" +echo "The Linux Kernel, the operating system core itself" +echo "" + +if ! $PREBUILT; then +echo "%prep" +echo "%setup -q" +echo "" +fi + +echo "%build" + +if ! $PREBUILT; then +echo "make clean && make %{_smp_mflags}" +echo "" +fi + +echo "%install" +echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules' + +echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} modules_install' +echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE" + +echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE" + +echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE" +echo "" +echo "%clean" +echo '#echo -rf $RPM_BUILD_ROOT' +echo "" +echo "%files" +echo '%defattr (-, root, root)' +echo "%dir /lib/modules" +echo "/lib/modules/$KERNELRELEASE" +echo "/boot/*" +echo "" diff --git a/scripts/patch-kernel b/scripts/patch-kernel new file mode 100755 index 000000000000..43af01075612 --- /dev/null +++ b/scripts/patch-kernel @@ -0,0 +1,257 @@ +#! /bin/sh +# Script to apply kernel patches. +#   usage: patch-kernel [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ] +#     The source directory defaults to /usr/src/linux, and the patch +#     directory defaults to the current directory. +# e.g. +#   scripts/patch-kernel . .. +#      Update the kernel tree in the current directory using patches in the +#      directory above to the latest Linus kernel +#   scripts/patch-kernel . .. -ac +#      Get the latest Linux kernel and patch it with the latest ac patch +#   scripts/patch-kernel . .. 2.4.9 +#      Gets standard kernel 2.4.9 +#   scripts/patch-kernel . .. 2.4.9 -ac +#      Gets 2.4.9 with latest ac patches +#   scripts/patch-kernel . .. 2.4.9 -ac11 +#      Gets 2.4.9 with ac patch ac11 +#   Note: It uses the patches relative to the Linus kernels, not the +#   ac to ac relative patches +# +# It determines the current kernel version from the top-level Makefile. +# It then looks for patches for the next sublevel in the patch directory. +# This is applied using "patch -p1 -s" from within the kernel directory. +# A check is then made for "*.rej" files to see if the patch was +# successful.  If it is, then all of the "*.orig" files are removed. +# +#       Nick Holloway <Nick.Holloway@alfie.demon.co.uk>, 2nd January 1995. +# +# Added support for handling multiple types of compression. What includes +# gzip, bzip, bzip2, zip, compress, and plaintext.  +# +#       Adam Sulmicki <adam@cfar.umd.edu>, 1st January 1997. +# +# Added ability to stop at a given version number +# Put the full version number (i.e. 2.3.31) as the last parameter +#       Dave Gilbert <linux@treblig.org>, 11th December 1999. + +# Fixed previous patch so that if we are already at the correct version +# not to patch up. +# +# Added -ac option, use -ac or -ac9 (say) to stop at a particular version +#       Dave Gilbert <linux@treblig.org>, 29th September 2001. +# +# Add support for (use of) EXTRAVERSION (to support 2.6.8.x, e.g.); +# update usage message; +# fix some whitespace damage; +# be smarter about stopping when current version is larger than requested; +#	Randy Dunlap <rddunlap@osdl.org>, 2004-AUG-18. + +# Set directories from arguments, or use defaults. +sourcedir=${1-/usr/src/linux} +patchdir=${2-.} +stopvers=${3-default} + +if [ "$1" == -h -o "$1" == --help -o ! -r "$sourcedir/Makefile" ]; then +cat << USAGE +usage: patch-kernel [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ] +  source directory defaults to /usr/src/linux, +  patch directory defaults to the current directory, +  stopversion defaults to <all in patchdir>. +USAGE +exit 1 +fi + +# See if we have any -ac options +for PARM in $* +do +  case $PARM in +	  -ac*) +		  gotac=$PARM; + +	esac; +done + +# --------------------------------------------------------------------------- +# Find a file, first parameter is basename of file +# it tries many compression mechanisms and sets variables to say how to get it +findFile () { +  filebase=$1; + +  if [ -r ${filebase}.gz ]; then +		ext=".gz" +		name="gzip" +		uncomp="gunzip -dc" +  elif [ -r ${filebase}.bz  ]; then +		ext=".bz" +		name="bzip" +		uncomp="bunzip -dc" +  elif [ -r ${filebase}.bz2 ]; then +		ext=".bz2" +		name="bzip2" +		uncomp="bunzip2 -dc" +  elif [ -r ${filebase}.zip ]; then +		ext=".zip" +		name="zip" +		uncomp="unzip -d" +  elif [ -r ${filebase}.Z ]; then +		ext=".Z" +		name="uncompress" +		uncomp="uncompress -c" +  elif [ -r ${filebase} ]; then +		ext="" +		name="plaintext" +		uncomp="cat" +  else +	return 1; +  fi + +  return 0; +} + +# --------------------------------------------------------------------------- +# Apply a patch and check it goes in cleanly +# First param is patch name (e.g. patch-2.4.9-ac5) - without path or extension + +applyPatch () { +  echo -n "Applying $1 (${name})... " +  if $uncomp ${patchdir}/$1${ext} | patch -p1 -s -N -E -d $sourcedir +  then +    echo "done." +  else +    echo "failed.  Clean up yourself." +    return 1; +  fi +  if [ "`find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ] +  then +    echo "Aborting.  Reject files found." +    return 1; +  fi +  # Remove backup files +  find $sourcedir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \; +  +  return 0; +} + +# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION +TMPFILE=`mktemp .tmpver.XXXXXX` || { echo "cannot make temp file" ; exit 1; } +grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE +tr -d [:blank:] < $TMPFILE > $TMPFILE.1 +source $TMPFILE.1 +rm -f $TMPFILE* +if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ] +then +    echo "unable to determine current kernel version" >&2 +    exit 1 +fi + +NAME=`grep ^NAME $sourcedir/Makefile` +NAME=${NAME##*=} + +echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} ($NAME)" + +# strip EXTRAVERSION to just a number (drop leading '.' and trailing additions) +EXTRAVER= +if [ x$EXTRAVERSION != "x" ] +then +	if [ ${EXTRAVERSION:0:1} == "." ]; then +		EXTRAVER=${EXTRAVERSION:1} +	else +		EXTRAVER=$EXTRAVERSION +	fi +	EXTRAVER=${EXTRAVER%%[[:punct:]]*} +	#echo "patch-kernel: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER" +fi + +#echo "stopvers=$stopvers" +if [ $stopvers != "default" ]; then +	STOPSUBLEVEL=`echo $stopvers | cut -d. -f3` +	STOPEXTRA=`echo $stopvers | cut -d. -f4` +	#echo "STOPSUBLEVEL=$STOPSUBLEVEL, STOPEXTRA=$STOPEXTRA" +else +	STOPSUBLEVEL=9999 +	STOPEXTRA=9999 +fi + +while :				# incrementing SUBLEVEL (s in v.p.s) +do +    if [ x$EXTRAVER != "x" ]; then +	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER" +    else +	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" +    fi + +    if [ $stopvers == $CURRENTFULLVERSION ]; then +        echo "Stopping at $CURRENTFULLVERSION base as requested." +        break +    fi + +    while :			# incrementing EXTRAVER (x in v.p.s.x) +    do +	EXTRAVER=$((EXTRAVER + 1)) +	FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER" +	#echo "... trying $FULLVERSION ..." + +	patch=patch-$FULLVERSION + +	# See if the file exists and find extension +	findFile $patchdir/${patch} || break + +	# Apply the patch and check all is OK +	applyPatch $patch || break + +	continue 2 +    done + +    EXTRAVER= +    SUBLEVEL=$((SUBLEVEL + 1)) +    FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" +    #echo "___ trying $FULLVERSION ___" + +    if [ $((SUBLEVEL)) -gt $((STOPSUBLEVEL)) ]; then +	echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)" +	exit 1 +    fi + +    patch=patch-$FULLVERSION + +    # See if the file exists and find extension +    findFile $patchdir/${patch} || break + +    # Apply the patch and check all is OK +    applyPatch $patch || break +done +#echo "base all done" + +if [ x$gotac != x ]; then +  # Out great user wants the -ac patches +	# They could have done -ac (get latest) or -acxx where xx=version they want +	if [ $gotac == "-ac" ]; then +	  # They want the latest version +		HIGHESTPATCH=0 +		for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.* +		do +			ACVALUE=`echo $PATCHNAMES | sed -e 's/^.*patch-[0-9.]*-ac\([0-9]*\).*/\1/'` +			# Check it is actually a recognised patch type +			findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${ACVALUE} || break + +		  if [ $ACVALUE -gt $HIGHESTPATCH ]; then +			  HIGHESTPATCH=$ACVALUE +		  fi +		done + +		if [ $HIGHESTPATCH -ne 0 ]; then +			findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} || break +			applyPatch patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} +		else +		  echo "No -ac patches found" +		fi +	else +	  # They want an exact version +		findFile $patchdir/patch-${CURRENTFULLVERSION}${gotac} || { +		  echo "Sorry, I couldn't find the $gotac patch for $CURRENTFULLVERSION.  Hohum." +			exit 1 +		} +		applyPatch patch-${CURRENTFULLVERSION}${gotac} +	fi +fi diff --git a/scripts/pnmtologo.c b/scripts/pnmtologo.c new file mode 100644 index 000000000000..6aa2a2483f8d --- /dev/null +++ b/scripts/pnmtologo.c @@ -0,0 +1,508 @@ + +/* + *  Convert a logo in ASCII PNM format to C source suitable for inclusion in + *  the Linux kernel + * + *  (C) Copyright 2001-2003 by Geert Uytterhoeven <geert@linux-m68k.org> + * + *  -------------------------------------------------------------------------- + * + *  This file is subject to the terms and conditions of the GNU General Public + *  License. See the file COPYING in the main directory of the Linux + *  distribution for more details. + */ + +#include <ctype.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +static const char *programname; +static const char *filename; +static const char *logoname = "linux_logo"; +static const char *outputname; +static FILE *out; + + +#define LINUX_LOGO_MONO		1	/* monochrome black/white */ +#define LINUX_LOGO_VGA16	2	/* 16 colors VGA text palette */ +#define LINUX_LOGO_CLUT224	3	/* 224 colors */ +#define LINUX_LOGO_GRAY256	4	/* 256 levels grayscale */ + +static const char *logo_types[LINUX_LOGO_GRAY256+1] = { +    [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO", +    [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16", +    [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224", +    [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256" +}; + +#define MAX_LINUX_LOGO_COLORS	224 + +struct color { +    unsigned char red; +    unsigned char green; +    unsigned char blue; +}; + +static const struct color clut_vga16[16] = { +    { 0x00, 0x00, 0x00 }, +    { 0x00, 0x00, 0xaa }, +    { 0x00, 0xaa, 0x00 }, +    { 0x00, 0xaa, 0xaa }, +    { 0xaa, 0x00, 0x00 }, +    { 0xaa, 0x00, 0xaa }, +    { 0xaa, 0x55, 0x00 }, +    { 0xaa, 0xaa, 0xaa }, +    { 0x55, 0x55, 0x55 }, +    { 0x55, 0x55, 0xff }, +    { 0x55, 0xff, 0x55 }, +    { 0x55, 0xff, 0xff }, +    { 0xff, 0x55, 0x55 }, +    { 0xff, 0x55, 0xff }, +    { 0xff, 0xff, 0x55 }, +    { 0xff, 0xff, 0xff }, +}; + + +static int logo_type = LINUX_LOGO_CLUT224; +static unsigned int logo_width; +static unsigned int logo_height; +static struct color **logo_data; +static struct color logo_clut[MAX_LINUX_LOGO_COLORS]; +static unsigned int logo_clutsize; + +static void die(const char *fmt, ...) +    __attribute__ ((noreturn)) __attribute ((format (printf, 1, 2))); +static void usage(void) __attribute ((noreturn)); + + +static unsigned int get_number(FILE *fp) +{ +    int c, val; + +    /* Skip leading whitespace */ +    do { +	c = fgetc(fp); +	if (c == EOF) +	    die("%s: end of file\n", filename); +	if (c == '#') { +	    /* Ignore comments 'till end of line */ +	    do { +		c = fgetc(fp); +		if (c == EOF) +		    die("%s: end of file\n", filename); +	    } while (c != '\n'); +	} +    } while (isspace(c)); + +    /* Parse decimal number */ +    val = 0; +    while (isdigit(c)) { +	val = 10*val+c-'0'; +	c = fgetc(fp); +	if (c == EOF) +	    die("%s: end of file\n", filename); +    } +    return val; +} + +static unsigned int get_number255(FILE *fp, unsigned int maxval) +{ +    unsigned int val = get_number(fp); +    return (255*val+maxval/2)/maxval; +} + +static void read_image(void) +{ +    FILE *fp; +    unsigned int i, j; +    int magic; +    unsigned int maxval; + +    /* open image file */ +    fp = fopen(filename, "r"); +    if (!fp) +	die("Cannot open file %s: %s\n", filename, strerror(errno)); + +    /* check file type and read file header */ +    magic = fgetc(fp); +    if (magic != 'P') +	die("%s is not a PNM file\n", filename); +    magic = fgetc(fp); +    switch (magic) { +	case '1': +	case '2': +	case '3': +	    /* Plain PBM/PGM/PPM */ +	    break; + +	case '4': +	case '5': +	case '6': +	    /* Binary PBM/PGM/PPM */ +	    die("%s: Binary PNM is not supported\n" +		"Use pnmnoraw(1) to convert it to ASCII PNM\n", filename); + +	default: +	    die("%s is not a PNM file\n", filename); +    } +    logo_width = get_number(fp); +    logo_height = get_number(fp); + +    /* allocate image data */ +    logo_data = (struct color **)malloc(logo_height*sizeof(struct color *)); +    if (!logo_data) +	die("%s\n", strerror(errno)); +    for (i = 0; i < logo_height; i++) { +	logo_data[i] = malloc(logo_width*sizeof(struct color)); +	if (!logo_data[i]) +	    die("%s\n", strerror(errno)); +    } + +    /* read image data */ +    switch (magic) { +	case '1': +	    /* Plain PBM */ +	    for (i = 0; i < logo_height; i++) +		for (j = 0; j < logo_width; j++) +		    logo_data[i][j].red = logo_data[i][j].green = +			logo_data[i][j].blue = 255*(1-get_number(fp)); +	    break; + +	case '2': +	    /* Plain PGM */ +	    maxval = get_number(fp); +	    for (i = 0; i < logo_height; i++) +		for (j = 0; j < logo_width; j++) +		    logo_data[i][j].red = logo_data[i][j].green = +			logo_data[i][j].blue = get_number255(fp, maxval); +	    break; + +	case '3': +	    /* Plain PPM */ +	    maxval = get_number(fp); +	    for (i = 0; i < logo_height; i++) +		for (j = 0; j < logo_width; j++) { +		    logo_data[i][j].red = get_number255(fp, maxval); +		    logo_data[i][j].green = get_number255(fp, maxval); +		    logo_data[i][j].blue = get_number255(fp, maxval); +		} +	    break; +    } + +    /* close file */ +    fclose(fp); +} + +static inline int is_black(struct color c) +{ +    return c.red == 0 && c.green == 0 && c.blue == 0; +} + +static inline int is_white(struct color c) +{ +    return c.red == 255 && c.green == 255 && c.blue == 255; +} + +static inline int is_gray(struct color c) +{ +    return c.red == c.green && c.red == c.blue; +} + +static inline int is_equal(struct color c1, struct color c2) +{ +    return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue; +} + +static void write_header(void) +{ +    /* open logo file */ +    if (outputname) { +	out = fopen(outputname, "w"); +	if (!out) +	    die("Cannot create file %s: %s\n", outputname, strerror(errno)); +    } else { +	out = stdout; +    } + +    fputs("/*\n", out); +    fputs(" *  DO NOT EDIT THIS FILE!\n", out); +    fputs(" *\n", out); +    fprintf(out, " *  It was automatically generated from %s\n", filename); +    fputs(" *\n", out); +    fprintf(out, " *  Linux logo %s\n", logoname); +    fputs(" */\n\n", out); +    fputs("#include <linux/linux_logo.h>\n\n", out); +    fprintf(out, "static unsigned char %s_data[] __initdata = {\n", +	    logoname); +} + +static void write_footer(void) +{ +    fputs("\n};\n\n", out); +    fprintf(out, "struct linux_logo %s __initdata = {\n", logoname); +    fprintf(out, "    .type\t= %s,\n", logo_types[logo_type]); +    fprintf(out, "    .width\t= %d,\n", logo_width); +    fprintf(out, "    .height\t= %d,\n", logo_height); +    if (logo_type == LINUX_LOGO_CLUT224) { +	fprintf(out, "    .clutsize\t= %d,\n", logo_clutsize); +	fprintf(out, "    .clut\t= %s_clut,\n", logoname); +    } +    fprintf(out, "    .data\t= %s_data\n", logoname); +    fputs("};\n\n", out); + +    /* close logo file */ +    if (outputname) +	fclose(out); +} + +static int write_hex_cnt; + +static void write_hex(unsigned char byte) +{ +    if (write_hex_cnt % 12) +	fprintf(out, ", 0x%02x", byte); +    else if (write_hex_cnt) +	fprintf(out, ",\n\t0x%02x", byte); +    else +	fprintf(out, "\t0x%02x", byte); +    write_hex_cnt++; +} + +static void write_logo_mono(void) +{ +    unsigned int i, j; +    unsigned char val, bit; + +    /* validate image */ +    for (i = 0; i < logo_height; i++) +	for (j = 0; j < logo_width; j++) +	    if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j])) +		die("Image must be monochrome\n"); + +    /* write file header */ +    write_header(); + +    /* write logo data */ +    for (i = 0; i < logo_height; i++) { +	for (j = 0; j < logo_width;) { +	    for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1) +		if (logo_data[i][j].red) +		    val |= bit; +	    write_hex(val); +	} +    } + +    /* write logo structure and file footer */ +    write_footer(); +} + +static void write_logo_vga16(void) +{ +    unsigned int i, j, k; +    unsigned char val; + +    /* validate image */ +    for (i = 0; i < logo_height; i++) +	for (j = 0; j < logo_width; j++) { +	    for (k = 0; k < 16; k++) +		if (is_equal(logo_data[i][j], clut_vga16[k])) +		    break; +	    if (k == 16) +		die("Image must use the 16 console colors only\n" +		    "Use ppmquant(1) -map clut_vga16.ppm to reduce the number " +		    "of colors\n"); +	} + +    /* write file header */ +    write_header(); + +    /* write logo data */ +    for (i = 0; i < logo_height; i++) +	for (j = 0; j < logo_width; j++) { +	    for (k = 0; k < 16; k++) +		if (is_equal(logo_data[i][j], clut_vga16[k])) +		    break; +	    val = k<<4; +	    if (++j < logo_width) { +		for (k = 0; k < 16; k++) +		    if (is_equal(logo_data[i][j], clut_vga16[k])) +			break; +		val |= k; +	    } +	    write_hex(val); +	} + +    /* write logo structure and file footer */ +    write_footer(); +} + +static void write_logo_clut224(void) +{ +    unsigned int i, j, k; + +    /* validate image */ +    for (i = 0; i < logo_height; i++) +	for (j = 0; j < logo_width; j++) { +	    for (k = 0; k < logo_clutsize; k++) +		if (is_equal(logo_data[i][j], logo_clut[k])) +		    break; +	    if (k == logo_clutsize) { +		if (logo_clutsize == MAX_LINUX_LOGO_COLORS) +		    die("Image has more than %d colors\n" +			"Use ppmquant(1) to reduce the number of colors\n", +			MAX_LINUX_LOGO_COLORS); +		logo_clut[logo_clutsize++] = logo_data[i][j]; +	    } +	} + +    /* write file header */ +    write_header(); + +    /* write logo data */ +    for (i = 0; i < logo_height; i++) +	for (j = 0; j < logo_width; j++) { +	    for (k = 0; k < logo_clutsize; k++) +		if (is_equal(logo_data[i][j], logo_clut[k])) +		    break; +	    write_hex(k+32); +	} +    fputs("\n};\n\n", out); + +    /* write logo clut */ +    fprintf(out, "static unsigned char %s_clut[] __initdata = {\n", +	    logoname); +    write_hex_cnt = 0; +    for (i = 0; i < logo_clutsize; i++) { +	write_hex(logo_clut[i].red); +	write_hex(logo_clut[i].green); +	write_hex(logo_clut[i].blue); +    } + +    /* write logo structure and file footer */ +    write_footer(); +} + +static void write_logo_gray256(void) +{ +    unsigned int i, j; + +    /* validate image */ +    for (i = 0; i < logo_height; i++) +	for (j = 0; j < logo_width; j++) +	    if (!is_gray(logo_data[i][j])) +		die("Image must be grayscale\n"); + +    /* write file header */ +    write_header(); + +    /* write logo data */ +    for (i = 0; i < logo_height; i++) +	for (j = 0; j < logo_width; j++) +	    write_hex(logo_data[i][j].red); + +    /* write logo structure and file footer */ +    write_footer(); +} + +static void die(const char *fmt, ...) +{ +    va_list ap; + +    va_start(ap, fmt); +    vfprintf(stderr, fmt, ap); +    va_end(ap); + +    exit(1); +} + +static void usage(void) +{ +    die("\n" +	"Usage: %s [options] <filename>\n" +	"\n" +	"Valid options:\n" +	"    -h          : display this usage information\n" +	"    -n <name>   : specify logo name (default: linux_logo)\n" +	"    -o <output> : output to file <output> instead of stdout\n" +	"    -t <type>   : specify logo type, one of\n" +	"                      mono    : monochrome black/white\n" +	"                      vga16   : 16 colors VGA text palette\n" +	"                      clut224 : 224 colors (default)\n" +	"                      gray256 : 256 levels grayscale\n" +	"\n", programname); +} + +int main(int argc, char *argv[]) +{ +    int opt; + +    programname = argv[0]; + +    opterr = 0; +    while (1) { +	opt = getopt(argc, argv, "hn:o:t:"); +	if (opt == -1) +	    break; + +	switch (opt) { +	    case 'h': +		usage(); +		break; + +	    case 'n': +		logoname = optarg; +		break; + +	    case 'o': +		outputname = optarg; +		break; + +	    case 't': +		if (!strcmp(optarg, "mono")) +		    logo_type = LINUX_LOGO_MONO; +		else if (!strcmp(optarg, "vga16")) +		    logo_type = LINUX_LOGO_VGA16; +		else if (!strcmp(optarg, "clut224")) +		    logo_type = LINUX_LOGO_CLUT224; +		else if (!strcmp(optarg, "gray256")) +		    logo_type = LINUX_LOGO_GRAY256; +		else +		    usage(); +		break; + +	    default: +		usage(); +		break; +	} +    } +    if (optind != argc-1) +	usage(); + +    filename = argv[optind]; + +    read_image(); +    switch (logo_type) { +	case LINUX_LOGO_MONO: +	    write_logo_mono(); +	    break; + +	case LINUX_LOGO_VGA16: +	    write_logo_vga16(); +	    break; + +	case LINUX_LOGO_CLUT224: +	    write_logo_clut224(); +	    break; + +	case LINUX_LOGO_GRAY256: +	    write_logo_gray256(); +	    break; +    } +    exit(0); +} + diff --git a/scripts/reference_discarded.pl b/scripts/reference_discarded.pl new file mode 100644 index 000000000000..d5cabb81bd1b --- /dev/null +++ b/scripts/reference_discarded.pl @@ -0,0 +1,110 @@ +#!/usr/bin/perl -w +# +# reference_discarded.pl (C) Keith Owens 2001 <kaos@ocs.com.au> +# +# Released under GPL V2. +# +# List dangling references to vmlinux discarded sections. + +use strict; +die($0 . " takes no arguments\n") if($#ARGV >= 0); + +my %object; +my $object; +my $line; +my $ignore; +my $errorcount; + +$| = 1; + +# printf("Finding objects, "); +open(OBJDUMP_LIST, "find . -name '*.o' | xargs objdump -h |") || die "getting objdump list failed"; +while (defined($line = <OBJDUMP_LIST>)) { +	chomp($line); +	if ($line =~ /:\s+file format/) { +		($object = $line) =~ s/:.*//; +		$object{$object}->{'module'} = 0; +		$object{$object}->{'size'} = 0; +		$object{$object}->{'off'} = 0; +	} +	if ($line =~ /^\s*\d+\s+\.modinfo\s+/) { +		$object{$object}->{'module'} = 1; +	} +	if ($line =~ /^\s*\d+\s+\.comment\s+/) { +		($object{$object}->{'size'}, $object{$object}->{'off'}) = (split(' ', $line))[2,5]; +	} +} +close(OBJDUMP_LIST); +# printf("%d objects, ", scalar keys(%object)); +$ignore = 0; +foreach $object (keys(%object)) { +	if ($object{$object}->{'module'}) { +		++$ignore; +		delete($object{$object}); +	} +} +# printf("ignoring %d module(s)\n", $ignore); + +# Ignore conglomerate objects, they have been built from multiple objects and we +# only care about the individual objects.  If an object has more than one GCC: +# string in the comment section then it is conglomerate.  This does not filter +# out conglomerates that consist of exactly one object, can't be helped. + +# printf("Finding conglomerates, "); +$ignore = 0; +foreach $object (keys(%object)) { +	if (exists($object{$object}->{'off'})) { +		my ($off, $size, $comment, $l); +		$off = hex($object{$object}->{'off'}); +		$size = hex($object{$object}->{'size'}); +		open(OBJECT, "<$object") || die "cannot read $object"; +		seek(OBJECT, $off, 0) || die "seek to $off in $object failed"; +		$l = read(OBJECT, $comment, $size); +		die "read $size bytes from $object .comment failed" if ($l != $size); +		close(OBJECT); +		if ($comment =~ /GCC\:.*GCC\:/m || $object =~ /built-in\.o/) { +			++$ignore; +			delete($object{$object}); +		} +	} +} +# printf("ignoring %d conglomerate(s)\n", $ignore); + +# printf("Scanning objects\n"); +$errorcount = 0; +foreach $object (keys(%object)) { +	my $from; +	open(OBJDUMP, "objdump -r $object|") || die "cannot objdump -r $object"; +	while (defined($line = <OBJDUMP>)) { +		chomp($line); +		if ($line =~ /RELOCATION RECORDS FOR /) { +			($from = $line) =~ s/.*\[([^]]*).*/$1/; +		} +		if (($line =~ /\.text\.exit$/ || +		     $line =~ /\.exit\.text$/ || +		     $line =~ /\.data\.exit$/ || +		     $line =~ /\.exit\.data$/ || +		     $line =~ /\.exitcall\.exit$/) && +		    ($from !~ /\.text\.exit$/ && +		     $from !~ /\.exit\.text$/ && +		     $from !~ /\.data\.exit$/ && +		     $from !~ /\.exit\.data$/ && +		     $from !~ /\.altinstructions$/ && +		     $from !~ /\.pdr$/ && +		     $from !~ /\.debug_info$/ && +		     $from !~ /\.debug_aranges$/ && +		     $from !~ /\.debug_ranges$/ && +		     $from !~ /\.debug_line$/ && +		     $from !~ /\.debug_frame$/ && +		     $from !~ /\.exitcall\.exit$/ && +		     $from !~ /\.eh_frame$/ && +		     $from !~ /\.stab$/)) { +			printf("Error: %s %s refers to %s\n", $object, $from, $line); +			$errorcount = $errorcount + 1; +		} +	} +	close(OBJDUMP); +} +# printf("Done\n"); + +exit(0); diff --git a/scripts/reference_init.pl b/scripts/reference_init.pl new file mode 100644 index 000000000000..9a2408453869 --- /dev/null +++ b/scripts/reference_init.pl @@ -0,0 +1,107 @@ +#!/usr/bin/perl -w +# +# reference_init.pl (C) Keith Owens 2002 <kaos@ocs.com.au> +# +# List references to vmlinux init sections from non-init sections. + +# Unfortunately I had to exclude references from read only data to .init +# sections, almost all of these are false positives, they are created by +# gcc.  The downside of excluding rodata is that there really are some +# user references from rodata to init code, e.g. drivers/video/vgacon.c +# +# const struct consw vga_con = { +#        con_startup:            vgacon_startup, +# +# where vgacon_startup is __init.  If you want to wade through the false +# positives, take out the check for rodata. + +use strict; +die($0 . " takes no arguments\n") if($#ARGV >= 0); + +my %object; +my $object; +my $line; +my $ignore; + +$| = 1; + +printf("Finding objects, "); +open(OBJDUMP_LIST, "find . -name '*.o' | xargs objdump -h |") || die "getting objdump list failed"; +while (defined($line = <OBJDUMP_LIST>)) { +	chomp($line); +	if ($line =~ /:\s+file format/) { +		($object = $line) =~ s/:.*//; +		$object{$object}->{'module'} = 0; +		$object{$object}->{'size'} = 0; +		$object{$object}->{'off'} = 0; +	} +	if ($line =~ /^\s*\d+\s+\.modinfo\s+/) { +		$object{$object}->{'module'} = 1; +	} +	if ($line =~ /^\s*\d+\s+\.comment\s+/) { +		($object{$object}->{'size'}, $object{$object}->{'off'}) = (split(' ', $line))[2,5]; +	} +} +close(OBJDUMP_LIST); +printf("%d objects, ", scalar keys(%object)); +$ignore = 0; +foreach $object (keys(%object)) { +	if ($object{$object}->{'module'}) { +		++$ignore; +		delete($object{$object}); +	} +} +printf("ignoring %d module(s)\n", $ignore); + +# Ignore conglomerate objects, they have been built from multiple objects and we +# only care about the individual objects.  If an object has more than one GCC: +# string in the comment section then it is conglomerate.  This does not filter +# out conglomerates that consist of exactly one object, can't be helped. + +printf("Finding conglomerates, "); +$ignore = 0; +foreach $object (keys(%object)) { +	if (exists($object{$object}->{'off'})) { +		my ($off, $size, $comment, $l); +		$off = hex($object{$object}->{'off'}); +		$size = hex($object{$object}->{'size'}); +		open(OBJECT, "<$object") || die "cannot read $object"; +		seek(OBJECT, $off, 0) || die "seek to $off in $object failed"; +		$l = read(OBJECT, $comment, $size); +		die "read $size bytes from $object .comment failed" if ($l != $size); +		close(OBJECT); +		if ($comment =~ /GCC\:.*GCC\:/m || $object =~ /built-in\.o/) { +			++$ignore; +			delete($object{$object}); +		} +	} +} +printf("ignoring %d conglomerate(s)\n", $ignore); + +printf("Scanning objects\n"); +foreach $object (sort(keys(%object))) { +	my $from; +	open(OBJDUMP, "objdump -r $object|") || die "cannot objdump -r $object"; +	while (defined($line = <OBJDUMP>)) { +		chomp($line); +		if ($line =~ /RELOCATION RECORDS FOR /) { +			($from = $line) =~ s/.*\[([^]]*).*/$1/; +		} +		if (($line =~ /\.init$/ || $line =~ /\.init\./) && +		    ($from !~ /\.init$/ && +		     $from !~ /\.init\./ && +		     $from !~ /\.stab$/ && +		     $from !~ /\.rodata$/ && +		     $from !~ /\.text\.lock$/ && +		     $from !~ /\.pci_fixup_header$/ && +		     $from !~ /\.pci_fixup_final$/ && +		     $from !~ /\.pdr$/ && +		     $from !~ /\__param$/ && +		     $from !~ /\.altinstructions/ && +		     $from !~ /\.debug_/)) { +			printf("Error: %s %s refers to %s\n", $object, $from, $line); +		} +	} +	close(OBJDUMP); +} +printf("Done\n"); diff --git a/scripts/show_delta b/scripts/show_delta new file mode 100644 index 000000000000..48a706ab3d0c --- /dev/null +++ b/scripts/show_delta @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# show_deltas: Read list of printk messages instrumented with +# time data, and format with time deltas. +# +# Also, you can show the times relative to a fixed point. +# +# Copyright 2003 Sony Corporation +# +# GPL 2.0 applies. + +import sys +import string + +def usage(): +	print """usage: show_delta [<options>] <filename> + +This program parses the output from a set of printk message lines which +have time data prefixed because the CONFIG_PRINTK_TIME option is set, or +the kernel command line option "time" is specified. When run with no +options, the time information is converted to show the time delta between +each printk line and the next.  When run with the '-b' option, all times +are relative to a single (base) point in time. + +Options: +  -h            Show this usage help. +  -b <base>	Specify a base for time references. +		<base> can be a number or a string. +		If it is a string, the first message line +		which matches (at the beginning of the +		line) is used as the time reference. + +ex: $ dmesg >timefile +    $ show_delta -b NET4 timefile + +will show times relative to the line in the kernel output +starting with "NET4". +""" +	sys.exit(1) + +# returns a tuple containing the seconds and text for each message line +# seconds is returned as a float +# raise an exception if no timing data was found +def get_time(line): +	if line[0]!="[": +		raise ValueError + +	# split on closing bracket +	(time_str, rest) = string.split(line[1:],']',1) +	time = string.atof(time_str) + +	#print "time=", time +	return (time, rest) + + +# average line looks like: +# [    0.084282] VFS: Mounted root (romfs filesystem) readonly +# time data is expressed in seconds.useconds, +# convert_line adds a delta for each line +last_time = 0.0 +def convert_line(line, base_time): +	global last_time + +	try: +		(time, rest) = get_time(line) +	except: +		# if any problem parsing time, don't convert anything +		return line + +	if base_time: +		# show time from base +		delta = time - base_time +	else: +		# just show time from last line +		delta = time - last_time +		last_time = time + +	return ("[%5.6f < %5.6f >]" % (time, delta)) + rest + +def main(): +	base_str = "" +	filein = "" +	for arg in sys.argv[1:]: +		if arg=="-b": +			base_str = sys.argv[sys.argv.index("-b")+1] +		elif arg=="-h": +			usage() +		else: +			filein = arg + +	if not filein: +		usage() + +	try: +		lines = open(filein,"r").readlines() +	except: +		print "Problem opening file: %s" % filein +		sys.exit(1) + +	if base_str: +		print 'base= "%s"' % base_str +		# assume a numeric base.  If that fails, try searching +		# for a matching line. +		try: +			base_time = float(base_str) +		except: +			# search for line matching <base> string +			found = 0 +			for line in lines: +				try: +					(time, rest) = get_time(line) +				except: +					continue +				if string.find(rest, base_str)==1: +					base_time = time +					found = 1 +					# stop at first match +					break +			if not found: +				print 'Couldn\'t find line matching base pattern "%s"' % base_str +				sys.exit(1) +	else: +		base_time = 0.0 + +	for line in lines: +		print convert_line(line, base_time), + +main() + diff --git a/scripts/split-man b/scripts/split-man new file mode 100755 index 000000000000..03897fe6a75d --- /dev/null +++ b/scripts/split-man @@ -0,0 +1,112 @@ +#!/usr/bin/perl + +use strict; + +## Copyright (C) Michael Still (mikal@stillhq.com) +## Released under the terms of the GNU GPL +## +## Hoon through the specified DocBook SGML file, and split out the +## man pages. These can then be processed into groff format, and +## installed if desired... +## +## Arguements: $1 -- the name of the sgml file +##             $2 -- the directory to put the generated SGML files in +##             $3 -- kernel version + +my($SGML, $REF, $front, $refdata, $mode, $filename); + +if(($ARGV[0] eq "") || ($ARGV[1] eq "") || ($ARGV[2] eq "")){ +  die "Usage: split-man <sgml file> <output dir> <kernel version>\n"; +} + +open SGML, "< $ARGV[0]" or die "Could not open input file \"$ARGV[0]\"\n"; +if( ! -d "$ARGV[1]" ){ +  die "Output directory \"$ARGV[1]\" does not exist\n"; +} + +# Possible modes: +#   0: Looking for input I care about +#   1: Inside book front matter +#   2: Inside a refentry +#   3: Inside a refentry, and we know the filename + +$mode = 0; +$refdata = ""; +$front = ""; +while(<SGML>){ +  # Starting modes +  if(/<bookinfo>/ || /<docinfo>/){ +    $mode = 1; +  } +  elsif(/<refentry>/){ +    $mode = 2; +  } +  elsif(/<refentrytitle><phrase[^>]*>([^<]*)<.*$/){ +    $mode = 3; +    $filename = $1; + +    $filename =~ s/struct //; +    $filename =~ s/typedef //; + +    print "Found manpage for $filename\n"; +    open REF, "> $ARGV[1]/$filename.sgml" or +      die "Couldn't open output file \"$ARGV[1]/$filename.sgml\": $!\n"; +    print REF <<EOF; +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> + +<!-- BEGINFRONTTAG: The following is front matter for the parent book --> +$front +<!-- ENDFRONTTAG: End front matter --> + +$refdata +EOF +    $refdata = ""; +  } + +  # Extraction +  if($mode == 1){ +    chomp $_; +    $front = "$front<!-- $_ -->\n"; +  } +  elsif($mode == 2){ +    $refdata = "$refdata$_"; +  } +  elsif($mode == 3){ +    # There are some fixups which need to be applied +    if(/<\/refmeta>/){ +      print REF "<manvolnum>9</manvolnum>\n"; +    } +    if(/<\/refentry>/){ +      print REF <<EOF; +<refsect1><title>About this document</title> +<para> +This documentation was generated with kernel version $ARGV[2]. +</para> +</refsect1> +EOF +    } + +    # For some reason, we title the synopsis twice in the main DocBook +    if(! /<title>Synopsis<\/title>/){ +      if(/<refentrytitle>/){ +	s/struct //; +	s/typedef //; +      } + +      print REF "$_"; +    } +  } + +  # Ending modes +  if(/<\/bookinfo>/ || /<\/docinfo>/){ +    $mode = 0; +  } +  elsif(/<\/refentry>/){ +    $mode = 0; +    close REF; +  } +} + +# And make sure we don't process this unnessesarily +$ARGV[0] =~ s/\.sgml/.9/; +`touch $ARGV[0]`; diff --git a/scripts/ver_linux b/scripts/ver_linux new file mode 100755 index 000000000000..bb195a1c0f2d --- /dev/null +++ b/scripts/ver_linux @@ -0,0 +1,95 @@ +#!/bin/sh +# Before running this script please ensure that your PATH is +# typical as you use for compilation/istallation. I use +# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may +# differ on your system. +# +PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:$PATH +echo 'If some fields are empty or look unusual you may have an old version.' +echo 'Compare to the current minimal requirements in Documentation/Changes.' +echo ' ' + +uname -a +echo ' ' + +gcc --version 2>&1| head -n 1 | grep -v gcc | awk \ +'NR==1{print "Gnu C                 ", $1}' + +gcc --version 2>&1| grep gcc | awk \ +'NR==1{print "Gnu C                 ", $3}' + +make --version 2>&1 | awk -F, '{print $1}' | awk \ +      '/GNU Make/{print "Gnu make              ",$NF}' + +ld -v | awk -F\) '{print $1}' | awk \ +'/BFD/{print "binutils              ",$NF} \ +/^GNU/{print "binutils              ",$4}' + +fdformat --version | awk -F\- '{print "util-linux            ", $NF}' + +mount --version | awk -F\- '{print "mount                 ", $NF}' + +depmod -V  2>&1 | awk 'NR==1 {print "module-init-tools     ",$NF}' + +tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' |  awk \ +'NR==1 {print "e2fsprogs             ", $2}' + +fsck.jfs -V 2>&1 | grep version | sed 's/,//' |  awk \ +'NR==1 {print "jfsutils              ", $3}' + +reiserfsck -V 2>&1 | grep reiserfsck | awk \ +'NR==1{print "reiserfsprogs         ", $2}' + +fsck.reiser4 -V 2>&1 | grep fsck.reiser4 | awk \ +'NR==1{print "reiser4progs          ", $2}' + +xfs_db -V 2>&1 | grep version | awk \ +'NR==1{print "xfsprogs              ", $3}' + +cardmgr -V 2>&1| grep version | awk \ +'NR==1{print "pcmcia-cs             ", $3}' + +quota -V 2>&1 | grep version | awk \ +'NR==1{print "quota-tools           ", $NF}' + +pppd --version 2>&1| grep version | awk \ +'NR==1{print "PPP                   ", $3}' + +isdnctrl 2>&1 | grep version | awk \ +'NR==1{print "isdn4k-utils          ", $NF}' + +showmount --version 2>&1 | grep nfs-utils | awk \ +'NR==1{print "nfs-utils             ", $NF}' + +ls -l `ldd /bin/sh | awk '/libc/{print $3}'` | sed \ +-e 's/\.so$//' | awk -F'[.-]'   '{print "Linux C Library        " \ +$(NF-2)"."$(NF-1)"."$NF}' + +ldd -v > /dev/null 2>&1 && ldd -v || ldd --version |head -n 1 | awk \ +'NR==1{print "Dynamic linker (ldd)  ", $NF}' + +ls -l /usr/lib/lib{g,stdc}++.so  2>/dev/null | awk -F. \ +       '{print "Linux C++ Library      " $4"."$5"."$6}' + +ps --version 2>&1 | grep version | awk \ +'NR==1{print "Procps                ", $NF}' + +ifconfig --version 2>&1 | grep tools | awk \ +'NR==1{print "Net-tools             ", $NF}' + +# Kbd needs 'loadkeys -h', +loadkeys -h 2>&1 | awk \ +'(NR==1 && ($3 !~ /option/)) {print "Kbd                   ", $3}' + +# while console-tools needs 'loadkeys -V'. +loadkeys -V 2>&1 | awk \ +'(NR==1 && ($2 ~ /console-tools/)) {print "Console-tools         ", $3}' + +expr --v 2>&1 | awk 'NR==1{print "Sh-utils              ", $NF}' + +udevinfo -V | awk '{print "udev                  ", $3}' + +if [ -e /proc/modules ]; then +    X=`cat /proc/modules | sed -e "s/ .*$//"` +    echo "Modules Loaded         "$X +fi  |