Linux-2.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!
This commit is contained in:
Linus Torvalds
2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

2
scripts/Lindent Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
indent -kr -i8 -ts8 -sob -l80 -ss -ncs "$@"

22
scripts/Makefile Normal file
View File

@@ -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

330
scripts/Makefile.build Normal file
View File

@@ -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

94
scripts/Makefile.clean Normal file
View File

@@ -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

155
scripts/Makefile.host Normal file
View File

@@ -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)

267
scripts/Makefile.lib Normal file
View File

@@ -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

29
scripts/Makefile.modinst Normal file
View File

@@ -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))

110
scripts/Makefile.modpost Normal file
View File

@@ -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

18
scripts/basic/Makefile Normal file
View File

@@ -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

398
scripts/basic/docproc.c Normal file
View File

@@ -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<73>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;
}

390
scripts/basic/fixdep.c Normal file
View File

@@ -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;
}

View File

@@ -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;
}

36
scripts/bin2c.c Normal file
View File

@@ -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;
}

163
scripts/binoffset.c Normal file
View File

@@ -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 */

65
scripts/checkconfig.pl Executable file
View File

@@ -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);
}

24
scripts/checkincludes.pl Executable file
View File

@@ -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);
}

123
scripts/checkstack.pl Normal file
View File

@@ -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;

72
scripts/checkversion.pl Executable file
View File

@@ -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);
}

293
scripts/conmakehash.c Normal file
View File

@@ -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);
}

77
scripts/extract-ikconfig Executable file
View File

@@ -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

14
scripts/gcc-version.sh Normal file
View File

@@ -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

View File

@@ -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

49
scripts/genksyms/Makefile Normal file
View File

@@ -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

591
scripts/genksyms/genksyms.c Normal file
View File

@@ -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;
}

104
scripts/genksyms/genksyms.h Normal file
View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

407
scripts/genksyms/lex.l Normal file
View File

@@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -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;

469
scripts/genksyms/parse.y Normal file
View File

@@ -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);
}

686
scripts/kallsyms.c Normal file
View File

@@ -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;
}

208
scripts/kconfig/Makefile Normal file
View File

@@ -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

583
scripts/kconfig/conf.c Normal file
View File

@@ -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;
}

460
scripts/kconfig/confdata.c Normal file
View File

@@ -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;
}

1099
scripts/kconfig/expr.c Normal file

File diff suppressed because it is too large Load Diff

195
scripts/kconfig/expr.h Normal file
View File

@@ -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 */

1639
scripts/kconfig/gconf.c Normal file

File diff suppressed because it is too large Load Diff

543
scripts/kconfig/gconf.glade Normal file
View File

@@ -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>

326
scripts/kconfig/images.c Normal file
View File

@@ -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",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};

View File

@@ -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
}

File diff suppressed because it is too large Load Diff

123
scripts/kconfig/lkc.h Normal file
View File

@@ -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 */

View File

@@ -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));

1090
scripts/kconfig/mconf.c Normal file

File diff suppressed because it is too large Load Diff

390
scripts/kconfig/menu.c Normal file
View File

@@ -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 = &current_entry->list;
}
void menu_end_menu(void)
{
last_entry_ptr = &current_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;
}

1407
scripts/kconfig/qconf.cc Normal file

File diff suppressed because it is too large Load Diff

263
scripts/kconfig/qconf.h Normal file
View File

@@ -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;
};

816
scripts/kconfig/symbol.c Normal file
View File

@@ -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";
}

109
scripts/kconfig/util.c Normal file
View File

@@ -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;
}

366
scripts/kconfig/zconf.l Normal file
View File

@@ -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>";
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 */

690
scripts/kconfig/zconf.y Normal file
View File

@@ -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"

1831
scripts/kernel-doc Executable file

File diff suppressed because it is too large Load Diff

8
scripts/ksymoops/README Normal file
View File

@@ -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

View File

@@ -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.

42
scripts/lxdialog/Makefile Normal file
View File

@@ -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

View File

@@ -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 */
}

155
scripts/lxdialog/colors.h Normal file
View File

@@ -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];

187
scripts/lxdialog/dialog.h Normal file
View File

@@ -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

240
scripts/lxdialog/inputbox.c Normal file
View File

@@ -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 */
}

226
scripts/lxdialog/lxdialog.c Normal file
View File

@@ -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);
}

445
scripts/lxdialog/menubox.c Normal file
View File

@@ -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 */
}

85
scripts/lxdialog/msgbox.c Normal file
View File

@@ -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;
}

556
scripts/lxdialog/textbox.c Normal file
View File

@@ -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);
}

359
scripts/lxdialog/util.c Normal file
View File

@@ -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;
}

118
scripts/lxdialog/yesno.c Normal file
View File

@@ -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 */
}

31
scripts/makelst Executable file
View File

@@ -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

185
scripts/makeman Executable file
View File

@@ -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";

78
scripts/mkcompile_h Executable file
View File

@@ -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

31
scripts/mkmakefile Normal file
View File

@@ -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

44
scripts/mksysmap Normal file
View File

@@ -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

16
scripts/mkuboot.sh Executable file
View File

@@ -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} "$@"

6
scripts/mkversion Normal file
View File

@@ -0,0 +1,6 @@
if [ ! -f .version ]
then
echo 1
else
expr 0`cat .version` + 1
fi

16
scripts/mod/Makefile Normal file
View File

@@ -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

1
scripts/mod/empty.c Normal file
View File

@@ -0,0 +1 @@
/* empty file to figure out endianness / word size */

308
scripts/mod/file2alias.c Normal file
View File

@@ -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);
}

View File

@@ -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;
}

797
scripts/mod/modpost.c Normal file
View File

@@ -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;
}

107
scripts/mod/modpost.h Normal file
View File

@@ -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);

498
scripts/mod/sumversion.c Normal file
View File

@@ -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);
}

454
scripts/namespace.pl Normal file
View File

@@ -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";
}
}
}
}

89
scripts/package/Makefile Normal file
View File

@@ -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'

79
scripts/package/builddeb Normal file
View File

@@ -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

82
scripts/package/mkspec Executable file
View File

@@ -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 ""

257
scripts/patch-kernel Executable file
View File

@@ -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

508
scripts/pnmtologo.c Normal file
View File

@@ -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);
}

View File

@@ -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);

107
scripts/reference_init.pl Normal file
View File

@@ -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");

129
scripts/show_delta Normal file
View File

@@ -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()

112
scripts/split-man Executable file
View File

@@ -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]`;

95
scripts/ver_linux Executable file
View File

@@ -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