aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Makefile1
-rw-r--r--scripts/Makefile.build57
-rw-r--r--scripts/Makefile.clean2
-rw-r--r--scripts/Makefile.headersinst3
-rw-r--r--scripts/Makefile.help3
-rw-r--r--scripts/Makefile.lib19
-rw-r--r--scripts/Makefile.modbuiltin5
-rw-r--r--scripts/Makefile.modpost9
-rw-r--r--scripts/basic/Makefile2
-rw-r--r--scripts/basic/docproc.c132
-rw-r--r--scripts/basic/fixdep.c119
-rw-r--r--scripts/basic/hash.c64
-rw-r--r--scripts/binoffset.c163
-rwxr-xr-xscripts/checkkconfigsymbols.sh2
-rwxr-xr-xscripts/checkpatch.pl289
-rwxr-xr-xscripts/checksyscalls.sh5
-rwxr-xr-xscripts/coccicheck106
-rw-r--r--scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci67
-rw-r--r--scripts/coccinelle/api/alloc/kzalloc-simple.cocci86
-rw-r--r--scripts/coccinelle/api/err_cast.cocci56
-rw-r--r--scripts/coccinelle/api/kstrdup.cocci39
-rw-r--r--scripts/coccinelle/api/memdup.cocci40
-rw-r--r--scripts/coccinelle/api/memdup_user.cocci35
-rw-r--r--scripts/coccinelle/api/resource_size.cocci93
-rw-r--r--scripts/coccinelle/free/kfree.cocci117
-rw-r--r--scripts/coccinelle/iterators/fen.cocci64
-rw-r--r--scripts/coccinelle/iterators/itnull.cocci58
-rw-r--r--scripts/coccinelle/iterators/list_entry_update.cocci62
-rw-r--r--scripts/coccinelle/locks/call_kern.cocci74
-rw-r--r--scripts/coccinelle/locks/double_lock.cocci92
-rw-r--r--scripts/coccinelle/locks/flags.cocci80
-rw-r--r--scripts/coccinelle/locks/mini_lock.cocci95
-rw-r--r--scripts/coccinelle/misc/doubleinit.cocci53
-rw-r--r--scripts/coccinelle/misc/ifcol.cocci48
-rw-r--r--scripts/coccinelle/null/deref_null.cocci293
-rw-r--r--scripts/coccinelle/null/eno.cocci20
-rw-r--r--scripts/coccinelle/null/kmerr.cocci72
-rw-r--r--scripts/coccinelle/tests/doublebitand.cocci54
-rw-r--r--scripts/coccinelle/tests/doubletest.cocci40
-rwxr-xr-xscripts/decodecode10
-rw-r--r--scripts/dtc/fstree.c1
-rwxr-xr-xscripts/extract-ikconfig130
-rw-r--r--scripts/gcc-goto.sh5
-rw-r--r--scripts/gen_initramfs_list.sh1
-rw-r--r--scripts/genksyms/parse.c_shipped2
-rw-r--r--scripts/genksyms/parse.y2
-rwxr-xr-xscripts/get_maintainer.pl1371
-rw-r--r--scripts/gfp-translate9
-rwxr-xr-xscripts/headers.sh2
-rw-r--r--scripts/headers_install.pl7
-rw-r--r--scripts/kallsyms.c8
-rw-r--r--scripts/kconfig/.gitignore1
-rw-r--r--scripts/kconfig/Makefile180
-rw-r--r--scripts/kconfig/conf.c205
-rw-r--r--scripts/kconfig/confdata.c447
-rw-r--r--scripts/kconfig/expr.c48
-rw-r--r--scripts/kconfig/expr.h8
-rw-r--r--scripts/kconfig/gconf.c27
-rw-r--r--scripts/kconfig/gconf.glade1
-rw-r--r--scripts/kconfig/kxgettext.c15
-rw-r--r--scripts/kconfig/lex.zconf.c_shipped7
-rw-r--r--scripts/kconfig/lkc.h28
-rw-r--r--scripts/kconfig/lkc_proto.h4
-rw-r--r--scripts/kconfig/lxdialog/check-lxdialog.sh2
-rw-r--r--scripts/kconfig/lxdialog/checklist.c10
-rw-r--r--scripts/kconfig/mconf.c66
-rw-r--r--scripts/kconfig/menu.c70
-rw-r--r--scripts/kconfig/nconf.c497
-rw-r--r--scripts/kconfig/nconf.gui.c24
-rw-r--r--scripts/kconfig/nconf.h3
-rw-r--r--scripts/kconfig/qconf.cc274
-rw-r--r--scripts/kconfig/qconf.h93
-rw-r--r--scripts/kconfig/streamline_config.pl109
-rw-r--r--scripts/kconfig/symbol.c347
-rw-r--r--scripts/kconfig/util.c9
-rw-r--r--scripts/kconfig/zconf.gperf1
-rw-r--r--scripts/kconfig/zconf.hash.c_shipped122
-rw-r--r--scripts/kconfig/zconf.l7
-rw-r--r--scripts/kconfig/zconf.tab.c_shipped603
-rw-r--r--scripts/kconfig/zconf.y37
-rwxr-xr-xscripts/kernel-doc187
-rw-r--r--scripts/markup_oops.pl2
-rw-r--r--scripts/mkmakefile4
-rwxr-xr-xscripts/mkuboot.sh2
-rw-r--r--scripts/mod/file2alias.c63
-rw-r--r--scripts/mod/modpost.c188
-rw-r--r--scripts/mod/modpost.h43
-rwxr-xr-xscripts/namespace.pl147
-rw-r--r--scripts/package/Makefile39
-rwxr-xr-xscripts/package/mkspec2
-rw-r--r--scripts/recordmcount.c410
-rw-r--r--scripts/recordmcount.h443
-rwxr-xr-xscripts/recordmcount.pl48
-rw-r--r--scripts/selinux/genheaders/genheaders.c2
-rwxr-xr-xscripts/setlocalversion185
-rwxr-xr-xscripts/tags.sh4
97 files changed, 6998 insertions, 2184 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 52cab46ae35a..c5d5db54c009 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -6,5 +6,4 @@ kallsyms
pnmtologo
bin2c
unifdef
-binoffset
ihex2fw
diff --git a/scripts/Makefile b/scripts/Makefile
index 842dbc2d5aed..2e088109fbd5 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -11,6 +11,7 @@ hostprogs-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-$(CONFIG_LOGO) += pnmtologo
hostprogs-$(CONFIG_VT) += conmakehash
hostprogs-$(CONFIG_IKCONFIG) += bin2c
+hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
always := $(hostprogs-y) $(hostprogs-m)
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index e4deb73e9a84..4eb99ab34053 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -115,7 +115,10 @@ endif
# ---------------------------------------------------------------------------
# Default is built-in, unless we know otherwise
-modkern_cflags = $(if $(part-of-module), $(CFLAGS_MODULE), $(CFLAGS_KERNEL))
+modkern_cflags = \
+ $(if $(part-of-module), \
+ $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
+ $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL))
quiet_modtag := $(empty) $(empty)
$(real-objs-m) : part-of-module := y
@@ -156,14 +159,14 @@ $(obj)/%.i: $(src)/%.c FORCE
cmd_gensymtypes = \
$(CPP) -D__GENKSYMS__ $(c_flags) $< | \
- $(GENKSYMS) -T $@ -a $(ARCH) \
+ $(GENKSYMS) $(if $(1), -T $(2)) -a $(ARCH) \
$(if $(KBUILD_PRESERVE),-p) \
- $(if $(1),-r $(firstword $(wildcard $(@:.symtypes=.symref) /dev/null)))
+ -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
cmd_cc_symtypes_c = \
set -e; \
- $(call cmd_gensymtypes, true) >/dev/null; \
+ $(call cmd_gensymtypes,true,$@) >/dev/null; \
test -s $@ || rm -f $@
$(obj)/%.symtypes : $(src)/%.c FORCE
@@ -192,26 +195,42 @@ else
# the actual value of the checksum generated by genksyms
cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
-cmd_modversions = \
- if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
- $(call cmd_gensymtypes, $(KBUILD_SYMTYPES)) \
- > $(@D)/.tmp_$(@F:.o=.ver); \
- \
- $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
- -T $(@D)/.tmp_$(@F:.o=.ver); \
- rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
- else \
- mv -f $(@D)/.tmp_$(@F) $@; \
+cmd_modversions = \
+ if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
+ $(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
+ > $(@D)/.tmp_$(@F:.o=.ver); \
+ \
+ $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
+ -T $(@D)/.tmp_$(@F:.o=.ver); \
+ rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
+ else \
+ mv -f $(@D)/.tmp_$(@F) $@; \
fi;
endif
ifdef CONFIG_FTRACE_MCOUNT_RECORD
-cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
+ifdef BUILD_C_RECORDMCOUNT
+# Due to recursion, we must skip empty.o.
+# The empty.o file is created in the make process in order to determine
+# the target endianness and word size. It is made before all other C
+# files, including recordmcount.
+sub_cmd_record_mcount = \
+ if [ $(@) != "scripts/mod/empty.o" ]; then \
+ $(objtree)/scripts/recordmcount "$(@)"; \
+ fi;
+else
+sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
"$(if $(CONFIG_64BIT),64,32)" \
- "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
+ "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
+ "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
"$(if $(part-of-module),1,0)" "$(@)";
endif
+cmd_record_mcount = \
+ if [ "$(findstring -pg,$(_c_flags))" = "-pg" ]; then \
+ $(sub_cmd_record_mcount) \
+ fi;
+endif
define rule_cc_o_c
$(call echo-cmd,checksrc) $(cmd_checksrc) \
@@ -248,10 +267,10 @@ $(obj)/%.lst: $(src)/%.c FORCE
# Compile assembler sources (.S)
# ---------------------------------------------------------------------------
-modkern_aflags := $(AFLAGS_KERNEL)
+modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL)
-$(real-objs-m) : modkern_aflags := $(AFLAGS_MODULE)
-$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE)
+$(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
+$(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
quiet_cmd_as_s_S = CPP $(quiet_modtag) $@
cmd_as_s_S = $(CPP) $(a_flags) -o $@ $<
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 6f89fbb56256..686cb0d31c7c 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -45,6 +45,8 @@ __clean-files := $(extra-y) $(always) \
$(host-progs) \
$(hostprogs-y) $(hostprogs-m) $(hostprogs-)
+__clean-files := $(filter-out $(no-clean-files), $(__clean-files))
+
# as clean-files is given relative to the current directory, this adds
# a $(obj) prefix, except for absolute paths
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index 0fcd83838771..f89cb87f5c01 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -3,7 +3,6 @@
#
# header-y - list files to be installed. They are preprocessed
# to remove __KERNEL__ section of the file
-# unifdef-y - Same as header-y. Obsolete
# objhdr-y - Same as header-y but for generated files
#
# ==========================================================================
@@ -20,7 +19,7 @@ include scripts/Kbuild.include
install := $(INSTALL_HDR_PATH)/$(_dst)
-header-y := $(sort $(header-y) $(unifdef-y))
+header-y := $(sort $(header-y))
subdirs := $(patsubst %/,%,$(filter %/, $(header-y)))
header-y := $(filter-out %/, $(header-y))
diff --git a/scripts/Makefile.help b/scripts/Makefile.help
new file mode 100644
index 000000000000..d03608f5db04
--- /dev/null
+++ b/scripts/Makefile.help
@@ -0,0 +1,3 @@
+
+checker-help:
+ @echo ' coccicheck - Check with Coccinelle.'
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index f3ccdb1b302b..4c72c1189479 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -101,14 +101,6 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
modname_flags = $(if $(filter 1,$(words $(modname))),\
-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
-#hash values
-ifdef CONFIG_DYNAMIC_DEBUG
-debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
- -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
-else
-debug_flags =
-endif
-
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
$(ccflags-y) $(CFLAGS_$(basetarget).o)
_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
@@ -128,7 +120,9 @@ _c_flags += $(if $(patsubst n%,, \
endif
ifdef CONFIG_SYMBOL_PREFIX
-_cpp_flags += -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX))
+_sym_flags = -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX))
+_cpp_flags += $(_sym_flags)
+_a_flags += $(_sym_flags)
endif
@@ -152,8 +146,7 @@ endif
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__c_flags) $(modkern_cflags) \
- -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \
- $(debug_flags)
+ -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__a_flags) $(modkern_aflags)
@@ -245,3 +238,7 @@ quiet_cmd_lzo = LZO $@
cmd_lzo = (cat $(filter-out FORCE,$^) | \
lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
+
+# misc stuff
+# ---------------------------------------------------------------------------
+quote:="
diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin
index 102a276f6eea..1adb974e6950 100644
--- a/scripts/Makefile.modbuiltin
+++ b/scripts/Makefile.modbuiltin
@@ -14,6 +14,11 @@ __modbuiltin:
include scripts/Kbuild.include
+ifneq ($(KBUILD_SRC),)
+# Create output directory if not already present
+_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
+endif
+
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 8f14c81abbc7..7d22056582c1 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -30,7 +30,7 @@
# - 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 retrieved from the Module.symers file.
+# where the CRC of each module is retrieved from the Module.symvers file.
# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
# symbols in the final module linking stage
@@ -107,7 +107,7 @@ $(modules:.ko=.mod.c): __modpost ;
modname = $(notdir $(@:.mod.o=))
quiet_cmd_cc_o_c = CC $@
- cmd_cc_o_c = $(CC) $(c_flags) $(CFLAGS_MODULE) \
+ cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \
-c -o $@ $<
$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
@@ -117,8 +117,9 @@ targets += $(modules:.ko=.mod.o)
# Step 6), final link of the modules
quiet_cmd_ld_ko_o = LD [M] $@
- cmd_ld_ko_o = $(LD) -r $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \
- $(filter-out FORCE,$^)
+ cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \
+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+ -o $@ $(filter-out FORCE,$^)
$(modules): %.ko :%.o %.mod.o FORCE
$(call if_changed,ld_ko_o)
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index 09559951df12..4c324a1f1e0e 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -9,7 +9,7 @@
# fixdep: Used to generate dependency information during build process
# docproc: Used in Documentation/DocBook
-hostprogs-y := fixdep docproc hash
+hostprogs-y := fixdep docproc
always := $(hostprogs-y)
# fixdep is needed to compile other host programs
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c
index 79ab973fb43a..98dec87974d0 100644
--- a/scripts/basic/docproc.c
+++ b/scripts/basic/docproc.c
@@ -34,12 +34,14 @@
*
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <limits.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -54,6 +56,7 @@ typedef void FILEONLY(char * file);
FILEONLY *internalfunctions;
FILEONLY *externalfunctions;
FILEONLY *symbolsonly;
+FILEONLY *findall;
typedef void FILELINE(char * file, char * line);
FILELINE * singlefunctions;
@@ -65,12 +68,30 @@ FILELINE * docsection;
#define KERNELDOCPATH "scripts/"
#define KERNELDOC "kernel-doc"
#define DOCBOOK "-docbook"
+#define LIST "-list"
#define FUNCTION "-function"
#define NOFUNCTION "-nofunction"
#define NODOCSECTIONS "-no-doc-sections"
static char *srctree, *kernsrctree;
+static char **all_list = NULL;
+static int all_list_len = 0;
+
+static void consume_symbol(const char *sym)
+{
+ int i;
+
+ for (i = 0; i < all_list_len; i++) {
+ if (!all_list[i])
+ continue;
+ if (strcmp(sym, all_list[i]))
+ continue;
+ all_list[i] = NULL;
+ break;
+ }
+}
+
static void usage (void)
{
fprintf(stderr, "Usage: docproc {doc|depend} file\n");
@@ -248,6 +269,7 @@ static void docfunctions(char * filename, char * type)
struct symfile * sym = &symfilelist[i];
for (j=0; j < sym->symbolcnt; j++) {
vec[idx++] = type;
+ consume_symbol(sym->symbollist[j].name);
vec[idx++] = sym->symbollist[j].name;
}
}
@@ -287,6 +309,11 @@ static void singfunc(char * filename, char * line)
vec[idx++] = &line[i];
}
}
+ for (i = 0; i < idx; i++) {
+ if (strcmp(vec[i], FUNCTION))
+ continue;
+ consume_symbol(vec[i + 1]);
+ }
vec[idx++] = filename;
vec[idx] = NULL;
exec_kernel_doc(vec);
@@ -306,6 +333,13 @@ static void docsect(char *filename, char *line)
if (*s == '\n')
*s = '\0';
+ if (asprintf(&s, "DOC: %s", line) < 0) {
+ perror("asprintf");
+ exit(1);
+ }
+ consume_symbol(s);
+ free(s);
+
vec[0] = KERNELDOC;
vec[1] = DOCBOOK;
vec[2] = FUNCTION;
@@ -315,6 +349,84 @@ static void docsect(char *filename, char *line)
exec_kernel_doc(vec);
}
+static void find_all_symbols(char *filename)
+{
+ char *vec[4]; /* kerneldoc -list file NULL */
+ pid_t pid;
+ int ret, i, count, start;
+ char real_filename[PATH_MAX + 1];
+ int pipefd[2];
+ char *data, *str;
+ size_t data_len = 0;
+
+ vec[0] = KERNELDOC;
+ vec[1] = LIST;
+ vec[2] = filename;
+ vec[3] = NULL;
+
+ if (pipe(pipefd)) {
+ perror("pipe");
+ exit(1);
+ }
+
+ switch (pid=fork()) {
+ case -1:
+ perror("fork");
+ exit(1);
+ case 0:
+ close(pipefd[0]);
+ dup2(pipefd[1], 1);
+ memset(real_filename, 0, sizeof(real_filename));
+ strncat(real_filename, kernsrctree, PATH_MAX);
+ strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
+ PATH_MAX - strlen(real_filename));
+ execvp(real_filename, vec);
+ fprintf(stderr, "exec ");
+ perror(real_filename);
+ exit(1);
+ default:
+ close(pipefd[1]);
+ data = malloc(4096);
+ do {
+ while ((ret = read(pipefd[0],
+ data + data_len,
+ 4096)) > 0) {
+ data_len += ret;
+ data = realloc(data, data_len + 4096);
+ }
+ } while (ret == -EAGAIN);
+ if (ret != 0) {
+ perror("read");
+ exit(1);
+ }
+ waitpid(pid, &ret ,0);
+ }
+ if (WIFEXITED(ret))
+ exitstatus |= WEXITSTATUS(ret);
+ else
+ exitstatus = 0xff;
+
+ count = 0;
+ /* poor man's strtok, but with counting */
+ for (i = 0; i < data_len; i++) {
+ if (data[i] == '\n') {
+ count++;
+ data[i] = '\0';
+ }
+ }
+ start = all_list_len;
+ all_list_len += count;
+ all_list = realloc(all_list, sizeof(char *) * all_list_len);
+ str = data;
+ for (i = 0; i < data_len && start != all_list_len; i++) {
+ if (data[i] == '\0') {
+ all_list[start] = str;
+ str = data + i + 1;
+ start++;
+ }
+ }
+}
+
/*
* Parse file, calling action specific functions for:
* 1) Lines containing !E
@@ -322,7 +434,8 @@ static void docsect(char *filename, char *line)
* 3) Lines containing !D
* 4) Lines containing !F
* 5) Lines containing !P
- * 6) Default lines - lines not matching the above
+ * 6) Lines containing !C
+ * 7) Default lines - lines not matching the above
*/
static void parse_file(FILE *infile)
{
@@ -365,6 +478,12 @@ static void parse_file(FILE *infile)
s++;
docsection(line + 2, s);
break;
+ case 'C':
+ while (*s && !isspace(*s)) s++;
+ *s = '\0';
+ if (findall)
+ findall(line+2);
+ break;
default:
defaultline(line);
}
@@ -380,6 +499,7 @@ static void parse_file(FILE *infile)
int main(int argc, char *argv[])
{
FILE * infile;
+ int i;
srctree = getenv("SRCTREE");
if (!srctree)
@@ -415,6 +535,7 @@ int main(int argc, char *argv[])
symbolsonly = find_export_symbols;
singlefunctions = noaction2;
docsection = noaction2;
+ findall = find_all_symbols;
parse_file(infile);
/* Rewind to start from beginning of file again */
@@ -425,8 +546,16 @@ int main(int argc, char *argv[])
symbolsonly = printline;
singlefunctions = singfunc;
docsection = docsect;
+ findall = NULL;
parse_file(infile);
+
+ for (i = 0; i < all_list_len; i++) {
+ if (!all_list[i])
+ continue;
+ fprintf(stderr, "Warning: didn't use docs for %s\n",
+ all_list[i]);
+ }
}
else if (strcmp("depend", argv[1]) == 0)
{
@@ -439,6 +568,7 @@ int main(int argc, char *argv[])
symbolsonly = adddep;
singlefunctions = adddep2;
docsection = adddep2;
+ findall = adddep;
parse_file(infile);
printf("\n");
}
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index ea26b23de082..c9a16abacab4 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -138,38 +138,36 @@ static void print_cmdline(void)
printf("cmd_%s := %s\n\n", target, cmdline);
}
-char * str_config = NULL;
-int size_config = 0;
-int len_config = 0;
+struct item {
+ struct item *next;
+ unsigned int len;
+ unsigned int hash;
+ char name[0];
+};
-/*
- * Grow the configuration string to a desired length.
- * Usually the first growth is plenty.
- */
-static 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); }
- }
-}
+#define HASHSZ 256
+static struct item *hashtab[HASHSZ];
+static unsigned int strhash(const char *str, unsigned int sz)
+{
+ /* fnv32 hash */
+ unsigned int i, hash = 2166136261U;
+ for (i = 0; i < sz; i++)
+ hash = (hash ^ str[i]) * 0x01000193;
+ return hash;
+}
/*
* Lookup a value in the configuration string.
*/
-static int is_defined_config(const char * name, int len)
+static int is_defined_config(const char *name, int len, unsigned int hash)
{
- 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))
+ struct item *aux;
+
+ for (aux = hashtab[hash % HASHSZ]; aux; aux = aux->next) {
+ if (aux->hash == hash && aux->len == len &&
+ memcmp(aux->name, name, len) == 0)
return 1;
}
return 0;
@@ -178,13 +176,19 @@ static int is_defined_config(const char * name, int len)
/*
* Add a new value to the configuration string.
*/
-static void define_config(const char * name, int len)
+static void define_config(const char *name, int len, unsigned int hash)
{
- grow_config(len + 1);
+ struct item *aux = malloc(sizeof(*aux) + len);
- memcpy(str_config+len_config, name, len);
- len_config += len;
- str_config[len_config++] = '\n';
+ if (!aux) {
+ perror("fixdep:malloc");
+ exit(1);
+ }
+ memcpy(aux->name, name, len);
+ aux->len = len;
+ aux->hash = hash;
+ aux->next = hashtab[hash % HASHSZ];
+ hashtab[hash % HASHSZ] = aux;
}
/*
@@ -192,40 +196,49 @@ static void define_config(const char * name, int len)
*/
static void clear_config(void)
{
- len_config = 0;
- define_config("", 0);
+ struct item *aux, *next;
+ unsigned int i;
+
+ for (i = 0; i < HASHSZ; i++) {
+ for (aux = hashtab[i]; aux; aux = next) {
+ next = aux->next;
+ free(aux);
+ }
+ hashtab[i] = NULL;
+ }
}
/*
* Record the use of a CONFIG_* word.
*/
-static void use_config(char *m, int slen)
+static void use_config(const char *m, int slen)
{
- char s[PATH_MAX];
- char *p;
+ unsigned int hash = strhash(m, slen);
+ int c, i;
- if (is_defined_config(m, slen))
+ if (is_defined_config(m, slen, hash))
return;
- define_config(m, slen);
+ define_config(m, slen, hash);
- memcpy(s, m, slen); s[slen] = 0;
-
- for (p = s; p < s + slen; p++) {
- if (*p == '_')
- *p = '/';
+ printf(" $(wildcard include/config/");
+ for (i = 0; i < slen; i++) {
+ c = m[i];
+ if (c == '_')
+ c = '/';
else
- *p = tolower((int)*p);
+ c = tolower(c);
+ putchar(c);
}
- printf(" $(wildcard include/config/%s.h) \\\n", s);
+ printf(".h) \\\n");
}
-static void parse_config_file(char *map, size_t len)
+static void parse_config_file(const char *map, size_t len)
{
- int *end = (int *) (map + len);
+ const int *end = (const int *) (map + len);
/* start at +1, so that p can never be < map */
- int *m = (int *) map + 1;
- char *p, *q;
+ const int *m = (const int *) map + 1;
+ const char *p, *q;
for (; m < end; m++) {
if (*m == INT_CONF) { p = (char *) m ; goto conf; }
@@ -265,7 +278,7 @@ static int strrcmp(char *s, char *sub)
return memcmp(s + slen - sublen, sub, sublen);
}
-static void do_config_file(char *filename)
+static void do_config_file(const char *filename)
{
struct stat st;
int fd;
@@ -273,7 +286,7 @@ static void do_config_file(char *filename)
fd = open(filename, O_RDONLY);
if (fd < 0) {
- fprintf(stderr, "fixdep: ");
+ fprintf(stderr, "fixdep: error opening config file: ");
perror(filename);
exit(2);
}
@@ -344,11 +357,15 @@ static void print_deps(void)
fd = open(depfile, O_RDONLY);
if (fd < 0) {
- fprintf(stderr, "fixdep: ");
+ fprintf(stderr, "fixdep: error opening depfile: ");
perror(depfile);
exit(2);
}
- fstat(fd, &st);
+ if (fstat(fd, &st) < 0) {
+ fprintf(stderr, "fixdep: error fstat'ing depfile: ");
+ perror(depfile);
+ exit(2);
+ }
if (st.st_size == 0) {
fprintf(stderr,"fixdep: %s is empty\n",depfile);
close(fd);
diff --git a/scripts/basic/hash.c b/scripts/basic/hash.c
deleted file mode 100644
index 2ef5d3f666b8..000000000000
--- a/scripts/basic/hash.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define DYNAMIC_DEBUG_HASH_BITS 6
-
-static const char *program;
-
-static void usage(void)
-{
- printf("Usage: %s <djb2|r5> <modname>\n", program);
- exit(1);
-}
-
-/* djb2 hashing algorithm by Dan Bernstein. From:
- * http://www.cse.yorku.ca/~oz/hash.html
- */
-
-static unsigned int djb2_hash(char *str)
-{
- unsigned long hash = 5381;
- int c;
-
- c = *str;
- while (c) {
- hash = ((hash << 5) + hash) + c;
- c = *++str;
- }
- return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
-}
-
-static unsigned int r5_hash(char *str)
-{
- unsigned long hash = 0;
- int c;
-
- c = *str;
- while (c) {
- hash = (hash + (c << 4) + (c >> 4)) * 11;
- c = *++str;
- }
- return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
-}
-
-int main(int argc, char *argv[])
-{
- program = argv[0];
-
- if (argc != 3)
- usage();
- if (!strcmp(argv[1], "djb2"))
- printf("%d\n", djb2_hash(argv[2]));
- else if (!strcmp(argv[1], "r5"))
- printf("%d\n", r5_hash(argv[2]));
- else
- usage();
- exit(0);
-}
-
diff --git a/scripts/binoffset.c b/scripts/binoffset.c
deleted file mode 100644
index 1a2e39b8e3e5..000000000000
--- a/scripts/binoffset.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/***************************************************************************
- * binoffset.c
- * (C) 2002 Randy Dunlap <rdunlap@xenotime.net>
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-# binoffset.c:
-# - searches a (binary) file for a specified (binary) pattern
-# - returns the offset of the located pattern or ~0 if not found
-# - exits with exit status 0 normally or non-0 if pattern is not found
-# or any other error occurs.
-
-****************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#define VERSION "0.1"
-#define BUF_SIZE (16 * 1024)
-#define PAT_SIZE 100
-
-char *progname;
-char *inputname;
-int inputfd;
-unsigned int bix; /* buf index */
-unsigned char patterns [PAT_SIZE] = {0}; /* byte-sized pattern array */
-int pat_len; /* actual number of pattern bytes */
-unsigned char *madr; /* mmap address */
-size_t filesize;
-int num_matches = 0;
-off_t firstloc = 0;
-
-void usage (void)
-{
- fprintf (stderr, "%s ver. %s\n", progname, VERSION);
- fprintf (stderr, "usage: %s filename pattern_bytes\n",
- progname);
- fprintf (stderr, " [prints location of pattern_bytes in file]\n");
- exit (1);
-}
-
-void get_pattern (int pat_count, char *pats [])
-{
- int ix, err, tmp;
-
-#ifdef DEBUG
- fprintf (stderr,"get_pattern: count = %d\n", pat_count);
- for (ix = 0; ix < pat_count; ix++)
- fprintf (stderr, " pat # %d: [%s]\n", ix, pats[ix]);
-#endif
-
- for (ix = 0; ix < pat_count; ix++) {
- tmp = 0;
- err = sscanf (pats[ix], "%5i", &tmp);
- if (err != 1 || tmp > 0xff) {
- fprintf (stderr, "pattern or value error in pattern # %d [%s]\n",
- ix, pats[ix]);
- usage ();
- }
- patterns [ix] = tmp;
- }
- pat_len = pat_count;
-}
-
-void search_pattern (void)
-{
- for (bix = 0; bix < filesize; bix++) {
- if (madr[bix] == patterns[0]) {
- if (memcmp (&madr[bix], patterns, pat_len) == 0) {
- if (num_matches == 0)
- firstloc = bix;
- num_matches++;
- }
- }
- }
-}
-
-#ifdef NOTDEF
-size_t get_filesize (int fd)
-{
- off_t end_off = lseek (fd, 0, SEEK_END);
- lseek (fd, 0, SEEK_SET);
- return (size_t) end_off;
-}
-#endif
-
-size_t get_filesize (int fd)
-{
- int err;
- struct stat stat;
-
- err = fstat (fd, &stat);
- fprintf (stderr, "filesize: %ld\n", err < 0 ? (long)err : stat.st_size);
- if (err < 0)
- return err;
- return (size_t) stat.st_size;
-}
-
-int main (int argc, char *argv [])
-{
- progname = argv[0];
-
- if (argc < 3)
- usage ();
-
- get_pattern (argc - 2, argv + 2);
-
- inputname = argv[1];
-
- inputfd = open (inputname, O_RDONLY);
- if (inputfd == -1) {
- fprintf (stderr, "%s: cannot open '%s'\n",
- progname, inputname);
- exit (3);
- }
-
- filesize = get_filesize (inputfd);
-
- madr = mmap (0, filesize, PROT_READ, MAP_PRIVATE, inputfd, 0);
- if (madr == MAP_FAILED) {
- fprintf (stderr, "mmap error = %d\n", errno);
- close (inputfd);
- exit (4);
- }
-
- search_pattern ();
-
- if (munmap (madr, filesize))
- fprintf (stderr, "munmap error = %d\n", errno);
-
- if (close (inputfd))
- fprintf (stderr, "%s: error %d closing '%s'\n",
- progname, errno, inputname);
-
- fprintf (stderr, "number of pattern matches = %d\n", num_matches);
- if (num_matches == 0)
- firstloc = ~0;
- printf ("%ld\n", firstloc);
- fprintf (stderr, "%ld\n", firstloc);
-
- exit (num_matches ? 0 : 2);
-}
-
-/* end binoffset.c */
diff --git a/scripts/checkkconfigsymbols.sh b/scripts/checkkconfigsymbols.sh
index 46be3c5a62b7..2ca49bb31efc 100755
--- a/scripts/checkkconfigsymbols.sh
+++ b/scripts/checkkconfigsymbols.sh
@@ -14,7 +14,7 @@ find $paths -name '*.[chS]' -o -name 'Makefile' -o -name 'Makefile*[^~]'| while
do
# Output the bare Kconfig variable and the filename; the _MODULE part at
# the end is not removed here (would need perl an not-hungry regexp for that).
- sed -ne 's!^.*\<\(UML_\)\?CONFIG_\([0-9A-Z_]\+\).*!\2 '$i'!p' < $i
+ sed -ne 's!^.*\<\(UML_\)\?CONFIG_\([0-9A-Za-z_]\+\).*!\2 '$i'!p' < $i
done | \
# Smart "sort|uniq" implemented in awk and tuned to collect the names of all
# files which use a given symbol
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 3257d3d96767..e3c7fc0dca38 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2,7 +2,7 @@
# (c) 2001, Dave Jones. (the file handling bit)
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
-# (c) 2008,2009, Andy Whitcroft <apw@canonical.com>
+# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
# Licensed under the terms of the GNU GPL License version 2
use strict;
@@ -10,7 +10,7 @@ use strict;
my $P = $0;
$P =~ s@.*/@@g;
-my $V = '0.30';
+my $V = '0.31';
use Getopt::Long qw(:config no_auto_abbrev);
@@ -103,6 +103,8 @@ for my $key (keys %debug) {
die "$@" if ($@);
}
+my $rpt_cleaners = 0;
+
if ($terse) {
$emacs = 1;
$quiet++;
@@ -145,11 +147,28 @@ our $Sparse = qr{
__kprobes|
__ref
}x;
+
+# Notes to $Attribute:
+# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
our $Attribute = qr{
const|
+ __percpu|
+ __nocast|
+ __safe|
+ __bitwise__|
+ __packed__|
+ __packed2__|
+ __naked|
+ __maybe_unused|
+ __always_unused|
+ __noreturn|
+ __used|
+ __cold|
+ __noclone|
+ __deprecated|
__read_mostly|
__kprobes|
- __(?:mem|cpu|dev|)(?:initdata|init)|
+ __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
____cacheline_aligned|
____cacheline_aligned_in_smp|
____cacheline_internodealigned_in_smp|
@@ -189,6 +208,14 @@ our $typeTypedefs = qr{(?x:
atomic_t
)};
+our $logFunctions = qr{(?x:
+ printk|
+ pr_(debug|dbg|vdbg|devel|info|warning|err|notice|alert|crit|emerg|cont)|
+ (dev|netdev|netif)_(printk|dbg|vdbg|info|warn|err|notice|alert|crit|emerg|WARN)|
+ WARN|
+ panic
+)};
+
our @typeList = (
qr{void},
qr{(?:unsigned\s+)?char},
@@ -213,6 +240,12 @@ our @modifierList = (
qr{fastcall},
);
+our $allowed_asm_includes = qr{(?x:
+ irq|
+ memory
+)};
+# memory.h: ARM has a custom one
+
sub build_types {
my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
@@ -541,6 +574,9 @@ sub ctx_statement_block {
$type = ($level != 0)? '{' : '';
if ($level == 0) {
+ if (substr($blk, $off + 1, 1) eq ';') {
+ $off++;
+ }
last;
}
}
@@ -655,15 +691,15 @@ sub ctx_block_get {
$blk .= $rawlines[$line];
# Handle nested #if/#else.
- if ($rawlines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
+ if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
push(@stack, $level);
- } elsif ($rawlines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
+ } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
$level = $stack[$#stack - 1];
- } elsif ($rawlines[$line] =~ /^.\s*#\s*endif\b/) {
+ } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
$level = pop(@stack);
}
- foreach my $c (split(//, $rawlines[$line])) {
+ foreach my $c (split(//, $lines[$line])) {
##print "C<$c>L<$level><$open$close>O<$off>\n";
if ($off > 0) {
$off--;
@@ -823,7 +859,12 @@ sub annotate_values {
$av_preprocessor = 0;
}
- } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) {
+ } elsif ($cur =~ /^(\(\s*$Type\s*)\)/) {
+ print "CAST($1)\n" if ($dbg_values > 1);
+ push(@av_paren_type, $type);
+ $type = 'C';
+
+ } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
print "DECLARE($1)\n" if ($dbg_values > 1);
$type = 'T';
@@ -1288,7 +1329,11 @@ sub process {
$here = "#$realline: " if ($file);
# extract the filename as it passes
- if ($line=~/^\+\+\+\s+(\S+)/) {
+ if ($line =~ /^diff --git.*?(\S+)$/) {
+ $realfile = $1;
+ $realfile =~ s@^([^/]*)/@@;
+
+ } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
$realfile = $1;
$realfile =~ s@^([^/]*)/@@;
@@ -1312,6 +1357,14 @@ sub process {
$cnt_lines++ if ($realcnt != 0);
+# Check for incorrect file permissions
+ if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
+ my $permhere = $here . "FILE: $realfile\n";
+ if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
+ ERROR("do not set execute permissions for source files\n" . $permhere);
+ }
+ }
+
#check the patch for a signoff:
if ($line =~ /^\s*signed-off-by:/i) {
# This is a signoff, if ugly, so do not double report.
@@ -1369,6 +1422,38 @@ sub process {
} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
ERROR("trailing whitespace\n" . $herevet);
+ $rpt_cleaners = 1;
+ }
+
+# check for Kconfig help text having a real description
+# Only applies when adding the entry originally, after that we do not have
+# sufficient context to determine whether it is indeed long enough.
+ if ($realfile =~ /Kconfig/ &&
+ $line =~ /\+\s*(?:---)?help(?:---)?$/) {
+ my $length = 0;
+ my $cnt = $realcnt;
+ my $ln = $linenr + 1;
+ my $f;
+ my $is_end = 0;
+ while ($cnt > 0 && defined $lines[$ln - 1]) {
+ $f = $lines[$ln - 1];
+ $cnt-- if ($lines[$ln - 1] !~ /^-/);
+ $is_end = $lines[$ln - 1] =~ /^\+/;
+ $ln++;
+
+ next if ($f =~ /^-/);
+ $f =~ s/^.//;
+ $f =~ s/#.*//;
+ $f =~ s/^\s+//;
+ next if ($f =~ /^$/);
+ if ($f =~ /^\s*config\s/) {
+ $is_end = 1;
+ last;
+ }
+ $length++;
+ }
+ WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
+ #print "is_end<$is_end> length<$length>\n";
}
# check we are in a valid source file if not then ignore this hunk
@@ -1377,12 +1462,18 @@ sub process {
#80 column limit
if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
$rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
- $line !~ /^\+\s*printk\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&
+ !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ ||
+ $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
$length > 80)
{
WARN("line over 80 characters\n" . $herecurr);
}
+# check for spaces before a quoted newline
+ if ($rawline =~ /^.*\".*\s\\n/) {
+ WARN("unnecessary whitespace before a quoted newline\n" . $herecurr);
+ }
+
# check for adding lines without a newline.
if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
WARN("adding a line without newline at end of file\n" . $herecurr);
@@ -1409,6 +1500,23 @@ sub process {
$rawline =~ /^\+\s* \s*/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
ERROR("code indent should use tabs where possible\n" . $herevet);
+ $rpt_cleaners = 1;
+ }
+
+# check for space before tabs.
+ if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ WARN("please, no space before tabs\n" . $herevet);
+ }
+
+# check for spaces at the beginning of a line.
+# Exceptions:
+# 1) within comments
+# 2) indented preprocessor commands
+# 3) hanging labels
+ if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ WARN("please, no spaces at the start of a line\n" . $herevet);
}
# check we are in a valid C source file if not then ignore this hunk
@@ -1544,7 +1652,7 @@ sub process {
if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
ERROR("that open brace { should be on the previous line\n" .
- "$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+ "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
}
if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
$ctx =~ /\)\s*\;\s*$/ &&
@@ -1553,7 +1661,7 @@ sub process {
my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
if ($nindent > $indent) {
WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
- "$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+ "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
}
}
}
@@ -1714,8 +1822,17 @@ sub process {
!defined $suppress_export{$realline_next} &&
($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
$lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+ # Handle definitions which produce identifiers with
+ # a prefix:
+ # XXX(foo);
+ # EXPORT_SYMBOL(something_foo);
my $name = $1;
- if ($stat !~ /(?:
+ if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ &&
+ $name =~ /^${Ident}_$2/) {
+#print "FOO C name<$name>\n";
+ $suppress_export{$realline_next} = 1;
+
+ } elsif ($stat !~ /(?:
\n.}\s*$|
^.DEFINE_$Ident\(\Q$name\E\)|
^.DECLARE_$Ident\(\Q$name\E\)|
@@ -1741,9 +1858,9 @@ sub process {
WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
}
-# check for external initialisers.
+# check for global initialisers.
if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
- ERROR("do not initialise externals to 0 or NULL\n" .
+ ERROR("do not initialise globals to 0 or NULL\n" .
$herecurr);
}
# check for static initialisers.
@@ -1752,6 +1869,23 @@ sub process {
$herecurr);
}
+# check for static const char * arrays.
+ if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
+ WARN("static const char * array should probably be static const char * const\n" .
+ $herecurr);
+ }
+
+# check for static char foo[] = "bar" declarations.
+ if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
+ WARN("static char array declaration should probably be static const char\n" .
+ $herecurr);
+ }
+
+# check for declarations of struct pci_device_id
+ if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) {
+ WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr);
+ }
+
# check for new typedefs, only function parameters and sparse annotations
# make sense.
if ($line =~ /\btypedef\s/ &&
@@ -1845,6 +1979,11 @@ sub process {
ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
}
+# missing space after union, struct or enum definition
+ if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
+ WARN("missing space after $1 definition\n" . $herecurr);
+ }
+
# check for spacing round square brackets; allowed:
# 1. with a type on the left -- int [] a;
# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
@@ -2122,21 +2261,29 @@ sub process {
my $value = $2;
# Flatten any parentheses
- $value =~ s/\)\(/\) \(/g;
+ $value =~ s/\(/ \(/g;
+ $value =~ s/\)/\) /g;
while ($value =~ s/\[[^\{\}]*\]/1/ ||
$value !~ /(?:$Ident|-?$Constant)\s*
$Compare\s*
(?:$Ident|-?$Constant)/x &&
$value =~ s/\([^\(\)]*\)/1/) {
}
-
- if ($value =~ /^(?:$Ident|-?$Constant)$/) {
+#print "value<$value>\n";
+ if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
ERROR("return is not a function, parentheses are not required\n" . $herecurr);
} elsif ($spacing !~ /\s+/) {
ERROR("space required before the open parenthesis '('\n" . $herecurr);
}
}
+# Return of what appears to be an errno should normally be -'ve
+ if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
+ my $name = $1;
+ if ($name ne 'EOF' && $name ne 'ERROR') {
+ WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
+ }
+ }
# Need a space before open parenthesis after if, while etc
if ($line=~/\b(if|while|for|switch)\(/) {
@@ -2182,8 +2329,10 @@ sub process {
# Find out how long the conditional actually is.
my @newlines = ($c =~ /\n/gs);
my $cond_lines = 1 + $#newlines;
+ my $stat_real = '';
- my $stat_real = raw_line($linenr, $cond_lines);
+ $stat_real = raw_line($linenr, $cond_lines)
+ . "\n" if ($cond_lines);
if (defined($stat_real) && $cond_lines > 1) {
$stat_real = "[...]\n$stat_real";
}
@@ -2269,7 +2418,7 @@ sub process {
my $checkfile = "include/linux/$file";
if (-f "$root/$checkfile" &&
$realfile ne $checkfile &&
- $1 ne 'irq')
+ $1 !~ /$allowed_asm_includes/)
{
if ($realfile =~ m{^arch/}) {
CHK("Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
@@ -2348,11 +2497,13 @@ sub process {
DECLARE_PER_CPU|
DEFINE_PER_CPU|
__typeof__\(|
+ union|
+ struct|
\.$Ident\s*=\s*|
^\"|\"$
}x;
- #print "REST<$rest> dstat<$dstat>\n";
- if ($rest ne '') {
+ #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
+ if ($rest ne '' && $rest ne ',') {
if ($rest !~ /while\s*\(/ &&
$dstat !~ /$exceptions/)
{
@@ -2529,6 +2680,21 @@ sub process {
}
}
+# prefer usleep_range over udelay
+ if ($line =~ /\budelay\s*\(\s*(\w+)\s*\)/) {
+ # ignore udelay's < 10, however
+ if (! (($1 =~ /(\d+)/) && ($1 < 10)) ) {
+ CHK("usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line);
+ }
+ }
+
+# warn about unexpectedly long msleep's
+ if ($line =~ /\bmsleep\s*\((\d+)\);/) {
+ if ($1 < 20) {
+ WARN("msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line);
+ }
+ }
+
# warn about #ifdefs in C files
# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
# print "#ifdef in C files should be avoided\n";
@@ -2560,6 +2726,11 @@ sub process {
CHK("architecture specific defines should be avoided\n" . $herecurr);
}
+# Check that the storage class is at the beginning of a declaration
+ if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) {
+ WARN("storage class should be at the beginning of the declaration\n" . $herecurr)
+ }
+
# check the location of the inline attribute, that it is between
# storage class and type.
if ($line =~ /\b$Type\s+$Inline\b/ ||
@@ -2572,6 +2743,11 @@ sub process {
WARN("plain inline is preferred over $1\n" . $herecurr);
}
+# check for sizeof(&)
+ if ($line =~ /\bsizeof\s*\(\s*\&/) {
+ WARN("sizeof(& should be avoided\n" . $herecurr);
+ }
+
# check for new externs in .c files.
if ($realfile =~ /\.c$/ && defined $stat &&
$stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
@@ -2618,13 +2794,10 @@ sub process {
WARN("__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr);
}
-# check for semaphores used as mutexes
- if ($line =~ /^.\s*(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
- WARN("mutexes are preferred for single holder semaphores\n" . $herecurr);
- }
-# check for semaphores used as mutexes
- if ($line =~ /^.\s*init_MUTEX_LOCKED\s*\(/) {
+# check for semaphores initialized locked
+ if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
WARN("consider using a completion\n" . $herecurr);
+
}
# recommend strict_strto* over simple_strto*
if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
@@ -2634,9 +2807,46 @@ sub process {
if ($line =~ /^.\s*__initcall\s*\(/) {
WARN("please use device_initcall() instead of __initcall()\n" . $herecurr);
}
-# check for struct file_operations, ensure they are const.
+# check for various ops structs, ensure they are const.
+ my $struct_ops = qr{acpi_dock_ops|
+ address_space_operations|
+ backlight_ops|
+ block_device_operations|
+ dentry_operations|
+ dev_pm_ops|
+ dma_map_ops|
+ extent_io_ops|
+ file_lock_operations|
+ file_operations|
+ hv_ops|
+ ide_dma_ops|
+ intel_dvo_dev_ops|
+ item_operations|
+ iwl_ops|
+ kgdb_arch|
+ kgdb_io|
+ kset_uevent_ops|
+ lock_manager_operations|
+ microcode_ops|
+ mtrr_ops|
+ neigh_ops|
+ nlmsvc_binding|
+ pci_raw_ops|
+ pipe_buf_operations|
+ platform_hibernation_ops|
+ platform_suspend_ops|
+ proto_ops|
+ rpc_pipe_ops|
+ seq_operations|
+ snd_ac97_build_ops|
+ soc_pcmcia_socket_ops|
+ stacktrace_ops|
+ sysfs_ops|
+ tty_operations|
+ usb_mon_operations|
+ wd_ops}x;
if ($line !~ /\bconst\b/ &&
- $line =~ /\bstruct\s+(file_operations|seq_operations)\b/) {
+ $line =~ /\bstruct\s+($struct_ops)\b/) {
WARN("struct $1 should normally be const\n" .
$herecurr);
}
@@ -2672,6 +2882,16 @@ sub process {
WARN("use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
}
}
+
+# check for lockdep_set_novalidate_class
+ if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
+ $line =~ /__lockdep_no_validate__\s*\)/ ) {
+ if ($realfile !~ m@^kernel/lockdep@ &&
+ $realfile !~ m@^include/linux/lockdep@ &&
+ $realfile !~ m@^drivers/base/core@) {
+ ERROR("lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
+ }
+ }
}
# If we have no input at all, then there is nothing to report on
@@ -2708,6 +2928,15 @@ sub process {
print "\n" if ($quiet == 0);
}
+ if ($quiet == 0) {
+ # If there were whitespace errors which cleanpatch can fix
+ # then suggest that.
+ if ($rpt_cleaners) {
+ print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
+ print " scripts/cleanfile\n\n";
+ }
+ }
+
if ($clean == 1 && $quiet == 0) {
print "$vname has no obvious style problems and is ready for submission.\n"
}
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index 66ad375612f2..3ab316e52313 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -6,7 +6,7 @@
# and listed below so they are ignored.
#
# Usage:
-# syscallchk gcc gcc-options
+# checksyscalls.sh gcc gcc-options
#
ignore_list() {
@@ -183,7 +183,6 @@ cat << EOF
#define __IGNORE_ustat /* statfs */
#define __IGNORE_utime /* utimes */
#define __IGNORE_vfork /* clone */
-#define __IGNORE_wait4 /* waitid */
/* sync_file_range had a stupid ABI. Allow sync_file_range2 instead */
#ifdef __NR_sync_file_range2
@@ -205,5 +204,5 @@ sed -n -e '/^\#define/ s/[^_]*__NR_\([^[:space:]]*\).*/\
\#endif/p' $1
}
-(ignore_list && syscall_list ${srctree}/arch/x86/include/asm/unistd_32.h) | \
+(ignore_list && syscall_list $(dirname $0)/../arch/x86/include/asm/unistd_32.h) | \
$* -E -x c - > /dev/null
diff --git a/scripts/coccicheck b/scripts/coccicheck
new file mode 100755
index 000000000000..1bb1a1bd2daa
--- /dev/null
+++ b/scripts/coccicheck
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+SPATCH="`which ${SPATCH:=spatch}`"
+
+if [ "$C" = "1" -o "$C" = "2" ]; then
+ ONLINE=1
+
+# This requires Coccinelle >= 0.2.3
+# FLAGS="-ignore_unknown_options -very_quiet"
+# OPTIONS=$*
+
+# Workaround for Coccinelle < 0.2.3
+ FLAGS="-I $srctree/include -very_quiet"
+ shift $(( $# - 1 ))
+ OPTIONS=$1
+else
+ ONLINE=0
+ FLAGS="-very_quiet"
+ OPTIONS="-dir $srctree"
+fi
+
+if [ ! -x "$SPATCH" ]; then
+ echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/'
+ exit 1
+fi
+
+if [ "$MODE" = "" ] ; then
+ if [ "$ONLINE" = "0" ] ; then
+ echo 'You have not explicitly specified the mode to use. Using default "chain" mode.'
+ echo 'All available modes will be tried (in that order): patch, report, context, org'
+ echo 'You can specify the mode with "make coccicheck MODE=<mode>"'
+ fi
+ MODE="chain"
+elif [ "$MODE" = "report" -o "$MODE" = "org" ] ; then
+ FLAGS="$FLAGS -no_show_diff"
+fi
+
+if [ "$ONLINE" = "0" ] ; then
+ echo ''
+ echo 'Please check for false positives in the output before submitting a patch.'
+ echo 'When using "patch" mode, carefully review the patch before submitting it.'
+ echo ''
+fi
+
+coccinelle () {
+ COCCI="$1"
+
+ OPT=`grep "Option" $COCCI | cut -d':' -f2`
+
+# The option '-parse_cocci' can be used to syntactically check the SmPL files.
+#
+# $SPATCH -D $MODE $FLAGS -parse_cocci $COCCI $OPT > /dev/null
+
+ if [ "$ONLINE" = "0" ] ; then
+
+ FILE=`echo $COCCI | sed "s|$srctree/||"`
+
+ echo "Processing `basename $COCCI`"
+ echo "with option(s) \"$OPT\""
+ echo ''
+ echo 'Message example to submit a patch:'
+
+ sed -ne 's|^///||p' $COCCI
+
+ if [ "$MODE" = "patch" ] ; then
+ echo ' The semantic patch that makes this change is available'
+ elif [ "$MODE" = "report" ] ; then
+ echo ' The semantic patch that makes this report is available'
+ elif [ "$MODE" = "context" ] ; then
+ echo ' The semantic patch that spots this code is available'
+ elif [ "$MODE" = "org" ] ; then
+ echo ' The semantic patch that makes this Org report is available'
+ else
+ echo ' The semantic patch that makes this output is available'
+ fi
+ echo " in $FILE."
+ echo ''
+ echo ' More information about semantic patching is available at'
+ echo ' http://coccinelle.lip6.fr/'
+ echo ''
+
+ if [ "`sed -ne 's|^//#||p' $COCCI`" ] ; then
+ echo 'Semantic patch information:'
+ sed -ne 's|^//#||p' $COCCI
+ echo ''
+ fi
+ fi
+
+ if [ "$MODE" = "chain" ] ; then
+ $SPATCH -D patch $FLAGS -sp_file $COCCI $OPT $OPTIONS || \
+ $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \
+ $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || \
+ $SPATCH -D org $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1
+ else
+ $SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1
+ fi
+
+}
+
+if [ "$COCCI" = "" ] ; then
+ for f in `find $srctree/scripts/coccinelle/ -name '*.cocci' -type f | sort`; do
+ coccinelle $f
+ done
+else
+ coccinelle $COCCI
+fi
diff --git a/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci b/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci
new file mode 100644
index 000000000000..7d4771d449c3
--- /dev/null
+++ b/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci
@@ -0,0 +1,67 @@
+///
+/// Casting (void *) value returned by kmalloc is useless
+/// as mentioned in Documentation/CodingStyle, Chap 14.
+///
+// Confidence: High
+// Copyright: 2009,2010 Nicolas Palix, DIKU. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Options: -no_includes -include_headers
+//
+// Keywords: kmalloc, kzalloc, kcalloc
+// Version min: < 2.6.12 kmalloc
+// Version min: < 2.6.12 kcalloc
+// Version min: 2.6.14 kzalloc
+//
+
+virtual context
+virtual patch
+virtual org
+virtual report
+
+//----------------------------------------------------------
+// For context mode
+//----------------------------------------------------------
+
+@depends on context@
+type T;
+@@
+
+* (T *)
+ \(kmalloc\|kzalloc\|kcalloc\)(...)
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+type T;
+@@
+
+- (T *)
+ \(kmalloc\|kzalloc\|kcalloc\)(...)
+
+//----------------------------------------------------------
+// For org and report mode
+//----------------------------------------------------------
+
+@r depends on org || report@
+type T;
+position p;
+@@
+
+ (T@p *)\(kmalloc\|kzalloc\|kcalloc\)(...)
+
+@script:python depends on org@
+p << r.p;
+t << r.T;
+@@
+
+coccilib.org.print_safe_todo(p[0], t)
+
+@script:python depends on report@
+p << r.p;
+t << r.T;
+@@
+
+msg="WARNING: casting value returned by k[cmz]alloc to (%s *) is useless." % (t)
+coccilib.report.print_report(p[0], msg)
diff --git a/scripts/coccinelle/api/alloc/kzalloc-simple.cocci b/scripts/coccinelle/api/alloc/kzalloc-simple.cocci
new file mode 100644
index 000000000000..046b9b16f8f9
--- /dev/null
+++ b/scripts/coccinelle/api/alloc/kzalloc-simple.cocci
@@ -0,0 +1,86 @@
+///
+/// Use kzalloc rather than kmalloc followed by memset with 0
+///
+/// This considers some simple cases that are common and easy to validate
+/// Note in particular that there are no ...s in the rule, so all of the
+/// matched code has to be contiguous
+///
+// Confidence: High
+// Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2009-2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/rules/kzalloc.html
+// Options: -no_includes -include_headers
+//
+// Keywords: kmalloc, kzalloc
+// Version min: < 2.6.12 kmalloc
+// Version min: 2.6.14 kzalloc
+//
+
+virtual context
+virtual patch
+virtual org
+virtual report
+
+//----------------------------------------------------------
+// For context mode
+//----------------------------------------------------------
+
+@depends on context@
+type T, T2;
+expression x;
+expression E1,E2;
+statement S;
+@@
+
+* x = (T)kmalloc(E1,E2);
+ if ((x==NULL) || ...) S
+* memset((T2)x,0,E1);
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+type T, T2;
+expression x;
+expression E1,E2;
+statement S;
+@@
+
+- x = (T)kmalloc(E1,E2);
++ x = kzalloc(E1,E2);
+ if ((x==NULL) || ...) S
+- memset((T2)x,0,E1);
+
+//----------------------------------------------------------
+// For org mode
+//----------------------------------------------------------
+
+@r depends on org || report@
+type T, T2;
+expression x;
+expression E1,E2;
+statement S;
+position p;
+@@
+
+ x = (T)kmalloc@p(E1,E2);
+ if ((x==NULL) || ...) S
+ memset((T2)x,0,E1);
+
+@script:python depends on org@
+p << r.p;
+x << r.x;
+@@
+
+msg="%s" % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+coccilib.org.print_todo(p[0], msg_safe)
+
+@script:python depends on report@
+p << r.p;
+x << r.x;
+@@
+
+msg="WARNING: kzalloc should be used for %s, instead of kmalloc/memset" % (x)
+coccilib.report.print_report(p[0], msg)
diff --git a/scripts/coccinelle/api/err_cast.cocci b/scripts/coccinelle/api/err_cast.cocci
new file mode 100644
index 000000000000..2ce115000af6
--- /dev/null
+++ b/scripts/coccinelle/api/err_cast.cocci
@@ -0,0 +1,56 @@
+///
+/// Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(...))
+///
+// Confidence: High
+// Copyright: (C) 2009, 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2009, 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Options:
+//
+// Keywords: ERR_PTR, PTR_ERR, ERR_CAST
+// Version min: 2.6.25
+//
+
+virtual context
+virtual patch
+virtual org
+virtual report
+
+
+@ depends on context && !patch && !org && !report@
+expression x;
+@@
+
+* ERR_PTR(PTR_ERR(x))
+
+@ depends on !context && patch && !org && !report @
+expression x;
+@@
+
+- ERR_PTR(PTR_ERR(x))
++ ERR_CAST(x)
+
+@r depends on !context && !patch && (org || report)@
+expression x;
+position p;
+@@
+
+ ERR_PTR@p(PTR_ERR(x))
+
+@script:python depends on org@
+p << r.p;
+x << r.x;
+@@
+
+msg="WARNING ERR_CAST can be used with %s" % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+coccilib.org.print_todo(p[0], msg_safe)
+
+@script:python depends on report@
+p << r.p;
+x << r.x;
+@@
+
+msg="WARNING: ERR_CAST can be used with %s" % (x)
+coccilib.report.print_report(p[0], msg)
diff --git a/scripts/coccinelle/api/kstrdup.cocci b/scripts/coccinelle/api/kstrdup.cocci
new file mode 100644
index 000000000000..e0805ad08d39
--- /dev/null
+++ b/scripts/coccinelle/api/kstrdup.cocci
@@ -0,0 +1,39 @@
+/// Use kstrdup rather than duplicating its implementation
+///
+// Confidence: High
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+
+@@
+expression from,to;
+expression flag,E1,E2;
+statement S;
+@@
+
+- to = kmalloc(strlen(from) + 1,flag);
++ to = kstrdup(from, flag);
+ ... when != \(from = E1 \| to = E1 \)
+ if (to==NULL || ...) S
+ ... when != \(from = E2 \| to = E2 \)
+- strcpy(to, from);
+
+@@
+expression x,from,to;
+expression flag,E1,E2,E3;
+statement S;
+@@
+
+- x = strlen(from) + 1;
+ ... when != \( x = E1 \| from = E1 \)
+- to = \(kmalloc\|kzalloc\)(x,flag);
++ to = kstrdup(from, flag);
+ ... when != \(x = E2 \| from = E2 \| to = E2 \)
+ if (to==NULL || ...) S
+ ... when != \(x = E3 \| from = E3 \| to = E3 \)
+- memcpy(to, from, x);
diff --git a/scripts/coccinelle/api/memdup.cocci b/scripts/coccinelle/api/memdup.cocci
new file mode 100644
index 000000000000..b5d722077dc1
--- /dev/null
+++ b/scripts/coccinelle/api/memdup.cocci
@@ -0,0 +1,40 @@
+/// Use kmemdup rather than duplicating its implementation
+///
+// Confidence: High
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+
+@r1@
+expression from,to;
+expression flag;
+position p;
+@@
+
+ to = \(kmalloc@p\|kzalloc@p\)(strlen(from) + 1,flag);
+
+@r2@
+expression x,from,to;
+expression flag,E1;
+position p;
+@@
+
+ x = strlen(from) + 1;
+ ... when != \( x = E1 \| from = E1 \)
+ to = \(kmalloc@p\|kzalloc@p\)(x,flag);
+
+@@
+expression from,to,size,flag;
+position p != {r1.p,r2.p};
+statement S;
+@@
+
+- to = \(kmalloc@p\|kzalloc@p\)(size,flag);
++ to = kmemdup(from,size,flag);
+ if (to==NULL || ...) S
+- memcpy(to, from, size);
diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci
new file mode 100644
index 000000000000..72ce012e878a
--- /dev/null
+++ b/scripts/coccinelle/api/memdup_user.cocci
@@ -0,0 +1,35 @@
+/// Use kmemdup_user rather than duplicating its implementation
+/// This is a little bit restricted to reduce false positives
+///
+// Confidence: High
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+
+@@
+expression from,to,size,flag;
+position p;
+identifier l1,l2;
+@@
+
+- to = \(kmalloc@p\|kzalloc@p\)(size,flag);
++ to = memdup_user(from,size);
+ if (
+- to==NULL
++ IS_ERR(to)
+ || ...) {
+ <+... when != goto l1;
+- -ENOMEM
++ PTR_ERR(to)
+ ...+>
+ }
+- if (copy_from_user(to, from, size) != 0) {
+- <+... when != goto l2;
+- -EFAULT
+- ...+>
+- }
diff --git a/scripts/coccinelle/api/resource_size.cocci b/scripts/coccinelle/api/resource_size.cocci
new file mode 100644
index 000000000000..1935a58b39d9
--- /dev/null
+++ b/scripts/coccinelle/api/resource_size.cocci
@@ -0,0 +1,93 @@
+///
+/// Use resource_size function on resource object
+/// instead of explicit computation.
+///
+// Confidence: High
+// Copyright: (C) 2009, 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2009, 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Options:
+//
+// Keywords: resource_size
+// Version min: 2.6.27 resource_size
+//
+
+virtual context
+virtual patch
+virtual org
+virtual report
+
+//----------------------------------------------------------
+// For context mode
+//----------------------------------------------------------
+
+@r_context depends on context && !patch && !org@
+struct resource *res;
+@@
+
+* (res->end - res->start) + 1
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@r_patch depends on !context && patch && !org@
+struct resource *res;
+@@
+
+- (res->end - res->start) + 1
++ resource_size(res)
+
+//----------------------------------------------------------
+// For org mode
+//----------------------------------------------------------
+
+
+@r_org depends on !context && !patch && (org || report)@
+struct resource *res;
+position p;
+@@
+
+ (res->end@p - res->start) + 1
+
+@rbad_org depends on !context && !patch && (org || report)@
+struct resource *res;
+position p != r_org.p;
+@@
+
+ res->end@p - res->start
+
+@script:python depends on org@
+p << r_org.p;
+x << r_org.res;
+@@
+
+msg="ERROR with %s" % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+coccilib.org.print_todo(p[0], msg_safe)
+
+@script:python depends on report@
+p << r_org.p;
+x << r_org.res;
+@@
+
+msg="ERROR: Missing resource_size with %s" % (x)
+coccilib.report.print_report(p[0], msg)
+
+@script:python depends on org@
+p << rbad_org.p;
+x << rbad_org.res;
+@@
+
+msg="WARNING with %s" % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+coccilib.org.print_todo(p[0], msg_safe)
+
+@script:python depends on report@
+p << rbad_org.p;
+x << rbad_org.res;
+@@
+
+msg="WARNING: Suspicious code. resource_size is maybe missing with %s" % (x)
+coccilib.report.print_report(p[0], msg)
diff --git a/scripts/coccinelle/free/kfree.cocci b/scripts/coccinelle/free/kfree.cocci
new file mode 100644
index 000000000000..f9f79d9245ee
--- /dev/null
+++ b/scripts/coccinelle/free/kfree.cocci
@@ -0,0 +1,117 @@
+/// Find a use after free.
+//# Values of variables may imply that some
+//# execution paths are not possible, resulting in false positives.
+//# Another source of false positives are macros such as
+//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual org
+virtual report
+
+@free@
+expression E;
+position p1;
+@@
+
+kfree@p1(E)
+
+@print expression@
+constant char *c;
+expression free.E,E2;
+type T;
+position p;
+identifier f;
+@@
+
+(
+ f(...,c,...,(T)E@p,...)
+|
+ E@p == E2
+|
+ E@p != E2
+|
+ !E@p
+|
+ E@p || ...
+)
+
+@sz@
+expression free.E;
+position p;
+@@
+
+ sizeof(<+...E@p...+>)
+
+@loop exists@
+expression E;
+identifier l;
+position ok;
+@@
+
+while (1) { ...
+ kfree@ok(E)
+ ... when != break;
+ when != goto l;
+ when forall
+}
+
+@r exists@
+expression free.E, subE<=free.E, E2;
+expression E1;
+iterator iter;
+statement S;
+position free.p1!=loop.ok,p2!={print.p,sz.p};
+@@
+
+kfree@p1(E,...)
+...
+(
+ iter(...,subE,...) S // no use
+|
+ list_remove_head(E1,subE,...)
+|
+ subE = E2
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+ BUG(...)
+|
+ BUG_ON(...)
+|
+ return_VALUE(...)
+|
+ return_ACPI_STATUS(...)
+|
+ E@p2 // bad use
+)
+
+@script:python depends on org@
+p1 << free.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("kfree",p1)
+cocci.print_secs("ref",p2)
+
+@script:python depends on report@
+p1 << free.p1;
+p2 << r.p2;
+@@
+
+msg = "reference preceded by free on line %s" % (p1[0].line)
+coccilib.report.print_report(p2[0],msg)
diff --git a/scripts/coccinelle/iterators/fen.cocci b/scripts/coccinelle/iterators/fen.cocci
new file mode 100644
index 000000000000..77bc108c3f59
--- /dev/null
+++ b/scripts/coccinelle/iterators/fen.cocci
@@ -0,0 +1,64 @@
+/// These iterators only exit normally when the loop cursor is NULL, so there
+/// is no point to call of_node_put on the final value.
+///
+// Confidence: High
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+
+@@
+iterator name for_each_node_by_name;
+expression np,E;
+identifier l;
+@@
+
+for_each_node_by_name(np,...) {
+ ... when != break;
+ when != goto l;
+}
+... when != np = E
+- of_node_put(np);
+
+@@
+iterator name for_each_node_by_type;
+expression np,E;
+identifier l;
+@@
+
+for_each_node_by_type(np,...) {
+ ... when != break;
+ when != goto l;
+}
+... when != np = E
+- of_node_put(np);
+
+@@
+iterator name for_each_compatible_node;
+expression np,E;
+identifier l;
+@@
+
+for_each_compatible_node(np,...) {
+ ... when != break;
+ when != goto l;
+}
+... when != np = E
+- of_node_put(np);
+
+@@
+iterator name for_each_matching_node;
+expression np,E;
+identifier l;
+@@
+
+for_each_matching_node(np,...) {
+ ... when != break;
+ when != goto l;
+}
+... when != np = E
+- of_node_put(np);
diff --git a/scripts/coccinelle/iterators/itnull.cocci b/scripts/coccinelle/iterators/itnull.cocci
new file mode 100644
index 000000000000..baa4297a4ed1
--- /dev/null
+++ b/scripts/coccinelle/iterators/itnull.cocci
@@ -0,0 +1,58 @@
+/// Many iterators have the property that the first argument is always bound
+/// to a real list element, never NULL. False positives arise for some
+/// iterators that do not have this property, or in cases when the loop
+/// cursor is reassigned. The latter should only happen when the matched
+/// code is on the way to a loop exit (break, goto, or return).
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+
+@@
+iterator I;
+expression x,E,E1,E2;
+statement S,S1,S2;
+@@
+
+I(x,...) { <...
+(
+- if (x == NULL && ...) S
+|
+- if (x != NULL || ...)
+ S
+|
+- (x == NULL) ||
+ E
+|
+- (x != NULL) &&
+ E
+|
+- (x == NULL && ...) ? E1 :
+ E2
+|
+- (x != NULL || ...) ?
+ E1
+- : E2
+|
+- if (x == NULL && ...) S1 else
+ S2
+|
+- if (x != NULL || ...)
+ S1
+- else S2
+|
++ BAD(
+ x == NULL
++ )
+|
++ BAD(
+ x != NULL
++ )
+)
+ ...> } \ No newline at end of file
diff --git a/scripts/coccinelle/iterators/list_entry_update.cocci b/scripts/coccinelle/iterators/list_entry_update.cocci
new file mode 100644
index 000000000000..b2967475679b
--- /dev/null
+++ b/scripts/coccinelle/iterators/list_entry_update.cocci
@@ -0,0 +1,62 @@
+/// list_for_each_entry uses its first argument to get from one element of
+/// the list to the next, so it is usually not a good idea to reassign it.
+/// The first rule finds such a reassignment and the second rule checks
+/// that there is a path from the reassignment back to the top of the loop.
+///
+// Confidence: High
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual context
+virtual org
+virtual report
+
+@r@
+iterator name list_for_each_entry;
+expression x,E;
+position p1,p2;
+@@
+
+list_for_each_entry@p1(x,...) { <... x =@p2 E ...> }
+
+@depends on context && !org && !report@
+expression x,E;
+position r.p1,r.p2;
+statement S;
+@@
+
+*x =@p2 E
+...
+list_for_each_entry@p1(x,...) S
+
+// ------------------------------------------------------------------------
+
+@back depends on (org || report) && !context exists@
+expression x,E;
+position r.p1,r.p2;
+statement S;
+@@
+
+x =@p2 E
+...
+list_for_each_entry@p1(x,...) S
+
+@script:python depends on back && org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("iterator",p1)
+cocci.print_secs("update",p2)
+
+@script:python depends on back && report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "iterator with update on line %s" % (p2[0].line)
+coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/coccinelle/locks/call_kern.cocci b/scripts/coccinelle/locks/call_kern.cocci
new file mode 100644
index 000000000000..00af5344a68f
--- /dev/null
+++ b/scripts/coccinelle/locks/call_kern.cocci
@@ -0,0 +1,74 @@
+/// Find functions that refer to GFP_KERNEL but are called with locks held.
+/// The proposed change of converting the GFP_KERNEL is not necessarily the
+/// correct one. It may be desired to unlock the lock, or to not call the
+/// function under the lock in the first place.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+
+@gfp exists@
+identifier fn;
+position p;
+@@
+
+fn(...) {
+ ... when != read_unlock_irq(...)
+ when != write_unlock_irq(...)
+ when != read_unlock_irqrestore(...)
+ when != write_unlock_irqrestore(...)
+ when != spin_unlock(...)
+ when != spin_unlock_irq(...)
+ when != spin_unlock_irqrestore(...)
+ when != local_irq_enable(...)
+ when any
+ GFP_KERNEL@p
+ ... when any
+}
+
+@locked@
+identifier gfp.fn;
+@@
+
+(
+read_lock_irq
+|
+write_lock_irq
+|
+read_lock_irqsave
+|
+write_lock_irqsave
+|
+spin_lock
+|
+spin_trylock
+|
+spin_lock_irq
+|
+spin_lock_irqsave
+|
+local_irq_disable
+)
+ (...)
+... when != read_unlock_irq(...)
+ when != write_unlock_irq(...)
+ when != read_unlock_irqrestore(...)
+ when != write_unlock_irqrestore(...)
+ when != spin_unlock(...)
+ when != spin_unlock_irq(...)
+ when != spin_unlock_irqrestore(...)
+ when != local_irq_enable(...)
+fn(...)
+
+@depends on locked@
+position gfp.p;
+@@
+
+- GFP_KERNEL@p
++ GFP_ATOMIC
diff --git a/scripts/coccinelle/locks/double_lock.cocci b/scripts/coccinelle/locks/double_lock.cocci
new file mode 100644
index 000000000000..63b24e682fad
--- /dev/null
+++ b/scripts/coccinelle/locks/double_lock.cocci
@@ -0,0 +1,92 @@
+/// Find double locks. False positives may occur when some paths cannot
+/// occur at execution, due to the values of variables, and when there is
+/// an intervening function call that releases the lock.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual org
+virtual report
+
+@locked@
+position p1;
+expression E1;
+position p;
+@@
+
+(
+mutex_lock@p1
+|
+mutex_trylock@p1
+|
+spin_lock@p1
+|
+spin_trylock@p1
+|
+read_lock@p1
+|
+read_trylock@p1
+|
+write_lock@p1
+|
+write_trylock@p1
+) (E1@p,...);
+
+@balanced@
+position p1 != locked.p1;
+position locked.p;
+identifier lock,unlock;
+expression x <= locked.E1;
+expression E,locked.E1;
+expression E2;
+@@
+
+if (E) {
+ <+... when != E1
+ lock(E1@p,...)
+ ...+>
+}
+... when != E1
+ when != \(x = E2\|&x\)
+ when forall
+if (E) {
+ <+... when != E1
+ unlock@p1(E1,...)
+ ...+>
+}
+
+@r depends on !balanced exists@
+expression x <= locked.E1;
+expression locked.E1;
+expression E2;
+identifier lock;
+position locked.p,p1,p2;
+@@
+
+lock@p1 (E1@p,...);
+... when != E1
+ when != \(x = E2\|&x\)
+lock@p2 (E1,...);
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+lock << r.lock;
+@@
+
+cocci.print_main(lock,p1)
+cocci.print_secs("second lock",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+lock << r.lock;
+@@
+
+msg = "second lock on line %s" % (p2[0].line)
+coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/coccinelle/locks/flags.cocci b/scripts/coccinelle/locks/flags.cocci
new file mode 100644
index 000000000000..b4344d838097
--- /dev/null
+++ b/scripts/coccinelle/locks/flags.cocci
@@ -0,0 +1,80 @@
+/// Find nested lock+irqsave functions that use the same flags variables
+///
+// Confidence: High
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual context
+virtual org
+virtual report
+
+@r@
+expression lock1,lock2,flags;
+position p1,p2;
+@@
+
+(
+spin_lock_irqsave@p1(lock1,flags)
+|
+read_lock_irqsave@p1(lock1,flags)
+|
+write_lock_irqsave@p1(lock1,flags)
+)
+... when != flags
+(
+spin_lock_irqsave(lock1,flags)
+|
+read_lock_irqsave(lock1,flags)
+|
+write_lock_irqsave(lock1,flags)
+|
+spin_lock_irqsave@p2(lock2,flags)
+|
+read_lock_irqsave@p2(lock2,flags)
+|
+write_lock_irqsave@p2(lock2,flags)
+)
+
+@d@
+expression f <= r.flags;
+expression lock1,lock2,flags;
+position r.p1, r.p2;
+@@
+
+(
+*spin_lock_irqsave@p1(lock1,flags)
+|
+*read_lock_irqsave@p1(lock1,flags)
+|
+*write_lock_irqsave@p1(lock1,flags)
+)
+... when != f
+(
+*spin_lock_irqsave@p2(lock2,flags)
+|
+*read_lock_irqsave@p2(lock2,flags)
+|
+*write_lock_irqsave@p2(lock2,flags)
+)
+
+// ----------------------------------------------------------------------
+
+@script:python depends on d && org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("original lock",p1)
+cocci.print_secs("nested lock+irqsave that reuses flags",p2)
+
+@script:python depends on d && report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg="ERROR: nested lock+irqsave that reuses flags from %s." % (p1[0].line)
+coccilib.report.print_report(p2[0], msg)
diff --git a/scripts/coccinelle/locks/mini_lock.cocci b/scripts/coccinelle/locks/mini_lock.cocci
new file mode 100644
index 000000000000..7641a2925434
--- /dev/null
+++ b/scripts/coccinelle/locks/mini_lock.cocci
@@ -0,0 +1,95 @@
+/// Find missing unlocks. This semantic match considers the specific case
+/// where the unlock is missing from an if branch, and there is a lock
+/// before the if and an unlock after the if. False positives are due to
+/// cases where the if branch represents a case where the function is
+/// supposed to exit with the lock held, or where there is some preceding
+/// function call that releases the lock.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual org
+virtual report
+
+@prelocked@
+position p1,p;
+expression E1;
+@@
+
+(
+mutex_lock@p1
+|
+mutex_trylock@p1
+|
+spin_lock@p1
+|
+spin_trylock@p1
+|
+read_lock@p1
+|
+read_trylock@p1
+|
+write_lock@p1
+|
+write_trylock@p1
+|
+read_lock_irq@p1
+|
+write_lock_irq@p1
+|
+read_lock_irqsave@p1
+|
+write_lock_irqsave@p1
+|
+spin_lock_irq@p1
+|
+spin_lock_irqsave@p1
+) (E1@p,...);
+
+@looped@
+position r;
+@@
+
+for(...;...;...) { <+... return@r ...; ...+> }
+
+@err@
+expression E1;
+position prelocked.p;
+position up != prelocked.p1;
+position r!=looped.r;
+identifier lock,unlock;
+@@
+
+lock(E1@p,...);
+<+... when != E1
+if (...) {
+ ... when != E1
+ return@r ...;
+}
+...+>
+unlock@up(E1,...);
+
+@script:python depends on org@
+p << prelocked.p1;
+lock << err.lock;
+unlock << err.unlock;
+p2 << err.r;
+@@
+
+cocci.print_main(lock,p)
+cocci.print_secs(unlock,p2)
+
+@script:python depends on report@
+p << prelocked.p1;
+lock << err.lock;
+unlock << err.unlock;
+p2 << err.r;
+@@
+
+msg = "preceding lock on line %s" % (p[0].line)
+coccilib.report.print_report(p2[0],msg)
diff --git a/scripts/coccinelle/misc/doubleinit.cocci b/scripts/coccinelle/misc/doubleinit.cocci
new file mode 100644
index 000000000000..55d7dc19dfe0
--- /dev/null
+++ b/scripts/coccinelle/misc/doubleinit.cocci
@@ -0,0 +1,53 @@
+/// Find duplicate field initializations. This has a high rate of false
+/// positives due to #ifdefs, which Coccinelle is not aware of in a structure
+/// initialization.
+///
+// Confidence: Low
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual org
+virtual report
+
+@r@
+identifier I, s, fld;
+position p0,p;
+expression E;
+@@
+
+struct I s =@p0 { ... .fld@p = E, ...};
+
+@s@
+identifier I, s, r.fld;
+position r.p0,p;
+expression E;
+@@
+
+struct I s =@p0 { ... .fld@p = E, ...};
+
+@script:python depends on org@
+p0 << r.p0;
+fld << r.fld;
+ps << s.p;
+pr << r.p;
+@@
+
+if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
+ cocci.print_main(fld,p0)
+ cocci.print_secs("s",ps)
+ cocci.print_secs("r",pr)
+
+@script:python depends on report@
+p0 << r.p0;
+fld << r.fld;
+ps << s.p;
+pr << r.p;
+@@
+
+if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
+ msg = "%s: first occurrence %s, second occurrence %s" % (fld,ps[0].line,pr[0].line)
+ coccilib.report.print_report(p0[0],msg)
diff --git a/scripts/coccinelle/misc/ifcol.cocci b/scripts/coccinelle/misc/ifcol.cocci
new file mode 100644
index 000000000000..b7ed91dbeb95
--- /dev/null
+++ b/scripts/coccinelle/misc/ifcol.cocci
@@ -0,0 +1,48 @@
+/// Find confusingly indented code in or after an if. An if branch should
+/// be indented. The code following an if should not be indented.
+/// Sometimes, code after an if that is indented is actually intended to be
+/// part of the if branch.
+///
+/// This has a high rate of false positives, because Coccinelle's column
+/// calculation does not distinguish between spaces and tabs, so code that
+/// is not visually aligned may be considered to be in the same column.
+///
+// Confidence: Low
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual org
+virtual report
+
+@r disable braces4@
+position p1,p2;
+statement S1,S2;
+@@
+
+(
+if (...) { ... }
+|
+if (...) S1@p1 S2@p2
+)
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+if (p1[0].column == p2[0].column):
+ cocci.print_main("branch",p1)
+ cocci.print_secs("after",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+if (p1[0].column == p2[0].column):
+ msg = "code aligned with following code on line %s" % (p2[0].line)
+ coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/coccinelle/null/deref_null.cocci b/scripts/coccinelle/null/deref_null.cocci
new file mode 100644
index 000000000000..9969d76d0f4b
--- /dev/null
+++ b/scripts/coccinelle/null/deref_null.cocci
@@ -0,0 +1,293 @@
+///
+/// A variable is dereference under a NULL test.
+/// Even though it is know to be NULL.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments: -I ... -all_includes can give more complete results
+// Options:
+
+virtual context
+virtual patch
+virtual org
+virtual report
+
+@initialize:python depends on !context && patch && !org && !report@
+
+import sys
+print >> sys.stderr, "This semantic patch does not support the 'patch' mode."
+
+@depends on patch@
+@@
+
+this_rule_should_never_matches();
+
+@ifm depends on !patch@
+expression *E;
+statement S1,S2;
+position p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...) S1 else S2
+
+// The following two rules are separate, because both can match a single
+// expression in different ways
+@pr1 depends on !patch expression@
+expression *ifm.E;
+identifier f;
+position p1;
+@@
+
+ (E != NULL && ...) ? <+...E->f@p1...+> : ...
+
+@pr2 depends on !patch expression@
+expression *ifm.E;
+identifier f;
+position p2;
+@@
+
+(
+ (E != NULL) && ... && <+...E->f@p2...+>
+|
+ (E == NULL) || ... || <+...E->f@p2...+>
+|
+ sizeof(<+...E->f@p2...+>)
+)
+
+// For org and report modes
+
+@r depends on !context && !patch && (org || report) exists@
+expression subE <= ifm.E;
+expression *ifm.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr1.p1,pr2.p2};
+position ifm.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+ ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+ E->f@p // bad use
+)
+ ... when any
+ return ...;
+}
+else S3
+
+@script:python depends on !context && !patch && !org && report@
+p << r.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+coccilib.report.print_report(p[0], msg)
+cocci.include_match(False)
+
+@script:python depends on !context && !patch && org && !report@
+p << r.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+cocci.print_main(msg_safe,p)
+cocci.include_match(False)
+
+@s depends on !context && !patch && (org || report) exists@
+expression subE <= ifm.E;
+expression *ifm.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr1.p1,pr2.p2};
+position ifm.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+ ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+ E->f@p // bad use
+)
+ ... when any
+}
+else S3
+
+@script:python depends on !context && !patch && !org && report@
+p << s.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+coccilib.report.print_report(p[0], msg)
+
+@script:python depends on !context && !patch && org && !report@
+p << s.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+cocci.print_main(msg_safe,p)
+
+// For context mode
+
+@depends on context && !patch && !org && !report exists@
+expression subE <= ifm.E;
+expression *ifm.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr1.p1,pr2.p2};
+position ifm.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+ ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+* E->f@p // bad use
+)
+ ... when any
+ return ...;
+}
+else S3
+
+// The following three rules are duplicates of ifm, pr1 and pr2 respectively.
+// It is need because the previous rule as already made a "change".
+
+@ifm1 depends on !patch@
+expression *E;
+statement S1,S2;
+position p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...) S1 else S2
+
+@pr11 depends on !patch expression@
+expression *ifm1.E;
+identifier f;
+position p1;
+@@
+
+ (E != NULL && ...) ? <+...E->f@p1...+> : ...
+
+@pr12 depends on !patch expression@
+expression *ifm1.E;
+identifier f;
+position p2;
+@@
+
+(
+ (E != NULL) && ... && <+...E->f@p2...+>
+|
+ (E == NULL) || ... || <+...E->f@p2...+>
+|
+ sizeof(<+...E->f@p2...+>)
+)
+
+@depends on context && !patch && !org && !report exists@
+expression subE <= ifm1.E;
+expression *ifm1.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr11.p1,pr12.p2};
+position ifm1.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+ ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+* E->f@p // bad use
+)
+ ... when any
+}
+else S3
diff --git a/scripts/coccinelle/null/eno.cocci b/scripts/coccinelle/null/eno.cocci
new file mode 100644
index 000000000000..4c9c52b9c413
--- /dev/null
+++ b/scripts/coccinelle/null/eno.cocci
@@ -0,0 +1,20 @@
+/// The various basic memory allocation functions don't return ERR_PTR
+///
+// Confidence: High
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+
+@@
+expression x,E;
+@@
+
+x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...)
+... when != x = E
+- IS_ERR(x)
++ !x
diff --git a/scripts/coccinelle/null/kmerr.cocci b/scripts/coccinelle/null/kmerr.cocci
new file mode 100644
index 000000000000..949bf656c64c
--- /dev/null
+++ b/scripts/coccinelle/null/kmerr.cocci
@@ -0,0 +1,72 @@
+/// This semantic patch looks for kmalloc etc that are not followed by a
+/// NULL check. It only gives a report in the case where there is some
+/// error handling code later in the function, which may be helpful
+/// in determining what the error handling code for the call to kmalloc etc
+/// should be.
+///
+// Confidence: High
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual context
+virtual org
+virtual report
+
+@withtest@
+expression x;
+position p;
+identifier f,fld;
+@@
+
+x@p = f(...);
+... when != x->fld
+\(x == NULL \| x != NULL\)
+
+@fixed depends on context && !org && !report@
+expression x,x1;
+position p1 != withtest.p;
+statement S;
+position any withtest.p;
+identifier f;
+@@
+
+*x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...);
+...
+*x1@p = f(...);
+if (!x1) S
+
+// ------------------------------------------------------------------------
+
+@rfixed depends on (org || report) && !context exists@
+expression x,x1;
+position p1 != withtest.p;
+position p2;
+statement S;
+position any withtest.p;
+identifier f;
+@@
+
+x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...);
+...
+x1@p = f@p2(...);
+if (!x1) S
+
+@script:python depends on org@
+p1 << rfixed.p1;
+p2 << rfixed.p2;
+@@
+
+cocci.print_main("alloc call",p1)
+cocci.print_secs("possible model",p2)
+
+@script:python depends on report@
+p1 << rfixed.p1;
+p2 << rfixed.p2;
+@@
+
+msg = "alloc with no test, possible model on line %s" % (p2[0].line)
+coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/coccinelle/tests/doublebitand.cocci b/scripts/coccinelle/tests/doublebitand.cocci
new file mode 100644
index 000000000000..9ba73d05a77e
--- /dev/null
+++ b/scripts/coccinelle/tests/doublebitand.cocci
@@ -0,0 +1,54 @@
+/// Find bit operations that include the same argument more than once
+//# One source of false positives is when the argument performs a side
+//# effect. Another source of false positives is when a neutral value
+//# such as 0 for | is used to indicate no information, to maintain the
+//# same structure as other similar expressions
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual context
+virtual org
+virtual report
+
+@r expression@
+expression E;
+position p;
+@@
+
+(
+* E@p
+ & ... & E
+|
+* E@p
+ | ... | E
+|
+* E@p
+ & ... & !E
+|
+* E@p
+ | ... | !E
+|
+* !E@p
+ & ... & E
+|
+* !E@p
+ | ... | E
+)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("duplicated argument to & or |",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0],"duplicated argument to & or |")
diff --git a/scripts/coccinelle/tests/doubletest.cocci b/scripts/coccinelle/tests/doubletest.cocci
new file mode 100644
index 000000000000..13a2c0e8a4bf
--- /dev/null
+++ b/scripts/coccinelle/tests/doubletest.cocci
@@ -0,0 +1,40 @@
+/// Find &&/|| operations that include the same argument more than once
+//# A common source of false positives is when the argument performs a side
+//# effect.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual context
+virtual org
+virtual report
+
+@r expression@
+expression E;
+position p;
+@@
+
+(
+* E@p
+ || ... || E
+|
+* E@p
+ && ... && E
+)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("duplicated argument to && or ||",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0],"duplicated argument to && or ||")
diff --git a/scripts/decodecode b/scripts/decodecode
index 8b30cc36744f..18ba881c3415 100755
--- a/scripts/decodecode
+++ b/scripts/decodecode
@@ -40,7 +40,7 @@ echo $code
code=`echo $code | sed -e 's/.*Code: //'`
width=`expr index "$code" ' '`
-width=$[($width-1)/2]
+width=$((($width-1)/2))
case $width in
1) type=byte ;;
2) type=2byte ;;
@@ -48,10 +48,10 @@ case $width in
esac
disas() {
- ${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s &> /dev/null
+ ${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s > /dev/null 2>&1
- if [ "$ARCH" == "arm" ]; then
- if [ $width == 2 ]; then
+ if [ "$ARCH" = "arm" ]; then
+ if [ $width -eq 2 ]; then
OBJDUMPFLAGS="-M force-thumb"
fi
@@ -59,7 +59,7 @@ disas() {
fi
${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $1.o | \
- grep -v "/tmp\|Disassembly\|\.text\|^$" &> $1.dis
+ grep -v "/tmp\|Disassembly\|\.text\|^$" > $1.dis 2>&1
}
marker=`expr index "$code" "\<"`
diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c
index 766b2694d935..8fe1bdf239f0 100644
--- a/scripts/dtc/fstree.c
+++ b/scripts/dtc/fstree.c
@@ -77,6 +77,7 @@ static struct node *read_fstree(const char *dirname)
free(tmpnam);
}
+ closedir(d);
return tree;
}
diff --git a/scripts/extract-ikconfig b/scripts/extract-ikconfig
index de233ff43c1c..1512c0a755ac 100755
--- a/scripts/extract-ikconfig
+++ b/scripts/extract-ikconfig
@@ -1,92 +1,66 @@
#!/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"
-test -e $binoffset || cc -o $binoffset ./scripts/binoffset.c || exit 1
-
-IKCFG_ST="0x49 0x4b 0x43 0x46 0x47 0x5f 0x53 0x54"
-IKCFG_ED="0x49 0x4b 0x43 0x46 0x47 0x5f 0x45 0x44"
-dump_config() {
- 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`
- [ "$?" != "0" ] && end="-1"
- if [ "$end" -eq "-1" ]; then
- return
- fi
-
- start=`expr $start + 8`
- size=`expr $end - $start`
-
- dd if="$file" ibs=1 skip="$start" count="$size" 2>/dev/null | zcat
-
- clean_up
- exit 0
-}
-
-
-usage()
+# ----------------------------------------------------------------------
+# extract-ikconfig - Extract the .config file from a kernel image
+#
+# This will only work when the kernel was compiled with CONFIG_IKCONFIG.
+#
+# The obscure use of the "tr" filter is to work around older versions of
+# "grep" that report the byte offset of the line instead of the pattern.
+#
+# (c) 2009,2010 Dick Streefland <dick@streefland.net>
+# Licensed under the terms of the GNU General Public License.
+# ----------------------------------------------------------------------
+
+cf1='IKCFG_ST\037\213\010'
+cf2='0123456789'
+
+dump_config()
{
- echo " usage: extract-ikconfig [b]zImage_filename"
+ if pos=`tr "$cf1\n$cf2" "\n$cf2=" < "$1" | grep -abo "^$cf2"`
+ then
+ pos=${pos%%:*}
+ tail -c+$(($pos+8)) "$1" | zcat > $tmp1 2> /dev/null
+ if [ $? != 1 ]
+ then # exit status must be 0 or 2 (trailing garbage warning)
+ cat $tmp1
+ exit 0
+ fi
+ fi
}
-clean_up()
+try_decompress()
{
- if [ "$TMPFILE" != "" ]; then
- rm -f $TMPFILE
- fi
+ for pos in `tr "$1\n$2" "\n$2=" < "$img" | grep -abo "^$2"`
+ do
+ pos=${pos%%:*}
+ tail -c+$pos "$img" | $3 > $tmp2 2> /dev/null
+ dump_config $tmp2
+ done
}
-if [ $# -lt 1 ]
+# Check invocation:
+me=${0##*/}
+img=$1
+if [ $# -ne 1 -o ! -s "$img" ]
then
- usage
- exit 1
+ echo "Usage: $me <kernel-image>" >&2
+ exit 2
fi
-TMPFILE=`mktemp -t ikconfig-XXXXXX` || exit 1
-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"
-
-ELFHDR="0x7f 0x45 0x4c 0x46"
+# Prepare temp files:
+tmp1=/tmp/ikconfig$$.1
+tmp2=/tmp/ikconfig$$.2
+trap "rm -f $tmp1 $tmp2" 0
-# 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"
-
-# check if this is simply an ELF file
-else
- off=`$binoffset "$image" $ELFHDR 2>/dev/null`
- [ "$?" != "0" ] && off="-1"
- if [ "$off" -eq "0" ]; then
- dump_config "$image"
- fi
-fi
+# Initial attempt for uncompressed images or objects:
+dump_config "$img"
-echo "ERROR: Unable to extract kernel configuration information."
-echo " This kernel image may not have the config info."
+# That didn't work, so retry after decompression.
+try_decompress '\037\213\010' xy gunzip
+try_decompress 'BZh' xy bunzip2
+try_decompress '\135\0\0\0' xxx unlzma
+try_decompress '\211\114\132' xy 'lzop -d'
-clean_up
+# Bail out:
+echo "$me: Cannot find kernel config." >&2
exit 1
diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh
new file mode 100644
index 000000000000..520d16b1ffaf
--- /dev/null
+++ b/scripts/gcc-goto.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Test for gcc 'asm goto' suport
+# Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
+
+echo "int main(void) { entry: asm goto (\"\"::::entry); return 0; }" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index f3b5c05ced40..5958fffb2114 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -243,6 +243,7 @@ case "$arg" in
echo "$output_file" | grep -q "\.gz$" && compr="gzip -9 -f"
echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"
echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"
+ echo "$output_file" | grep -q "\.lzo$" && compr="lzop -9 -f"
echo "$output_file" | grep -q "\.cpio$" && compr="cat"
shift
;;
diff --git a/scripts/genksyms/parse.c_shipped b/scripts/genksyms/parse.c_shipped
index eaee44e66a43..809b949e495b 100644
--- a/scripts/genksyms/parse.c_shipped
+++ b/scripts/genksyms/parse.c_shipped
@@ -160,7 +160,7 @@
#include <assert.h>
-#include <malloc.h>
+#include <stdlib.h>
#include "genksyms.h"
static int is_typedef;
diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
index 10d7dc724b6d..09a265cd7193 100644
--- a/scripts/genksyms/parse.y
+++ b/scripts/genksyms/parse.y
@@ -24,7 +24,7 @@
%{
#include <assert.h>
-#include <malloc.h>
+#include <stdlib.h>
#include "genksyms.h"
static int is_typedef;
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 090f24839700..d21ec3a89603 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -13,7 +13,7 @@
use strict;
my $P = $0;
-my $V = '0.23';
+my $V = '0.26-beta6';
use Getopt::Long qw(:config no_auto_abbrev);
@@ -24,14 +24,19 @@ my $email_maintainer = 1;
my $email_list = 1;
my $email_subscriber_list = 0;
my $email_git_penguin_chiefs = 0;
-my $email_git = 1;
+my $email_git = 0;
+my $email_git_all_signature_types = 0;
my $email_git_blame = 0;
+my $email_git_blame_signatures = 1;
+my $email_git_fallback = 1;
my $email_git_min_signatures = 1;
my $email_git_max_maintainers = 5;
my $email_git_min_percent = 5;
my $email_git_since = "1-year-ago";
my $email_hg_since = "-365";
+my $interactive = 0;
my $email_remove_duplicates = 1;
+my $email_use_mailmap = 1;
my $output_multiline = 1;
my $output_separator = ", ";
my $output_roles = 0;
@@ -41,17 +46,24 @@ my $web = 0;
my $subsystem = 0;
my $status = 0;
my $keywords = 1;
+my $sections = 0;
+my $file_emails = 0;
my $from_filename = 0;
my $pattern_depth = 0;
my $version = 0;
my $help = 0;
+my $vcs_used = 0;
+
my $exit = 0;
+my %commit_author_hash;
+my %commit_signer_hash;
+
my @penguin_chief = ();
-push(@penguin_chief,"Linus Torvalds:torvalds\@linux-foundation.org");
+push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org");
#Andrew wants in on most everything - 2009/01/14
-#push(@penguin_chief,"Andrew Morton:akpm\@linux-foundation.org");
+#push(@penguin_chief, "Andrew Morton:akpm\@linux-foundation.org");
my @penguin_chief_names = ();
foreach my $chief (@penguin_chief) {
@@ -61,7 +73,15 @@ foreach my $chief (@penguin_chief) {
push(@penguin_chief_names, $chief_name);
}
}
-my $penguin_chiefs = "\(" . join("|",@penguin_chief_names) . "\)";
+my $penguin_chiefs = "\(" . join("|", @penguin_chief_names) . "\)";
+
+# Signature types of people who are either
+# a) responsible for the code in question, or
+# b) familiar enough with it to give relevant feedback
+my @signature_tags = ();
+push(@signature_tags, "Signed-off-by:");
+push(@signature_tags, "Reviewed-by:");
+push(@signature_tags, "Acked-by:");
# rfc822 email address - preloaded methods go here.
my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
@@ -74,38 +94,106 @@ my %VCS_cmds;
my %VCS_cmds_git = (
"execute_cmd" => \&git_execute_cmd,
"available" => '(which("git") ne "") && (-d ".git")',
- "find_signers_cmd" => "git log --since=\$email_git_since -- \$file",
- "find_commit_signers_cmd" => "git log -1 \$commit",
+ "find_signers_cmd" =>
+ "git log --no-color --since=\$email_git_since " .
+ '--format="GitCommit: %H%n' .
+ 'GitAuthor: %an <%ae>%n' .
+ 'GitDate: %aD%n' .
+ 'GitSubject: %s%n' .
+ '%b%n"' .
+ " -- \$file",
+ "find_commit_signers_cmd" =>
+ "git log --no-color " .
+ '--format="GitCommit: %H%n' .
+ 'GitAuthor: %an <%ae>%n' .
+ 'GitDate: %aD%n' .
+ 'GitSubject: %s%n' .
+ '%b%n"' .
+ " -1 \$commit",
+ "find_commit_author_cmd" =>
+ "git log --no-color " .
+ '--format="GitCommit: %H%n' .
+ 'GitAuthor: %an <%ae>%n' .
+ 'GitDate: %aD%n' .
+ 'GitSubject: %s%n"' .
+ " -1 \$commit",
"blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
"blame_file_cmd" => "git blame -l \$file",
- "commit_pattern" => "^commit [0-9a-f]{40,40}",
- "blame_commit_pattern" => "^([0-9a-f]+) "
+ "commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})",
+ "blame_commit_pattern" => "^([0-9a-f]+) ",
+ "author_pattern" => "^GitAuthor: (.*)",
+ "subject_pattern" => "^GitSubject: (.*)",
);
my %VCS_cmds_hg = (
"execute_cmd" => \&hg_execute_cmd,
"available" => '(which("hg") ne "") && (-d ".hg")',
"find_signers_cmd" =>
- "hg log --date=\$email_hg_since" .
- " --template='commit {node}\\n{desc}\\n' -- \$file",
- "find_commit_signers_cmd" => "hg log --template='{desc}\\n' -r \$commit",
+ "hg log --date=\$email_hg_since " .
+ "--template='HgCommit: {node}\\n" .
+ "HgAuthor: {author}\\n" .
+ "HgSubject: {desc}\\n'" .
+ " -- \$file",
+ "find_commit_signers_cmd" =>
+ "hg log " .
+ "--template='HgSubject: {desc}\\n'" .
+ " -r \$commit",
+ "find_commit_author_cmd" =>
+ "hg log " .
+ "--template='HgCommit: {node}\\n" .
+ "HgAuthor: {author}\\n" .
+ "HgSubject: {desc|firstline}\\n'" .
+ " -r \$commit",
"blame_range_cmd" => "", # not supported
- "blame_file_cmd" => "hg blame -c \$file",
- "commit_pattern" => "^commit [0-9a-f]{40,40}",
- "blame_commit_pattern" => "^([0-9a-f]+):"
+ "blame_file_cmd" => "hg blame -n \$file",
+ "commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})",
+ "blame_commit_pattern" => "^([ 0-9a-f]+):",
+ "author_pattern" => "^HgAuthor: (.*)",
+ "subject_pattern" => "^HgSubject: (.*)",
);
+my $conf = which_conf(".get_maintainer.conf");
+if (-f $conf) {
+ my @conf_args;
+ open(my $conffile, '<', "$conf")
+ or warn "$P: Can't find a readable .get_maintainer.conf file $!\n";
+
+ while (<$conffile>) {
+ my $line = $_;
+
+ $line =~ s/\s*\n?$//g;
+ $line =~ s/^\s*//g;
+ $line =~ s/\s+/ /g;
+
+ next if ($line =~ m/^\s*#/);
+ next if ($line =~ m/^\s*$/);
+
+ my @words = split(" ", $line);
+ foreach my $word (@words) {
+ last if ($word =~ m/^#/);
+ push (@conf_args, $word);
+ }
+ }
+ close($conffile);
+ unshift(@ARGV, @conf_args) if @conf_args;
+}
+
if (!GetOptions(
'email!' => \$email,
'git!' => \$email_git,
+ 'git-all-signature-types!' => \$email_git_all_signature_types,
'git-blame!' => \$email_git_blame,
+ 'git-blame-signatures!' => \$email_git_blame_signatures,
+ 'git-fallback!' => \$email_git_fallback,
'git-chief-penguins!' => \$email_git_penguin_chiefs,
'git-min-signatures=i' => \$email_git_min_signatures,
'git-max-maintainers=i' => \$email_git_max_maintainers,
'git-min-percent=i' => \$email_git_min_percent,
'git-since=s' => \$email_git_since,
'hg-since=s' => \$email_hg_since,
+ 'i|interactive!' => \$interactive,
'remove-duplicates!' => \$email_remove_duplicates,
+ 'mailmap!' => \$email_use_mailmap,
'm!' => \$email_maintainer,
'n!' => \$email_usename,
'l!' => \$email_list,
@@ -120,9 +208,11 @@ if (!GetOptions(
'web!' => \$web,
'pattern-depth=i' => \$pattern_depth,
'k|keywords!' => \$keywords,
+ 'sections!' => \$sections,
+ 'fe|file-emails!' => \$file_emails,
'f|file' => \$from_filename,
'v|version' => \$version,
- 'h|help' => \$help,
+ 'h|help|usage' => \$help,
)) {
die "$P: invalid argument - use --help if necessary\n";
}
@@ -137,29 +227,34 @@ if ($version != 0) {
exit 0;
}
-if ($#ARGV < 0) {
- usage();
- die "$P: argument missing: patchfile or -f file please\n";
-}
-
-if ($output_separator ne ", ") {
- $output_multiline = 0;
+if (-t STDIN && !@ARGV) {
+ # We're talking to a terminal, but have no command line arguments.
+ die "$P: missing patchfile or -f file - use --help if necessary\n";
}
-if ($output_rolestats) {
- $output_roles = 1;
-}
-
-my $selections = $email + $scm + $status + $subsystem + $web;
-if ($selections == 0) {
- usage();
- die "$P: Missing required option: email, scm, status, subsystem or web\n";
+$output_multiline = 0 if ($output_separator ne ", ");
+$output_rolestats = 1 if ($interactive);
+$output_roles = 1 if ($output_rolestats);
+
+if ($sections) {
+ $email = 0;
+ $email_list = 0;
+ $scm = 0;
+ $status = 0;
+ $subsystem = 0;
+ $web = 0;
+ $keywords = 0;
+ $interactive = 0;
+} else {
+ my $selections = $email + $scm + $status + $subsystem + $web;
+ if ($selections == 0) {
+ die "$P: Missing required option: email, scm, status, subsystem or web\n";
+ }
}
if ($email &&
($email_maintainer + $email_list + $email_subscriber_list +
$email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) {
- usage();
die "$P: Please select at least 1 email option\n";
}
@@ -173,8 +268,9 @@ if (!top_of_kernel_tree($lk_path)) {
my @typevalue = ();
my %keyword_hash;
-open(MAINT, "<${lk_path}MAINTAINERS") || die "$P: Can't open MAINTAINERS\n";
-while (<MAINT>) {
+open (my $maint, '<', "${lk_path}MAINTAINERS")
+ or die "$P: Can't open MAINTAINERS: $!\n";
+while (<$maint>) {
my $line = $_;
if ($line =~ m/^(\C):\s*(.*)/) {
@@ -199,32 +295,84 @@ while (<MAINT>) {
push(@typevalue, $line);
}
}
-close(MAINT);
+close($maint);
-my %mailmap;
-if ($email_remove_duplicates) {
- open(MAILMAP, "<${lk_path}.mailmap") || warn "$P: Can't open .mailmap\n";
- while (<MAILMAP>) {
- my $line = $_;
-
- next if ($line =~ m/^\s*#/);
- next if ($line =~ m/^\s*$/);
-
- my ($name, $address) = parse_email($line);
- $line = format_email($name, $address, $email_usename);
-
- next if ($line =~ m/^\s*$/);
+#
+# Read mail address map
+#
- if (exists($mailmap{$name})) {
- my $obj = $mailmap{$name};
- push(@$obj, $address);
- } else {
- my @arr = ($address);
- $mailmap{$name} = \@arr;
+my $mailmap;
+
+read_mailmap();
+
+sub read_mailmap {
+ $mailmap = {
+ names => {},
+ addresses => {}
+ };
+
+ return if (!$email_use_mailmap || !(-f "${lk_path}.mailmap"));
+
+ open(my $mailmap_file, '<', "${lk_path}.mailmap")
+ or warn "$P: Can't open .mailmap: $!\n";
+
+ while (<$mailmap_file>) {
+ s/#.*$//; #strip comments
+ s/^\s+|\s+$//g; #trim
+
+ next if (/^\s*$/); #skip empty lines
+ #entries have one of the following formats:
+ # name1 <mail1>
+ # <mail1> <mail2>
+ # name1 <mail1> <mail2>
+ # name1 <mail1> name2 <mail2>
+ # (see man git-shortlog)
+ if (/^(.+)<(.+)>$/) {
+ my $real_name = $1;
+ my $address = $2;
+
+ $real_name =~ s/\s+$//;
+ ($real_name, $address) = parse_email("$real_name <$address>");
+ $mailmap->{names}->{$address} = $real_name;
+
+ } elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) {
+ my $real_address = $1;
+ my $wrong_address = $2;
+
+ $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+ } elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) {
+ my $real_name = $1;
+ my $real_address = $2;
+ my $wrong_address = $3;
+
+ $real_name =~ s/\s+$//;
+ ($real_name, $real_address) =
+ parse_email("$real_name <$real_address>");
+ $mailmap->{names}->{$wrong_address} = $real_name;
+ $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+ } elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) {
+ my $real_name = $1;
+ my $real_address = $2;
+ my $wrong_name = $3;
+ my $wrong_address = $4;
+
+ $real_name =~ s/\s+$//;
+ ($real_name, $real_address) =
+ parse_email("$real_name <$real_address>");
+
+ $wrong_name =~ s/\s+$//;
+ ($wrong_name, $wrong_address) =
+ parse_email("$wrong_name <$wrong_address>");
+
+ my $wrong_email = format_email($wrong_name, $wrong_address, 1);
+ $mailmap->{names}->{$wrong_email} = $real_name;
+ $mailmap->{addresses}->{$wrong_email} = $real_address;
}
}
- close(MAILMAP);
+ close($mailmap_file);
}
## use the filenames on the command line or find the filenames in the patchfiles
@@ -232,31 +380,47 @@ if ($email_remove_duplicates) {
my @files = ();
my @range = ();
my @keyword_tvi = ();
+my @file_emails = ();
+
+if (!@ARGV) {
+ push(@ARGV, "&STDIN");
+}
foreach my $file (@ARGV) {
- ##if $file is a directory and it lacks a trailing slash, add one
- if ((-d $file)) {
- $file =~ s@([^/])$@$1/@;
- } elsif (!(-f $file)) {
- die "$P: file '${file}' not found\n";
+ if ($file ne "&STDIN") {
+ ##if $file is a directory and it lacks a trailing slash, add one
+ if ((-d $file)) {
+ $file =~ s@([^/])$@$1/@;
+ } elsif (!(-f $file)) {
+ die "$P: file '${file}' not found\n";
+ }
}
if ($from_filename) {
push(@files, $file);
- if (-f $file && $keywords) {
- open(FILE, "<$file") or die "$P: Can't open ${file}\n";
- my $text = do { local($/) ; <FILE> };
- foreach my $line (keys %keyword_hash) {
- if ($text =~ m/$keyword_hash{$line}/x) {
- push(@keyword_tvi, $line);
+ if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) {
+ open(my $f, '<', $file)
+ or die "$P: Can't open $file: $!\n";
+ my $text = do { local($/) ; <$f> };
+ close($f);
+ if ($keywords) {
+ foreach my $line (keys %keyword_hash) {
+ if ($text =~ m/$keyword_hash{$line}/x) {
+ push(@keyword_tvi, $line);
+ }
}
}
- close(FILE);
+ if ($file_emails) {
+ my @poss_addr = $text =~ m$[A-Za-zÀ-ÿ\"\' \,\.\+-]*\s*[\,]*\s*[\(\<\{]{0,1}[A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+\.[A-Za-z0-9]+[\)\>\}]{0,1}$g;
+ push(@file_emails, clean_file_emails(@poss_addr));
+ }
}
} else {
my $file_cnt = @files;
my $lastfile;
- open(PATCH, "<$file") or die "$P: Can't open ${file}\n";
- while (<PATCH>) {
+
+ open(my $patch, "< $file")
+ or die "$P: Can't open $file: $!\n";
+ while (<$patch>) {
my $patch_line = $_;
if (m/^\+\+\+\s+(\S+)/) {
my $filename = $1;
@@ -276,7 +440,8 @@ foreach my $file (@ARGV) {
}
}
}
- close(PATCH);
+ close($patch);
+
if ($file_cnt == @files) {
warn "$P: file '${file}' doesn't appear to be a patch. "
. "Add -f to options?\n";
@@ -285,133 +450,211 @@ foreach my $file (@ARGV) {
}
}
+@file_emails = uniq(@file_emails);
+
+my %email_hash_name;
+my %email_hash_address;
my @email_to = ();
+my %hash_list_to;
my @list_to = ();
my @scm = ();
my @web = ();
my @subsystem = ();
my @status = ();
+my %deduplicate_name_hash = ();
+my %deduplicate_address_hash = ();
+my $signature_pattern;
-# Find responsible parties
+my @maintainers = get_maintainers();
-foreach my $file (@files) {
+if (@maintainers) {
+ @maintainers = merge_email(@maintainers);
+ output(@maintainers);
+}
- my %hash;
- my $tvi = find_first_section();
- while ($tvi < @typevalue) {
- my $start = find_starting_index($tvi);
- my $end = find_ending_index($tvi);
- my $exclude = 0;
- my $i;
-
- #Do not match excluded file patterns
-
- for ($i = $start; $i < $end; $i++) {
- my $line = $typevalue[$i];
- if ($line =~ m/^(\C):\s*(.*)/) {
- my $type = $1;
- my $value = $2;
- if ($type eq 'X') {
- if (file_match_pattern($file, $value)) {
- $exclude = 1;
- }
- }
- }
- }
+if ($scm) {
+ @scm = uniq(@scm);
+ output(@scm);
+}
+
+if ($status) {
+ @status = uniq(@status);
+ output(@status);
+}
+
+if ($subsystem) {
+ @subsystem = uniq(@subsystem);
+ output(@subsystem);
+}
+
+if ($web) {
+ @web = uniq(@web);
+ output(@web);
+}
+
+exit($exit);
+
+sub get_maintainers {
+ %email_hash_name = ();
+ %email_hash_address = ();
+ %commit_author_hash = ();
+ %commit_signer_hash = ();
+ @email_to = ();
+ %hash_list_to = ();
+ @list_to = ();
+ @scm = ();
+ @web = ();
+ @subsystem = ();
+ @status = ();
+ %deduplicate_name_hash = ();
+ %deduplicate_address_hash = ();
+ if ($email_git_all_signature_types) {
+ $signature_pattern = "(.+?)[Bb][Yy]:";
+ } else {
+ $signature_pattern = "\(" . join("|", @signature_tags) . "\)";
+ }
+
+ # Find responsible parties
+
+ my %exact_pattern_match_hash = ();
+
+ foreach my $file (@files) {
+
+ my %hash;
+ my $tvi = find_first_section();
+ while ($tvi < @typevalue) {
+ my $start = find_starting_index($tvi);
+ my $end = find_ending_index($tvi);
+ my $exclude = 0;
+ my $i;
+
+ #Do not match excluded file patterns
- if (!$exclude) {
for ($i = $start; $i < $end; $i++) {
my $line = $typevalue[$i];
if ($line =~ m/^(\C):\s*(.*)/) {
my $type = $1;
my $value = $2;
- if ($type eq 'F') {
+ if ($type eq 'X') {
if (file_match_pattern($file, $value)) {
- my $value_pd = ($value =~ tr@/@@);
- my $file_pd = ($file =~ tr@/@@);
- $value_pd++ if (substr($value,-1,1) ne "/");
- if ($pattern_depth == 0 ||
- (($file_pd - $value_pd) < $pattern_depth)) {
- $hash{$tvi} = $value_pd;
+ $exclude = 1;
+ last;
+ }
+ }
+ }
+ }
+
+ if (!$exclude) {
+ for ($i = $start; $i < $end; $i++) {
+ my $line = $typevalue[$i];
+ if ($line =~ m/^(\C):\s*(.*)/) {
+ my $type = $1;
+ my $value = $2;
+ if ($type eq 'F') {
+ if (file_match_pattern($file, $value)) {
+ my $value_pd = ($value =~ tr@/@@);
+ my $file_pd = ($file =~ tr@/@@);
+ $value_pd++ if (substr($value,-1,1) ne "/");
+ $value_pd = -1 if ($value =~ /^\.\*/);
+ if ($value_pd >= $file_pd) {
+ $exact_pattern_match_hash{$file} = 1;
+ }
+ if ($pattern_depth == 0 ||
+ (($file_pd - $value_pd) < $pattern_depth)) {
+ $hash{$tvi} = $value_pd;
+ }
}
}
}
}
}
+ $tvi = $end + 1;
}
- $tvi += ($end - $start);
-
- }
-
- foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
- add_categories($line);
+ foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
+ add_categories($line);
+ if ($sections) {
+ my $i;
+ my $start = find_starting_index($line);
+ my $end = find_ending_index($line);
+ for ($i = $start; $i < $end; $i++) {
+ my $line = $typevalue[$i];
+ if ($line =~ /^[FX]:/) { ##Restore file patterns
+ $line =~ s/([^\\])\.([^\*])/$1\?$2/g;
+ $line =~ s/([^\\])\.$/$1\?/g; ##Convert . back to ?
+ $line =~ s/\\\./\./g; ##Convert \. to .
+ $line =~ s/\.\*/\*/g; ##Convert .* to *
+ }
+ $line =~ s/^([A-Z]):/$1:\t/g;
+ print("$line\n");
+ }
+ print("\n");
+ }
+ }
}
- if ($email && $email_git) {
- vcs_file_signoffs($file);
+ if ($keywords) {
+ @keyword_tvi = sort_and_uniq(@keyword_tvi);
+ foreach my $line (@keyword_tvi) {
+ add_categories($line);
+ }
}
- if ($email && $email_git_blame) {
- vcs_file_blame($file);
+ foreach my $email (@email_to, @list_to) {
+ $email->[0] = deduplicate_email($email->[0]);
}
-}
-if ($keywords) {
- @keyword_tvi = sort_and_uniq(@keyword_tvi);
- foreach my $line (@keyword_tvi) {
- add_categories($line);
+ foreach my $file (@files) {
+ if ($email &&
+ ($email_git || ($email_git_fallback &&
+ !$exact_pattern_match_hash{$file}))) {
+ vcs_file_signoffs($file);
+ }
+ if ($email && $email_git_blame) {
+ vcs_file_blame($file);
+ }
}
-}
-if ($email) {
- foreach my $chief (@penguin_chief) {
- if ($chief =~ m/^(.*):(.*)/) {
- my $email_address;
+ if ($email) {
+ foreach my $chief (@penguin_chief) {
+ if ($chief =~ m/^(.*):(.*)/) {
+ my $email_address;
- $email_address = format_email($1, $2, $email_usename);
- if ($email_git_penguin_chiefs) {
- push(@email_to, [$email_address, 'chief penguin']);
- } else {
- @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
+ $email_address = format_email($1, $2, $email_usename);
+ if ($email_git_penguin_chiefs) {
+ push(@email_to, [$email_address, 'chief penguin']);
+ } else {
+ @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
+ }
}
}
+
+ foreach my $email (@file_emails) {
+ my ($name, $address) = parse_email($email);
+
+ my $tmp_email = format_email($name, $address, $email_usename);
+ push_email_address($tmp_email, '');
+ add_role($tmp_email, 'in file');
+ }
}
-}
-if ($email || $email_list) {
my @to = ();
- if ($email) {
- @to = (@to, @email_to);
- }
- if ($email_list) {
- @to = (@to, @list_to);
+ if ($email || $email_list) {
+ if ($email) {
+ @to = (@to, @email_to);
+ }
+ if ($email_list) {
+ @to = (@to, @list_to);
+ }
}
- output(merge_email(@to));
-}
-if ($scm) {
- @scm = uniq(@scm);
- output(@scm);
-}
-
-if ($status) {
- @status = uniq(@status);
- output(@status);
-}
-
-if ($subsystem) {
- @subsystem = uniq(@subsystem);
- output(@subsystem);
-}
+ if ($interactive) {
+ @to = interactive_get_maintainers(\@to);
+ }
-if ($web) {
- @web = uniq(@web);
- output(@web);
+ return @to;
}
-exit($exit);
-
sub file_match_pattern {
my ($file, $pattern) = @_;
if (substr($pattern, -1) eq "/") {
@@ -439,13 +682,17 @@ version: $V
MAINTAINER field selection options:
--email => print email address(es) if any
--git => include recent git \*-by: signers
+ --git-all-signature-types => include signers regardless of signature type
+ or use only ${signature_pattern} signers (default: $email_git_all_signature_types)
+ --git-fallback => use git when no exact MAINTAINERS pattern (default: $email_git_fallback)
--git-chief-penguins => include ${penguin_chiefs}
- --git-min-signatures => number of signatures required (default: 1)
- --git-max-maintainers => maximum maintainers to add (default: 5)
- --git-min-percent => minimum percentage of commits required (default: 5)
+ --git-min-signatures => number of signatures required (default: $email_git_min_signatures)
+ --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers)
+ --git-min-percent => minimum percentage of commits required (default: $email_git_min_percent)
--git-blame => use git blame to find modified commits for patch or file
- --git-since => git history to use (default: 1-year-ago)
- --hg-since => hg history to use (default: -365)
+ --git-since => git history to use (default: $email_git_since)
+ --hg-since => hg history to use (default: $email_hg_since)
+ --interactive => display a menu (mostly useful if used with the --git option)
--m => include maintainer(s) if any
--n => include name 'Full Name <addr\@domain.tld>'
--l => include list(s) if any
@@ -453,6 +700,7 @@ MAINTAINER field selection options:
--remove-duplicates => minimize duplicate email names/addresses
--roles => show roles (status:subsystem, git-signer, list, etc...)
--rolestats => show roles and statistics (commits/total_commits, %)
+ --file-emails => add email addresses found in -f file (default: 0 (off))
--scm => print SCM tree(s) if any
--status => print status if any
--subsystem => print subsystem name if any
@@ -465,7 +713,9 @@ Output type options:
Other options:
--pattern-depth => Number of pattern directory traversals (default: 0 (all))
- --keywords => scan patch for keywords (default: 1 (on))
+ --keywords => scan patch for keywords (default: $keywords)
+ --sections => print all of the subsystem sections with pattern matches
+ --mailmap => use .mailmap file (default: $email_use_mailmap)
--version => show version
--help => show this help information
@@ -496,34 +746,39 @@ Notes:
--git-min-signatures, --git-max-maintainers, --git-min-percent, and
--git-blame
Use --hg-since not --git-since to control date selection
+ File ".get_maintainer.conf", if it exists in the linux kernel source root
+ directory, can change whatever get_maintainer defaults are desired.
+ Entries in this file can be any command line argument.
+ This file is prepended to any additional command line arguments.
+ Multiple lines and # comments are allowed.
EOT
}
sub top_of_kernel_tree {
- my ($lk_path) = @_;
+ my ($lk_path) = @_;
- if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
- $lk_path .= "/";
- }
- if ( (-f "${lk_path}COPYING")
- && (-f "${lk_path}CREDITS")
- && (-f "${lk_path}Kbuild")
- && (-f "${lk_path}MAINTAINERS")
- && (-f "${lk_path}Makefile")
- && (-f "${lk_path}README")
- && (-d "${lk_path}Documentation")
- && (-d "${lk_path}arch")
- && (-d "${lk_path}include")
- && (-d "${lk_path}drivers")
- && (-d "${lk_path}fs")
- && (-d "${lk_path}init")
- && (-d "${lk_path}ipc")
- && (-d "${lk_path}kernel")
- && (-d "${lk_path}lib")
- && (-d "${lk_path}scripts")) {
- return 1;
- }
- return 0;
+ if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
+ $lk_path .= "/";
+ }
+ if ( (-f "${lk_path}COPYING")
+ && (-f "${lk_path}CREDITS")
+ && (-f "${lk_path}Kbuild")
+ && (-f "${lk_path}MAINTAINERS")
+ && (-f "${lk_path}Makefile")
+ && (-f "${lk_path}README")
+ && (-d "${lk_path}Documentation")
+ && (-d "${lk_path}arch")
+ && (-d "${lk_path}include")
+ && (-d "${lk_path}drivers")
+ && (-d "${lk_path}fs")
+ && (-d "${lk_path}init")
+ && (-d "${lk_path}ipc")
+ && (-d "${lk_path}kernel")
+ && (-d "${lk_path}lib")
+ && (-d "${lk_path}scripts")) {
+ return 1;
+ }
+ return 0;
}
sub parse_email {
@@ -545,7 +800,7 @@ sub parse_email {
$name =~ s/^\"|\"$//g;
$address =~ s/^\s+|\s+$//g;
- if ($name =~ /[^a-z0-9 \.\-]/i) { ##has "must quote" chars
+ if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
$name = "\"$name\"";
}
@@ -562,7 +817,7 @@ sub format_email {
$name =~ s/^\"|\"$//g;
$address =~ s/^\s+|\s+$//g;
- if ($name =~ /[^a-z0-9 \.\-]/i) { ##has "must quote" chars
+ if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
$name = "\"$name\"";
}
@@ -715,11 +970,19 @@ sub add_categories {
}
if ($list_additional =~ m/subscribers-only/) {
if ($email_subscriber_list) {
- push(@list_to, [$list_address, "subscriber list${list_role}"]);
+ if (!$hash_list_to{lc($list_address)}) {
+ $hash_list_to{lc($list_address)} = 1;
+ push(@list_to, [$list_address,
+ "subscriber list${list_role}"]);
+ }
}
} else {
if ($email_list) {
- push(@list_to, [$list_address, "open list${list_role}"]);
+ if (!$hash_list_to{lc($list_address)}) {
+ $hash_list_to{lc($list_address)} = 1;
+ push(@list_to, [$list_address,
+ "open list${list_role}"]);
+ }
}
}
} elsif ($ptype eq "M") {
@@ -750,15 +1013,12 @@ sub add_categories {
}
}
-my %email_hash_name;
-my %email_hash_address;
-
sub email_inuse {
my ($name, $address) = @_;
return 1 if (($name eq "") && ($address eq ""));
- return 1 if (($name ne "") && exists($email_hash_name{$name}));
- return 1 if (($address ne "") && exists($email_hash_address{$address}));
+ return 1 if (($name ne "") && exists($email_hash_name{lc($name)}));
+ return 1 if (($address ne "") && exists($email_hash_address{lc($address)}));
return 0;
}
@@ -776,8 +1036,8 @@ sub push_email_address {
push(@email_to, [format_email($name, $address, $email_usename), $role]);
} elsif (!email_inuse($name, $address)) {
push(@email_to, [format_email($name, $address, $email_usename), $role]);
- $email_hash_name{$name}++;
- $email_hash_address{$address}++;
+ $email_hash_name{lc($name)}++ if ($name ne "");
+ $email_hash_address{lc($address)}++;
}
return 1;
@@ -811,7 +1071,9 @@ sub add_role {
foreach my $entry (@email_to) {
if ($email_remove_duplicates) {
my ($entry_name, $entry_address) = parse_email($entry->[0]);
- if ($name eq $entry_name || $address eq $entry_address) {
+ if (($name eq $entry_name || $address eq $entry_address)
+ && ($role eq "" || !($entry->[1] =~ m/$role/))
+ ) {
if ($entry->[1] eq "") {
$entry->[1] = "$role";
} else {
@@ -819,7 +1081,9 @@ sub add_role {
}
}
} else {
- if ($email eq $entry->[0]) {
+ if ($email eq $entry->[0]
+ && ($role eq "" || !($entry->[1] =~ m/$role/))
+ ) {
if ($entry->[1] eq "") {
$entry->[1] = "$role";
} else {
@@ -842,30 +1106,69 @@ sub which {
return "";
}
-sub mailmap {
- my (@lines) = @_;
- my %hash;
+sub which_conf {
+ my ($conf) = @_;
- foreach my $line (@lines) {
- my ($name, $address) = parse_email($line);
- if (!exists($hash{$name})) {
- $hash{$name} = $address;
- } elsif ($address ne $hash{$name}) {
- $address = $hash{$name};
- $line = format_email($name, $address, $email_usename);
+ foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
+ if (-e "$path/$conf") {
+ return "$path/$conf";
}
- if (exists($mailmap{$name})) {
- my $obj = $mailmap{$name};
- foreach my $map_address (@$obj) {
- if (($map_address eq $address) &&
- ($map_address ne $hash{$name})) {
- $line = format_email($name, $hash{$name}, $email_usename);
- }
- }
+ }
+
+ return "";
+}
+
+sub mailmap_email {
+ my ($line) = @_;
+
+ my ($name, $address) = parse_email($line);
+ my $email = format_email($name, $address, 1);
+ my $real_name = $name;
+ my $real_address = $address;
+
+ if (exists $mailmap->{names}->{$email} ||
+ exists $mailmap->{addresses}->{$email}) {
+ if (exists $mailmap->{names}->{$email}) {
+ $real_name = $mailmap->{names}->{$email};
+ }
+ if (exists $mailmap->{addresses}->{$email}) {
+ $real_address = $mailmap->{addresses}->{$email};
+ }
+ } else {
+ if (exists $mailmap->{names}->{$address}) {
+ $real_name = $mailmap->{names}->{$address};
+ }
+ if (exists $mailmap->{addresses}->{$address}) {
+ $real_address = $mailmap->{addresses}->{$address};
}
}
+ return format_email($real_name, $real_address, 1);
+}
- return @lines;
+sub mailmap {
+ my (@addresses) = @_;
+
+ my @mapped_emails = ();
+ foreach my $line (@addresses) {
+ push(@mapped_emails, mailmap_email($line));
+ }
+ merge_by_realname(@mapped_emails) if ($email_use_mailmap);
+ return @mapped_emails;
+}
+
+sub merge_by_realname {
+ my %address_map;
+ my (@emails) = @_;
+
+ foreach my $email (@emails) {
+ my ($name, $address) = parse_email($email);
+ if (exists $address_map{$name}) {
+ $address = $address_map{$name};
+ $email = format_email($name, $address, 1);
+ } else {
+ $address_map{$name} = $address;
+ }
+ }
}
sub git_execute_cmd {
@@ -889,10 +1192,30 @@ sub hg_execute_cmd {
return @lines;
}
+sub extract_formatted_signatures {
+ my (@signature_lines) = @_;
+
+ my @type = @signature_lines;
+
+ s/\s*(.*):.*/$1/ for (@type);
+
+ # cut -f2- -d":"
+ s/\s*.*:\s*(.+)\s*/$1/ for (@signature_lines);
+
+## Reformat email addresses (with names) to avoid badly written signatures
+
+ foreach my $signer (@signature_lines) {
+ $signer = deduplicate_email($signer);
+ }
+
+ return (\@type, \@signature_lines);
+}
+
sub vcs_find_signers {
my ($cmd) = @_;
- my @lines = ();
my $commits;
+ my @lines = ();
+ my @signatures = ();
@lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
@@ -900,21 +1223,48 @@ sub vcs_find_signers {
$commits = grep(/$pattern/, @lines); # of commits
- @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines);
+ @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines);
+
+ return (0, @signatures) if !@signatures;
+
+ save_commits_by_author(@lines) if ($interactive);
+ save_commits_by_signer(@lines) if ($interactive);
+
+ if (!$email_git_penguin_chiefs) {
+ @signatures = grep(!/${penguin_chiefs}/i, @signatures);
+ }
+
+ my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+
+ return ($commits, @$signers_ref);
+}
+
+sub vcs_find_author {
+ my ($cmd) = @_;
+ my @lines = ();
+
+ @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
if (!$email_git_penguin_chiefs) {
@lines = grep(!/${penguin_chiefs}/i, @lines);
}
- # cut -f2- -d":"
- s/.*:\s*(.+)\s*/$1/ for (@lines);
-## Reformat email addresses (with names) to avoid badly written signatures
+ return @lines if !@lines;
+ my @authors = ();
foreach my $line (@lines) {
- my ($name, $address) = parse_email($line);
- $line = format_email($name, $address, 1);
+ if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+ my $author = $1;
+ my ($name, $address) = parse_email($author);
+ $author = format_email($name, $address, 1);
+ push(@authors, $author);
+ }
}
- return ($commits, @lines);
+ save_commits_by_author(@lines) if ($interactive);
+ save_commits_by_signer(@lines) if ($interactive);
+
+ return @authors;
}
sub vcs_save_commits {
@@ -974,6 +1324,10 @@ sub vcs_blame {
@commits = vcs_save_commits($cmd);
}
+ foreach my $commit (@commits) {
+ $commit =~ s/^\^//g;
+ }
+
return @commits;
}
@@ -982,7 +1336,7 @@ sub vcs_exists {
%VCS_cmds = %VCS_cmds_git;
return 1 if eval $VCS_cmds{"available"};
%VCS_cmds = %VCS_cmds_hg;
- return 1 if eval $VCS_cmds{"available"};
+ return 2 if eval $VCS_cmds{"available"};
%VCS_cmds = ();
if (!$printed_novcs) {
warn("$P: No supported VCS found. Add --nogit to options?\n");
@@ -994,6 +1348,405 @@ sub vcs_exists {
return 0;
}
+sub vcs_is_git {
+ vcs_exists();
+ return $vcs_used == 1;
+}
+
+sub vcs_is_hg {
+ return $vcs_used == 2;
+}
+
+sub interactive_get_maintainers {
+ my ($list_ref) = @_;
+ my @list = @$list_ref;
+
+ vcs_exists();
+
+ my %selected;
+ my %authored;
+ my %signed;
+ my $count = 0;
+ my $maintained = 0;
+ foreach my $entry (@list) {
+ $maintained = 1 if ($entry->[1] =~ /^(maintainer|supporter)/i);
+ $selected{$count} = 1;
+ $authored{$count} = 0;
+ $signed{$count} = 0;
+ $count++;
+ }
+
+ #menu loop
+ my $done = 0;
+ my $print_options = 0;
+ my $redraw = 1;
+ while (!$done) {
+ $count = 0;
+ if ($redraw) {
+ printf STDERR "\n%1s %2s %-65s",
+ "*", "#", "email/list and role:stats";
+ if ($email_git ||
+ ($email_git_fallback && !$maintained) ||
+ $email_git_blame) {
+ print STDERR "auth sign";
+ }
+ print STDERR "\n";
+ foreach my $entry (@list) {
+ my $email = $entry->[0];
+ my $role = $entry->[1];
+ my $sel = "";
+ $sel = "*" if ($selected{$count});
+ my $commit_author = $commit_author_hash{$email};
+ my $commit_signer = $commit_signer_hash{$email};
+ my $authored = 0;
+ my $signed = 0;
+ $authored++ for (@{$commit_author});
+ $signed++ for (@{$commit_signer});
+ printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email;
+ printf STDERR "%4d %4d", $authored, $signed
+ if ($authored > 0 || $signed > 0);
+ printf STDERR "\n %s\n", $role;
+ if ($authored{$count}) {
+ my $commit_author = $commit_author_hash{$email};
+ foreach my $ref (@{$commit_author}) {
+ print STDERR " Author: @{$ref}[1]\n";
+ }
+ }
+ if ($signed{$count}) {
+ my $commit_signer = $commit_signer_hash{$email};
+ foreach my $ref (@{$commit_signer}) {
+ print STDERR " @{$ref}[2]: @{$ref}[1]\n";
+ }
+ }
+
+ $count++;
+ }
+ }
+ my $date_ref = \$email_git_since;
+ $date_ref = \$email_hg_since if (vcs_is_hg());
+ if ($print_options) {
+ $print_options = 0;
+ if (vcs_exists()) {
+ print STDERR <<EOT
+
+Version Control options:
+g use git history [$email_git]
+gf use git-fallback [$email_git_fallback]
+b use git blame [$email_git_blame]
+bs use blame signatures [$email_git_blame_signatures]
+c# minimum commits [$email_git_min_signatures]
+%# min percent [$email_git_min_percent]
+d# history to use [$$date_ref]
+x# max maintainers [$email_git_max_maintainers]
+t all signature types [$email_git_all_signature_types]
+m use .mailmap [$email_use_mailmap]
+EOT
+ }
+ print STDERR <<EOT
+
+Additional options:
+0 toggle all
+tm toggle maintainers
+tg toggle git entries
+tl toggle open list entries
+ts toggle subscriber list entries
+f emails in file [$file_emails]
+k keywords in file [$keywords]
+r remove duplicates [$email_remove_duplicates]
+p# pattern match depth [$pattern_depth]
+EOT
+ }
+ print STDERR
+"\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): ";
+
+ my $input = <STDIN>;
+ chomp($input);
+
+ $redraw = 1;
+ my $rerun = 0;
+ my @wish = split(/[, ]+/, $input);
+ foreach my $nr (@wish) {
+ $nr = lc($nr);
+ my $sel = substr($nr, 0, 1);
+ my $str = substr($nr, 1);
+ my $val = 0;
+ $val = $1 if $str =~ /^(\d+)$/;
+
+ if ($sel eq "y") {
+ $interactive = 0;
+ $done = 1;
+ $output_rolestats = 0;
+ $output_roles = 0;
+ last;
+ } elsif ($nr =~ /^\d+$/ && $nr > 0 && $nr <= $count) {
+ $selected{$nr - 1} = !$selected{$nr - 1};
+ } elsif ($sel eq "*" || $sel eq '^') {
+ my $toggle = 0;
+ $toggle = 1 if ($sel eq '*');
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = $toggle;
+ }
+ } elsif ($sel eq "0") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i};
+ }
+ } elsif ($sel eq "t") {
+ if (lc($str) eq "m") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i}
+ if ($list[$i]->[1] =~ /^(maintainer|supporter)/i);
+ }
+ } elsif (lc($str) eq "g") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i}
+ if ($list[$i]->[1] =~ /^(author|commit|signer)/i);
+ }
+ } elsif (lc($str) eq "l") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i}
+ if ($list[$i]->[1] =~ /^(open list)/i);
+ }
+ } elsif (lc($str) eq "s") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i}
+ if ($list[$i]->[1] =~ /^(subscriber list)/i);
+ }
+ }
+ } elsif ($sel eq "a") {
+ if ($val > 0 && $val <= $count) {
+ $authored{$val - 1} = !$authored{$val - 1};
+ } elsif ($str eq '*' || $str eq '^') {
+ my $toggle = 0;
+ $toggle = 1 if ($str eq '*');
+ for (my $i = 0; $i < $count; $i++) {
+ $authored{$i} = $toggle;
+ }
+ }
+ } elsif ($sel eq "s") {
+ if ($val > 0 && $val <= $count) {
+ $signed{$val - 1} = !$signed{$val - 1};
+ } elsif ($str eq '*' || $str eq '^') {
+ my $toggle = 0;
+ $toggle = 1 if ($str eq '*');
+ for (my $i = 0; $i < $count; $i++) {
+ $signed{$i} = $toggle;
+ }
+ }
+ } elsif ($sel eq "o") {
+ $print_options = 1;
+ $redraw = 1;
+ } elsif ($sel eq "g") {
+ if ($str eq "f") {
+ bool_invert(\$email_git_fallback);
+ } else {
+ bool_invert(\$email_git);
+ }
+ $rerun = 1;
+ } elsif ($sel eq "b") {
+ if ($str eq "s") {
+ bool_invert(\$email_git_blame_signatures);
+ } else {
+ bool_invert(\$email_git_blame);
+ }
+ $rerun = 1;
+ } elsif ($sel eq "c") {
+ if ($val > 0) {
+ $email_git_min_signatures = $val;
+ $rerun = 1;
+ }
+ } elsif ($sel eq "x") {
+ if ($val > 0) {
+ $email_git_max_maintainers = $val;
+ $rerun = 1;
+ }
+ } elsif ($sel eq "%") {
+ if ($str ne "" && $val >= 0) {
+ $email_git_min_percent = $val;
+ $rerun = 1;
+ }
+ } elsif ($sel eq "d") {
+ if (vcs_is_git()) {
+ $email_git_since = $str;
+ } elsif (vcs_is_hg()) {
+ $email_hg_since = $str;
+ }
+ $rerun = 1;
+ } elsif ($sel eq "t") {
+ bool_invert(\$email_git_all_signature_types);
+ $rerun = 1;
+ } elsif ($sel eq "f") {
+ bool_invert(\$file_emails);
+ $rerun = 1;
+ } elsif ($sel eq "r") {
+ bool_invert(\$email_remove_duplicates);
+ $rerun = 1;
+ } elsif ($sel eq "m") {
+ bool_invert(\$email_use_mailmap);
+ read_mailmap();
+ $rerun = 1;
+ } elsif ($sel eq "k") {
+ bool_invert(\$keywords);
+ $rerun = 1;
+ } elsif ($sel eq "p") {
+ if ($str ne "" && $val >= 0) {
+ $pattern_depth = $val;
+ $rerun = 1;
+ }
+ } elsif ($sel eq "h" || $sel eq "?") {
+ print STDERR <<EOT
+
+Interactive mode allows you to select the various maintainers, submitters,
+commit signers and mailing lists that could be CC'd on a patch.
+
+Any *'d entry is selected.
+
+If you have git or hg installed, you can choose to summarize the commit
+history of files in the patch. Also, each line of the current file can
+be matched to its commit author and that commits signers with blame.
+
+Various knobs exist to control the length of time for active commit
+tracking, the maximum number of commit authors and signers to add,
+and such.
+
+Enter selections at the prompt until you are satisfied that the selected
+maintainers are appropriate. You may enter multiple selections separated
+by either commas or spaces.
+
+EOT
+ } else {
+ print STDERR "invalid option: '$nr'\n";
+ $redraw = 0;
+ }
+ }
+ if ($rerun) {
+ print STDERR "git-blame can be very slow, please have patience..."
+ if ($email_git_blame);
+ goto &get_maintainers;
+ }
+ }
+
+ #drop not selected entries
+ $count = 0;
+ my @new_emailto = ();
+ foreach my $entry (@list) {
+ if ($selected{$count}) {
+ push(@new_emailto, $list[$count]);
+ }
+ $count++;
+ }
+ return @new_emailto;
+}
+
+sub bool_invert {
+ my ($bool_ref) = @_;
+
+ if ($$bool_ref) {
+ $$bool_ref = 0;
+ } else {
+ $$bool_ref = 1;
+ }
+}
+
+sub deduplicate_email {
+ my ($email) = @_;
+
+ my $matched = 0;
+ my ($name, $address) = parse_email($email);
+ $email = format_email($name, $address, 1);
+ $email = mailmap_email($email);
+
+ return $email if (!$email_remove_duplicates);
+
+ ($name, $address) = parse_email($email);
+
+ if ($name ne "" && $deduplicate_name_hash{lc($name)}) {
+ $name = $deduplicate_name_hash{lc($name)}->[0];
+ $address = $deduplicate_name_hash{lc($name)}->[1];
+ $matched = 1;
+ } elsif ($deduplicate_address_hash{lc($address)}) {
+ $name = $deduplicate_address_hash{lc($address)}->[0];
+ $address = $deduplicate_address_hash{lc($address)}->[1];
+ $matched = 1;
+ }
+ if (!$matched) {
+ $deduplicate_name_hash{lc($name)} = [ $name, $address ];
+ $deduplicate_address_hash{lc($address)} = [ $name, $address ];
+ }
+ $email = format_email($name, $address, 1);
+ $email = mailmap_email($email);
+ return $email;
+}
+
+sub save_commits_by_author {
+ my (@lines) = @_;
+
+ my @authors = ();
+ my @commits = ();
+ my @subjects = ();
+
+ foreach my $line (@lines) {
+ if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+ my $author = $1;
+ $author = deduplicate_email($author);
+ push(@authors, $author);
+ }
+ push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+ push(@subjects, $1) if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+ }
+
+ for (my $i = 0; $i < @authors; $i++) {
+ my $exists = 0;
+ foreach my $ref(@{$commit_author_hash{$authors[$i]}}) {
+ if (@{$ref}[0] eq $commits[$i] &&
+ @{$ref}[1] eq $subjects[$i]) {
+ $exists = 1;
+ last;
+ }
+ }
+ if (!$exists) {
+ push(@{$commit_author_hash{$authors[$i]}},
+ [ ($commits[$i], $subjects[$i]) ]);
+ }
+ }
+}
+
+sub save_commits_by_signer {
+ my (@lines) = @_;
+
+ my $commit = "";
+ my $subject = "";
+
+ foreach my $line (@lines) {
+ $commit = $1 if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+ $subject = $1 if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+ if ($line =~ /^[ \t]*${signature_pattern}.*\@.*$/) {
+ my @signatures = ($line);
+ my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+ my @types = @$types_ref;
+ my @signers = @$signers_ref;
+
+ my $type = $types[0];
+ my $signer = $signers[0];
+
+ $signer = deduplicate_email($signer);
+
+ my $exists = 0;
+ foreach my $ref(@{$commit_signer_hash{$signer}}) {
+ if (@{$ref}[0] eq $commit &&
+ @{$ref}[1] eq $subject &&
+ @{$ref}[2] eq $type) {
+ $exists = 1;
+ last;
+ }
+ }
+ if (!$exists) {
+ push(@{$commit_signer_hash{$signer}},
+ [ ($commit, $subject, $type) ]);
+ }
+ }
+ }
+}
+
sub vcs_assign {
my ($role, $divisor, @lines) = @_;
@@ -1007,9 +1760,9 @@ sub vcs_assign {
$divisor = 1;
}
- if ($email_remove_duplicates) {
- @lines = mailmap(@lines);
- }
+ @lines = mailmap(@lines);
+
+ return if (@lines <= 0);
@lines = sort(@lines);
@@ -1042,12 +1795,18 @@ sub vcs_file_signoffs {
my @signers = ();
my $commits;
- return if (!vcs_exists());
+ $vcs_used = vcs_exists();
+ return if (!$vcs_used);
my $cmd = $VCS_cmds{"find_signers_cmd"};
$cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
($commits, @signers) = vcs_find_signers($cmd);
+
+ foreach my $signer (@signers) {
+ $signer = deduplicate_email($signer);
+ }
+
vcs_assign("commit_signer", $commits, @signers);
}
@@ -1055,29 +1814,114 @@ sub vcs_file_blame {
my ($file) = @_;
my @signers = ();
+ my @all_commits = ();
my @commits = ();
my $total_commits;
+ my $total_lines;
- return if (!vcs_exists());
+ $vcs_used = vcs_exists();
+ return if (!$vcs_used);
- @commits = vcs_blame($file);
- @commits = uniq(@commits);
+ @all_commits = vcs_blame($file);
+ @commits = uniq(@all_commits);
$total_commits = @commits;
+ $total_lines = @all_commits;
- foreach my $commit (@commits) {
- my $commit_count;
- my @commit_signers = ();
+ if ($email_git_blame_signatures) {
+ if (vcs_is_hg()) {
+ my $commit_count;
+ my @commit_signers = ();
+ my $commit = join(" -r ", @commits);
+ my $cmd;
+
+ $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
+
+ ($commit_count, @commit_signers) = vcs_find_signers($cmd);
+
+ push(@signers, @commit_signers);
+ } else {
+ foreach my $commit (@commits) {
+ my $commit_count;
+ my @commit_signers = ();
+ my $cmd;
- my $cmd = $VCS_cmds{"find_commit_signers_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
- ($commit_count, @commit_signers) = vcs_find_signers($cmd);
- push(@signers, @commit_signers);
+ ($commit_count, @commit_signers) = vcs_find_signers($cmd);
+
+ push(@signers, @commit_signers);
+ }
+ }
}
if ($from_filename) {
+ if ($output_rolestats) {
+ my @blame_signers;
+ if (vcs_is_hg()) {{ # Double brace for last exit
+ my $commit_count;
+ my @commit_signers = ();
+ @commits = uniq(@commits);
+ @commits = sort(@commits);
+ my $commit = join(" -r ", @commits);
+ my $cmd;
+
+ $cmd = $VCS_cmds{"find_commit_author_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
+
+ my @lines = ();
+
+ @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+ if (!$email_git_penguin_chiefs) {
+ @lines = grep(!/${penguin_chiefs}/i, @lines);
+ }
+
+ last if !@lines;
+
+ my @authors = ();
+ foreach my $line (@lines) {
+ if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+ my $author = $1;
+ $author = deduplicate_email($author);
+ push(@authors, $author);
+ }
+ }
+
+ save_commits_by_author(@lines) if ($interactive);
+ save_commits_by_signer(@lines) if ($interactive);
+
+ push(@signers, @authors);
+ }}
+ else {
+ foreach my $commit (@commits) {
+ my $i;
+ my $cmd = $VCS_cmds{"find_commit_author_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ my @author = vcs_find_author($cmd);
+ next if !@author;
+
+ my $formatted_author = deduplicate_email($author[0]);
+
+ my $count = grep(/$commit/, @all_commits);
+ for ($i = 0; $i < $count ; $i++) {
+ push(@blame_signers, $formatted_author);
+ }
+ }
+ }
+ if (@blame_signers) {
+ vcs_assign("authored lines", $total_lines, @blame_signers);
+ }
+ }
+ foreach my $signer (@signers) {
+ $signer = deduplicate_email($signer);
+ }
vcs_assign("commits", $total_commits, @signers);
} else {
+ foreach my $signer (@signers) {
+ $signer = deduplicate_email($signer);
+ }
vcs_assign("modified commits", $total_commits, @signers);
}
}
@@ -1099,6 +1943,51 @@ sub sort_and_uniq {
return @parms;
}
+sub clean_file_emails {
+ my (@file_emails) = @_;
+ my @fmt_emails = ();
+
+ foreach my $email (@file_emails) {
+ $email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
+ my ($name, $address) = parse_email($email);
+ if ($name eq '"[,\.]"') {
+ $name = "";
+ }
+
+ my @nw = split(/[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name);
+ if (@nw > 2) {
+ my $first = $nw[@nw - 3];
+ my $middle = $nw[@nw - 2];
+ my $last = $nw[@nw - 1];
+
+ if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
+ (length($first) == 2 && substr($first, -1) eq ".")) ||
+ (length($middle) == 1 ||
+ (length($middle) == 2 && substr($middle, -1) eq "."))) {
+ $name = "$first $middle $last";
+ } else {
+ $name = "$middle $last";
+ }
+ }
+
+ if (substr($name, -1) =~ /[,\.]/) {
+ $name = substr($name, 0, length($name) - 1);
+ } elsif (substr($name, -2) =~ /[,\.]"/) {
+ $name = substr($name, 0, length($name) - 2) . '"';
+ }
+
+ if (substr($name, 0, 1) =~ /[,\.]/) {
+ $name = substr($name, 1, length($name) - 1);
+ } elsif (substr($name, 0, 2) =~ /"[,\.]/) {
+ $name = '"' . substr($name, 2, length($name) - 2);
+ }
+
+ my $fmt_email = format_email($name, $address, $email_usename);
+ push(@fmt_emails, $fmt_email);
+ }
+ return @fmt_emails;
+}
+
sub merge_email {
my @lines;
my %saw;
@@ -1183,7 +2072,7 @@ sub rfc822_strip_comments {
# valid: returns true if the parameter is an RFC822 valid address
#
-sub rfc822_valid ($) {
+sub rfc822_valid {
my $s = rfc822_strip_comments(shift);
if (!$rfc822re) {
@@ -1203,7 +2092,7 @@ sub rfc822_valid ($) {
# from success with no addresses found, because an empty string is
# a valid list.
-sub rfc822_validlist ($) {
+sub rfc822_validlist {
my $s = rfc822_strip_comments(shift);
if (!$rfc822re) {
diff --git a/scripts/gfp-translate b/scripts/gfp-translate
index 073cb6d152a0..c9230e158a8f 100644
--- a/scripts/gfp-translate
+++ b/scripts/gfp-translate
@@ -19,7 +19,7 @@ usage() {
exit 0
}
-# Parse command-line arguements
+# Parse command-line arguments
while [ $# -gt 0 ]; do
case $1 in
--source)
@@ -63,7 +63,12 @@ fi
# Extract GFP flags from the kernel source
TMPFILE=`mktemp -t gfptranslate-XXXXXX` || exit 1
-grep "^#define __GFP" $SOURCE/include/linux/gfp.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE
+grep -q ___GFP $SOURCE/include/linux/gfp.h
+if [ $? -eq 0 ]; then
+ grep "^#define ___GFP" $SOURCE/include/linux/gfp.h | sed -e 's/u$//' | grep -v GFP_BITS > $TMPFILE
+else
+ grep "^#define __GFP" $SOURCE/include/linux/gfp.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE
+fi
# Parse the flags
IFS="
diff --git a/scripts/headers.sh b/scripts/headers.sh
index 1ddcdd38d97f..978b42b3acd7 100755
--- a/scripts/headers.sh
+++ b/scripts/headers.sh
@@ -13,7 +13,7 @@ do_command()
fi
}
-archs=$(ls ${srctree}/arch)
+archs=${HDR_ARCH_LIST:-$(ls ${srctree}/arch)}
for arch in ${archs}; do
case ${arch} in
diff --git a/scripts/headers_install.pl b/scripts/headers_install.pl
index 4ca3be3b2e50..efb3be10d428 100644
--- a/scripts/headers_install.pl
+++ b/scripts/headers_install.pl
@@ -45,6 +45,13 @@ foreach my $file (@files) {
close $in;
system $unifdef . " $tmpfile > $installdir/$file";
+ # unifdef will exit 0 on success, and will exit 1 when the
+ # file was processed successfully but no changes were made,
+ # so abort only when it's higher than that.
+ my $e = $? >> 8;
+ if ($e > 1) {
+ die "$tmpfile: $!\n";
+ }
unlink $tmpfile;
}
exit 0;
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index e3902fb39afd..60dd3eb9366e 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -107,12 +107,8 @@ static int read_symbol(FILE *in, struct sym_entry *s)
rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
if (rc != 3) {
- if (rc != EOF) {
- /* skip line. sym is used as dummy to
- * shut of "warn_unused_result" warning.
- */
- sym = fgets(str, 500, in);
- }
+ if (rc != EOF && fgets(str, 500, in) == NULL)
+ fprintf(stderr, "Read error or end of file.\n");
return -1;
}
diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
index 6a36a76e6606..624f6502e03e 100644
--- a/scripts/kconfig/.gitignore
+++ b/scripts/kconfig/.gitignore
@@ -17,6 +17,7 @@ gconf.glade.h
#
conf
mconf
+nconf
qconf
gconf
kxgettext
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 75bdf5ae202c..368ae306aee4 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -8,7 +8,7 @@ PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-c
ifdef KBUILD_KCONFIG
Kconfig := $(KBUILD_KCONFIG)
else
-Kconfig := arch/$(SRCARCH)/Kconfig
+Kconfig := Kconfig
endif
xconfig: $(obj)/qconf
@@ -21,44 +21,54 @@ menuconfig: $(obj)/mconf
$< $(Kconfig)
config: $(obj)/conf
- $< $(Kconfig)
+ $< --oldaskconfig $(Kconfig)
nconfig: $(obj)/nconf
$< $(Kconfig)
oldconfig: $(obj)/conf
- $< -o $(Kconfig)
+ $< --$@ $(Kconfig)
silentoldconfig: $(obj)/conf
$(Q)mkdir -p include/generated
- $< -s $(Kconfig)
+ $< --$@ $(Kconfig)
+
+# if no path is given, then use src directory to find file
+ifdef LSMOD
+LSMOD_F := $(LSMOD)
+ifeq ($(findstring /,$(LSMOD)),)
+ LSMOD_F := $(objtree)/$(LSMOD)
+endif
+endif
localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
- $(Q)perl $< $(srctree) $(Kconfig) > .tmp.config
- $(Q)if [ -f .config ]; then \
- cmp -s .tmp.config .config || \
- (mv -f .config .config.old.1; \
- mv -f .tmp.config .config; \
- $(obj)/conf -s $(Kconfig); \
- mv -f .config.old.1 .config.old) \
- else \
- mv -f .tmp.config .config; \
- $(obj)/conf -s $(Kconfig); \
+ $(Q)mkdir -p include/generated
+ $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config
+ $(Q)if [ -f .config ]; then \
+ cmp -s .tmp.config .config || \
+ (mv -f .config .config.old.1; \
+ mv -f .tmp.config .config; \
+ $(obj)/conf --silentoldconfig $(Kconfig); \
+ mv -f .config.old.1 .config.old) \
+ else \
+ mv -f .tmp.config .config; \
+ $(obj)/conf --silentoldconfig $(Kconfig); \
fi
$(Q)rm -f .tmp.config
localyesconfig: $(obj)/streamline_config.pl $(obj)/conf
- $(Q)perl $< $(srctree) $(Kconfig) > .tmp.config
+ $(Q)mkdir -p include/generated
+ $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config
$(Q)sed -i s/=m/=y/ .tmp.config
- $(Q)if [ -f .config ]; then \
- cmp -s .tmp.config .config || \
- (mv -f .config .config.old.1; \
- mv -f .tmp.config .config; \
- $(obj)/conf -s $(Kconfig); \
- mv -f .config.old.1 .config.old) \
- else \
- mv -f .tmp.config .config; \
- $(obj)/conf -s $(Kconfig); \
+ $(Q)if [ -f .config ]; then \
+ cmp -s .tmp.config .config || \
+ (mv -f .config .config.old.1; \
+ mv -f .tmp.config .config; \
+ $(obj)/conf --silentoldconfig $(Kconfig); \
+ mv -f .config.old.1 .config.old) \
+ else \
+ mv -f .tmp.config .config; \
+ $(obj)/conf --silentoldconfig $(Kconfig); \
fi
$(Q)rm -f .tmp.config
@@ -85,30 +95,29 @@ update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
$(Q)rm -f arch/um/Kconfig.arch
$(Q)rm -f $(obj)/config.pot
-PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig
+PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
-randconfig: $(obj)/conf
- $< -r $(Kconfig)
+allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
+ $< --$@ $(Kconfig)
-allyesconfig: $(obj)/conf
- $< -y $(Kconfig)
+PHONY += listnewconfig oldnoconfig savedefconfig defconfig
-allnoconfig: $(obj)/conf
- $< -n $(Kconfig)
+listnewconfig oldnoconfig: $(obj)/conf
+ $< --$@ $(Kconfig)
-allmodconfig: $(obj)/conf
- $< -m $(Kconfig)
+savedefconfig: $(obj)/conf
+ $< --$@=defconfig $(Kconfig)
defconfig: $(obj)/conf
ifeq ($(KBUILD_DEFCONFIG),)
- $< -d $(Kconfig)
+ $< --defconfig $(Kconfig)
else
@echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
- $(Q)$< -D arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
+ $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
endif
%_defconfig: $(obj)/conf
- $(Q)$< -D arch/$(SRCARCH)/configs/$@ $(Kconfig)
+ $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
# Help text used by make help
help:
@@ -121,22 +130,23 @@ help:
@echo ' localmodconfig - Update current config disabling modules not loaded'
@echo ' localyesconfig - Update current config converting local mods to core'
@echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps'
- @echo ' randconfig - New config with random answer to all options'
- @echo ' defconfig - New config with default answer to all options'
- @echo ' allmodconfig - New config selecting modules when possible'
- @echo ' allyesconfig - New config where all options are accepted with yes'
+ @echo ' defconfig - New config with default from ARCH supplied defconfig'
+ @echo ' savedefconfig - Save current config as ./defconfig (minimal config)'
@echo ' allnoconfig - New config where all options are answered with no'
+ @echo ' allyesconfig - New config where all options are accepted with yes'
+ @echo ' allmodconfig - New config selecting modules when possible'
+ @echo ' alldefconfig - New config with all symbols set to default'
+ @echo ' randconfig - New config with random answer to all options'
+ @echo ' listnewconfig - List new options'
+ @echo ' oldnoconfig - Same as silentoldconfig but set new symbols to n (unset)'
# lxdialog stuff
check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
# Use recursively expanded variables so we do not call gcc unless
# we really need to do so. (Do not call gcc as part of make mrproper)
-HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
-HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
-
-HOST_EXTRACFLAGS += -DLOCALE
-
+HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
+ -DLOCALE
# ===========================================================================
# Shared Makefile for the various kconfig executables:
@@ -195,7 +205,7 @@ clean-files += config.pot linux.pot
PHONY += $(obj)/dochecklxdialog
$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog
$(obj)/dochecklxdialog:
- $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES)
+ $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf)
always := dochecklxdialog
@@ -209,10 +219,12 @@ HOSTCFLAGS_zconf.tab.o := -I$(src)
HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl
HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
-HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
+HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` -ldl
HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
-D LKC_DIRECT_LINK
+HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
+
HOSTLOADLIBES_nconf = -lmenu -lpanel -lncurses
$(obj)/qconf.o: $(obj)/.tmp_qtcheck
@@ -223,40 +235,48 @@ $(obj)/.tmp_qtcheck: $(src)/Makefile
# QT needs some extra effort...
$(obj)/.tmp_qtcheck:
@set -e; echo " CHECK qt"; dir=""; pkg=""; \
- pkg-config --exists qt 2> /dev/null && pkg=qt; \
- pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \
- if [ -n "$$pkg" ]; then \
- cflags="\$$(shell pkg-config $$pkg --cflags)"; \
- libs="\$$(shell pkg-config $$pkg --libs)"; \
- moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \
- dir="$$(pkg-config $$pkg --variable=prefix)"; \
+ if ! pkg-config --exists QtCore 2> /dev/null; then \
+ echo "* Unable to find the QT4 tool qmake. Trying to use QT3"; \
+ pkg-config --exists qt 2> /dev/null && pkg=qt; \
+ pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \
+ if [ -n "$$pkg" ]; then \
+ cflags="\$$(shell pkg-config $$pkg --cflags)"; \
+ libs="\$$(shell pkg-config $$pkg --libs)"; \
+ moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \
+ dir="$$(pkg-config $$pkg --variable=prefix)"; \
+ else \
+ for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \
+ if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
+ done; \
+ if [ -z "$$dir" ]; then \
+ echo "*"; \
+ echo "* Unable to find any QT installation. Please make sure that"; \
+ echo "* the QT4 or QT3 development package is correctly installed and"; \
+ echo "* either qmake can be found or install pkg-config or set"; \
+ echo "* the QTDIR environment variable to the correct location."; \
+ echo "*"; \
+ false; \
+ fi; \
+ libpath=$$dir/lib; lib=qt; osdir=""; \
+ $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \
+ osdir=x$$($(HOSTCXX) -print-multi-os-directory); \
+ test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \
+ test -f $$libpath/libqt-mt.so && lib=qt-mt; \
+ cflags="-I$$dir/include"; \
+ libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \
+ moc="$$dir/bin/moc"; \
+ fi; \
+ if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \
+ echo "*"; \
+ echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \
+ echo "*"; \
+ moc="/usr/bin/moc"; \
+ fi; \
else \
- for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \
- if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
- done; \
- if [ -z "$$dir" ]; then \
- echo "*"; \
- echo "* Unable to find the QT3 installation. Please make sure that"; \
- echo "* the QT3 development package is correctly installed and"; \
- echo "* either install pkg-config or set the QTDIR environment"; \
- echo "* variable to the correct location."; \
- echo "*"; \
- false; \
- fi; \
- libpath=$$dir/lib; lib=qt; osdir=""; \
- $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \
- osdir=x$$($(HOSTCXX) -print-multi-os-directory); \
- test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \
- test -f $$libpath/libqt-mt.so && lib=qt-mt; \
- cflags="-I$$dir/include"; \
- libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \
- moc="$$dir/bin/moc"; \
- fi; \
- if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \
- echo "*"; \
- echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \
- echo "*"; \
- moc="/usr/bin/moc"; \
+ cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \
+ libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \
+ binpath="\$$(shell pkg-config QtCore --variable=prefix)"; \
+ moc="$$binpath/bin/moc"; \
fi; \
echo "KC_QT_CFLAGS=$$cflags" > $@; \
echo "KC_QT_LIBS=$$libs" >> $@; \
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 9960d1c303f8..659326c3e895 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -10,6 +10,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <getopt.h>
#include <sys/stat.h>
#include <sys/time.h>
@@ -19,16 +20,21 @@
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;
+enum input_mode {
+ oldaskconfig,
+ silentoldconfig,
+ oldconfig,
+ allnoconfig,
+ allyesconfig,
+ allmodconfig,
+ alldefconfig,
+ randconfig,
+ defconfig,
+ savedefconfig,
+ listnewconfig,
+ oldnoconfig,
+} input_mode = oldaskconfig;
+
char *defconfig_file;
static int indent = 1;
@@ -93,16 +99,16 @@ static int conf_askvalue(struct symbol *sym, const char *def)
}
switch (input_mode) {
- case ask_new:
- case ask_silent:
+ case oldconfig:
+ case silentoldconfig:
if (sym_has_value(sym)) {
printf("%s\n", def);
return 0;
}
check_stdin();
- case ask_all:
+ case oldaskconfig:
fflush(stdout);
- fgets(line, 128, stdin);
+ xfgets(line, 128, stdin);
return 1;
default:
break;
@@ -156,14 +162,12 @@ static int conf_string(struct menu *menu)
static int conf_sym(struct menu *menu)
{
struct symbol *sym = menu->sym;
- int type;
tristate oldval, newval;
while (1) {
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
if (sym->name)
printf("(%s) ", sym->name);
- type = sym_get_type(sym);
putchar('[');
oldval = sym_get_tristate_value(sym);
switch (oldval) {
@@ -228,11 +232,9 @@ static int conf_choice(struct menu *menu)
{
struct symbol *sym, *def_sym;
struct menu *child;
- int type;
bool is_new;
sym = menu->sym;
- type = sym_get_type(sym);
is_new = !sym_has_value(sym);
if (sym_is_changable(sym)) {
conf_sym(menu);
@@ -294,17 +296,17 @@ static int conf_choice(struct menu *menu)
printf("?");
printf("]: ");
switch (input_mode) {
- case ask_new:
- case ask_silent:
+ case oldconfig:
+ case silentoldconfig:
if (!is_new) {
cnt = def;
printf("%d\n", cnt);
break;
}
check_stdin();
- case ask_all:
+ case oldaskconfig:
fflush(stdout);
- fgets(line, 128, stdin);
+ xfgets(line, 128, stdin);
strip(line);
if (line[0] == '?') {
print_help(menu);
@@ -360,7 +362,10 @@ static void conf(struct menu *menu)
switch (prop->type) {
case P_MENU:
- if (input_mode == ask_silent && rootEntry != menu) {
+ if ((input_mode == silentoldconfig ||
+ input_mode == listnewconfig ||
+ input_mode == oldnoconfig) &&
+ rootEntry != menu) {
check_conf(menu);
return;
}
@@ -418,10 +423,16 @@ static void check_conf(struct menu *menu)
if (sym && !sym_has_value(sym)) {
if (sym_is_changable(sym) ||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
- if (!conf_cnt++)
- printf(_("*\n* Restart config...\n*\n"));
- rootEntry = menu_get_parent_menu(menu);
- conf(rootEntry);
+ if (input_mode == listnewconfig) {
+ if (sym->name && !sym_is_choice_value(sym)) {
+ printf("%s%s\n", CONFIG_, sym->name);
+ }
+ } else if (input_mode != oldnoconfig) {
+ if (!conf_cnt++)
+ printf(_("*\n* Restart config...\n*\n"));
+ rootEntry = menu_get_parent_menu(menu);
+ conf(rootEntry);
+ }
}
}
@@ -429,6 +440,22 @@ static void check_conf(struct menu *menu)
check_conf(child);
}
+static struct option long_opts[] = {
+ {"oldaskconfig", no_argument, NULL, oldaskconfig},
+ {"oldconfig", no_argument, NULL, oldconfig},
+ {"silentoldconfig", no_argument, NULL, silentoldconfig},
+ {"defconfig", optional_argument, NULL, defconfig},
+ {"savedefconfig", required_argument, NULL, savedefconfig},
+ {"allnoconfig", no_argument, NULL, allnoconfig},
+ {"allyesconfig", no_argument, NULL, allyesconfig},
+ {"allmodconfig", no_argument, NULL, allmodconfig},
+ {"alldefconfig", no_argument, NULL, alldefconfig},
+ {"randconfig", no_argument, NULL, randconfig},
+ {"listnewconfig", no_argument, NULL, listnewconfig},
+ {"oldnoconfig", no_argument, NULL, oldnoconfig},
+ {NULL, 0, NULL, 0}
+};
+
int main(int ac, char **av)
{
int opt;
@@ -439,32 +466,17 @@ int main(int ac, char **av)
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
+ while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
+ input_mode = (enum input_mode)opt;
switch (opt) {
- case 'o':
- input_mode = ask_silent;
- break;
- case 's':
- input_mode = ask_silent;
+ case silentoldconfig:
sync_kconfig = 1;
break;
- case 'd':
- input_mode = set_default;
- break;
- case 'D':
- input_mode = set_default;
+ case defconfig:
+ case savedefconfig:
defconfig_file = optarg;
break;
- case 'n':
- input_mode = set_no;
- break;
- case 'm':
- input_mode = set_mod;
- break;
- case 'y':
- input_mode = set_yes;
- break;
- case 'r':
+ case randconfig:
{
struct timeval now;
unsigned int seed;
@@ -477,17 +489,12 @@ int main(int ac, char **av)
seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
srand(seed);
-
- input_mode = set_random;
break;
}
- case 'h':
- printf(_("See README for usage info\n"));
- exit(0);
- break;
- default:
+ case '?':
fprintf(stderr, _("See README for usage info\n"));
exit(1);
+ break;
}
}
if (ac == optind) {
@@ -501,8 +508,7 @@ int main(int ac, char **av)
name = conf_get_configname();
if (stat(name, &tmpstat)) {
fprintf(stderr, _("***\n"
- "*** You have not yet configured your kernel!\n"
- "*** (missing kernel config file \"%s\")\n"
+ "*** Configuration file \"%s\" not found!\n"
"***\n"
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
"*** \"make menuconfig\" or \"make xconfig\").\n"
@@ -512,7 +518,7 @@ int main(int ac, char **av)
}
switch (input_mode) {
- case set_default:
+ case defconfig:
if (!defconfig_file)
defconfig_file = conf_get_default_confname();
if (conf_read(defconfig_file)) {
@@ -522,25 +528,30 @@ int main(int ac, char **av)
exit(1);
}
break;
- case ask_silent:
- case ask_all:
- case ask_new:
+ case savedefconfig:
+ case silentoldconfig:
+ case oldaskconfig:
+ case oldconfig:
+ case listnewconfig:
+ case oldnoconfig:
conf_read(NULL);
break;
- case set_no:
- case set_mod:
- case set_yes:
- case set_random:
+ case allnoconfig:
+ case allyesconfig:
+ case allmodconfig:
+ case alldefconfig:
+ case randconfig:
name = getenv("KCONFIG_ALLCONFIG");
if (name && !stat(name, &tmpstat)) {
conf_read_simple(name, S_DEF_USER);
break;
}
switch (input_mode) {
- case set_no: name = "allno.config"; break;
- case set_mod: name = "allmod.config"; break;
- case set_yes: name = "allyes.config"; break;
- case set_random: name = "allrandom.config"; break;
+ case allnoconfig: name = "allno.config"; break;
+ case allyesconfig: name = "allyes.config"; break;
+ case allmodconfig: name = "allmod.config"; break;
+ case alldefconfig: name = "alldef.config"; break;
+ case randconfig: name = "allrandom.config"; break;
default: break;
}
if (!stat(name, &tmpstat))
@@ -557,7 +568,7 @@ int main(int ac, char **av)
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
fprintf(stderr,
- _("\n*** Kernel configuration requires explicit update.\n\n"));
+ _("\n*** The configuration requires explicit update.\n\n"));
return 1;
}
}
@@ -565,33 +576,42 @@ int main(int ac, char **av)
}
switch (input_mode) {
- case set_no:
+ case allnoconfig:
conf_set_all_new_symbols(def_no);
break;
- case set_yes:
+ case allyesconfig:
conf_set_all_new_symbols(def_yes);
break;
- case set_mod:
+ case allmodconfig:
conf_set_all_new_symbols(def_mod);
break;
- case set_random:
+ case alldefconfig:
+ conf_set_all_new_symbols(def_default);
+ break;
+ case randconfig:
conf_set_all_new_symbols(def_random);
break;
- case set_default:
+ case defconfig:
conf_set_all_new_symbols(def_default);
break;
- case ask_new:
- case ask_all:
+ case savedefconfig:
+ break;
+ case oldaskconfig:
rootEntry = &rootmenu;
conf(&rootmenu);
- input_mode = ask_silent;
+ input_mode = silentoldconfig;
/* fall through */
- case ask_silent:
+ case oldconfig:
+ case listnewconfig:
+ case oldnoconfig:
+ case silentoldconfig:
/* Update until a loop caused no more changes */
do {
conf_cnt = 0;
check_conf(&rootmenu);
- } while (conf_cnt);
+ } while (conf_cnt &&
+ (input_mode != listnewconfig &&
+ input_mode != oldnoconfig));
break;
}
@@ -600,18 +620,35 @@ int main(int ac, char **av)
* All other commands are only used to generate a config.
*/
if (conf_get_changed() && conf_write(NULL)) {
- fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
+ fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
exit(1);
}
if (conf_write_autoconf()) {
- fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n"));
+ fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
return 1;
}
- } else {
+ } else if (input_mode == savedefconfig) {
+ if (conf_write_defconfig(defconfig_file)) {
+ fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
+ defconfig_file);
+ return 1;
+ }
+ } else if (input_mode != listnewconfig) {
if (conf_write(NULL)) {
- fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
+ fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
exit(1);
}
}
return 0;
}
+/*
+ * Helper function to facilitate fgets() by Jean Sacren.
+ */
+void xfgets(str, size, in)
+ char *str;
+ int size;
+ FILE *in;
+{
+ if (fgets(str, size, in) == NULL)
+ fprintf(stderr, "\nError in reading or end of file.\n");
+}
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index c4dec80cfd8e..61c35bf2d9cb 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -5,6 +5,7 @@
#include <sys/stat.h>
#include <ctype.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
@@ -18,6 +19,9 @@
static void conf_warning(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+static void conf_message(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
static const char *conf_filename;
static int conf_lineno, conf_warnings, conf_unsaved;
@@ -34,6 +38,29 @@ static void conf_warning(const char *fmt, ...)
conf_warnings++;
}
+static void conf_default_message_callback(const char *fmt, va_list ap)
+{
+ printf("#\n# ");
+ vprintf(fmt, ap);
+ printf("\n#\n");
+}
+
+static void (*conf_message_callback) (const char *fmt, va_list ap) =
+ conf_default_message_callback;
+void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
+{
+ conf_message_callback = fn;
+}
+
+static void conf_message(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (conf_message_callback)
+ conf_message_callback(fmt, ap);
+}
+
const char *conf_get_configname(void)
{
char *name = getenv("KCONFIG_CONFIG");
@@ -170,8 +197,11 @@ int conf_read_simple(const char *name, int def)
if (in)
goto load;
sym_add_change_count(1);
- if (!sym_defconfig_list)
+ if (!sym_defconfig_list) {
+ if (modules_sym)
+ sym_calc_value(modules_sym);
return 1;
+ }
for_all_defaults(sym_defconfig_list, prop) {
if (expr_calc_value(prop->visible.expr) == no ||
@@ -180,9 +210,8 @@ int conf_read_simple(const char *name, int def)
name = conf_expand_value(prop->expr->left.sym->name);
in = zconf_fopen(name);
if (in) {
- printf(_("#\n"
- "# using defaults found in %s\n"
- "#\n"), name);
+ conf_message(_("using defaults found in %s"),
+ name);
goto load;
}
}
@@ -217,24 +246,23 @@ load:
while (fgets(line, sizeof(line), in)) {
conf_lineno++;
sym = NULL;
- switch (line[0]) {
- case '#':
- if (memcmp(line + 2, "CONFIG_", 7))
+ if (line[0] == '#') {
+ if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
continue;
- p = strchr(line + 9, ' ');
+ p = strchr(line + 2 + strlen(CONFIG_), ' ');
if (!p)
continue;
*p++ = 0;
if (strncmp(p, "is not set", 10))
continue;
if (def == S_DEF_USER) {
- sym = sym_find(line + 9);
+ sym = sym_find(line + 2 + strlen(CONFIG_));
if (!sym) {
sym_add_change_count(1);
- break;
+ goto setsym;
}
} else {
- sym = sym_lookup(line + 9, 0);
+ sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
if (sym->type == S_UNKNOWN)
sym->type = S_BOOLEAN;
}
@@ -250,13 +278,8 @@ load:
default:
;
}
- break;
- case 'C':
- if (memcmp(line, "CONFIG_", 7)) {
- conf_warning("unexpected data");
- continue;
- }
- p = strchr(line + 7, '=');
+ } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
+ p = strchr(line + strlen(CONFIG_), '=');
if (!p)
continue;
*p++ = 0;
@@ -267,13 +290,13 @@ load:
*p2 = 0;
}
if (def == S_DEF_USER) {
- sym = sym_find(line + 7);
+ sym = sym_find(line + strlen(CONFIG_));
if (!sym) {
sym_add_change_count(1);
- break;
+ goto setsym;
}
} else {
- sym = sym_lookup(line + 7, 0);
+ sym = sym_lookup(line + strlen(CONFIG_), 0);
if (sym->type == S_UNKNOWN)
sym->type = S_OTHER;
}
@@ -282,14 +305,12 @@ load:
}
if (conf_set_sym_val(sym, def, def_flags, p))
continue;
- break;
- case '\r':
- case '\n':
- break;
- default:
- conf_warning("unexpected data");
+ } else {
+ if (line[0] != '\r' && line[0] != '\n')
+ conf_warning("unexpected data");
continue;
}
+setsym:
if (sym && sym_is_choice_value(sym)) {
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
switch (sym->def[def].tri) {
@@ -396,15 +417,149 @@ int conf_read(const char *name)
return 0;
}
+/* Write a S_STRING */
+static void conf_write_string(bool headerfile, const char *name,
+ const char *str, FILE *out)
+{
+ int l;
+ if (headerfile)
+ fprintf(out, "#define %s%s \"", CONFIG_, name);
+ else
+ fprintf(out, "%s%s=\"", CONFIG_, name);
+
+ while (1) {
+ l = strcspn(str, "\"\\");
+ if (l) {
+ xfwrite(str, l, 1, out);
+ str += l;
+ }
+ if (!*str)
+ break;
+ fprintf(out, "\\%c", *str++);
+ }
+ fputs("\"\n", out);
+}
+
+static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no)
+{
+ const char *str;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ if (write_no)
+ fprintf(out, "# %s%s is not set\n",
+ CONFIG_, sym->name);
+ break;
+ case mod:
+ fprintf(out, "%s%s=m\n", CONFIG_, sym->name);
+ break;
+ case yes:
+ fprintf(out, "%s%s=y\n", CONFIG_, sym->name);
+ break;
+ }
+ break;
+ case S_STRING:
+ conf_write_string(false, sym->name, sym_get_string_value(sym), out);
+ break;
+ case S_HEX:
+ case S_INT:
+ str = sym_get_string_value(sym);
+ fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str);
+ break;
+ case S_OTHER:
+ case S_UNKNOWN:
+ break;
+ }
+}
+
+/*
+ * Write out a minimal config.
+ * All values that has default values are skipped as this is redundant.
+ */
+int conf_write_defconfig(const char *filename)
+{
+ struct symbol *sym;
+ struct menu *menu;
+ FILE *out;
+
+ out = fopen(filename, "w");
+ if (!out)
+ return 1;
+
+ sym_clear_all_valid();
+
+ /* Traverse all menus to find all relevant symbols */
+ menu = rootmenu.list;
+
+ while (menu != NULL)
+ {
+ sym = menu->sym;
+ if (sym == NULL) {
+ if (!menu_is_visible(menu))
+ goto next_menu;
+ } else if (!sym_is_choice(sym)) {
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ goto next_menu;
+ sym->flags &= ~SYMBOL_WRITE;
+ /* If we cannot change the symbol - skip */
+ if (!sym_is_changable(sym))
+ goto next_menu;
+ /* If symbol equals to default value - skip */
+ if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
+ goto next_menu;
+
+ /*
+ * If symbol is a choice value and equals to the
+ * default for a choice - skip.
+ * But only if value is bool and equal to "y" and
+ * choice is not "optional".
+ * (If choice is "optional" then all values can be "n")
+ */
+ if (sym_is_choice_value(sym)) {
+ struct symbol *cs;
+ struct symbol *ds;
+
+ cs = prop_get_symbol(sym_get_choice_prop(sym));
+ ds = sym_choice_default(cs);
+ if (!sym_is_optional(cs) && sym == ds) {
+ if ((sym->type == S_BOOLEAN) &&
+ sym_get_tristate_value(sym) == yes)
+ goto next_menu;
+ }
+ }
+ conf_write_symbol(sym, out, true);
+ }
+next_menu:
+ if (menu->list != NULL) {
+ menu = menu->list;
+ }
+ else if (menu->next != NULL) {
+ menu = menu->next;
+ } else {
+ while ((menu = menu->parent)) {
+ if (menu->next != NULL) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+ }
+ fclose(out);
+ return 0;
+}
+
int conf_write(const char *name)
{
FILE *out;
struct symbol *sym;
struct menu *menu;
const char *basename;
- char dirname[128], tmpname[128], newname[128];
- int type, l;
const char *str;
+ char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
time_t now;
int use_timestamp = 1;
char *env;
@@ -443,8 +598,6 @@ int conf_write(const char *name)
if (!out)
return 1;
- sym = sym_lookup("KERNELVERSION", 0);
- sym_calc_value(sym);
time(&now);
env = getenv("KCONFIG_NOTIMESTAMP");
if (env && *env)
@@ -452,10 +605,10 @@ int conf_write(const char *name)
fprintf(out, _("#\n"
"# Automatically generated make config: don't edit\n"
- "# Linux kernel version: %s\n"
+ "# %s\n"
"%s%s"
"#\n"),
- sym_get_string_value(sym),
+ rootmenu.prompt->text,
use_timestamp ? "# " : "",
use_timestamp ? ctime(&now) : "");
@@ -478,56 +631,11 @@ int conf_write(const char *name)
if (!(sym->flags & SYMBOL_WRITE))
goto next;
sym->flags &= ~SYMBOL_WRITE;
- type = sym->type;
- if (type == S_TRISTATE) {
- sym_calc_value(modules_sym);
- if (modules_sym->curr.tri == no)
- type = S_BOOLEAN;
- }
- switch (type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- switch (sym_get_tristate_value(sym)) {
- case no:
- fprintf(out, "# CONFIG_%s is not set\n", sym->name);
- break;
- case mod:
- fprintf(out, "CONFIG_%s=m\n", sym->name);
- break;
- case yes:
- fprintf(out, "CONFIG_%s=y\n", sym->name);
- break;
- }
- break;
- case S_STRING:
- str = sym_get_string_value(sym);
- fprintf(out, "CONFIG_%s=\"", sym->name);
- while (1) {
- l = strcspn(str, "\"\\");
- if (l) {
- fwrite(str, l, 1, out);
- str += l;
- }
- if (!*str)
- break;
- fprintf(out, "\\%c", *str++);
- }
- fputs("\"\n", out);
- break;
- case S_HEX:
- str = sym_get_string_value(sym);
- if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
- fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
- break;
- }
- case S_INT:
- str = sym_get_string_value(sym);
- fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
- break;
- }
+ /* Write config symbol to file */
+ conf_write_symbol(sym, out, true);
}
- next:
+next:
if (menu->list) {
menu = menu->list;
continue;
@@ -551,9 +659,7 @@ int conf_write(const char *name)
return 1;
}
- printf(_("#\n"
- "# configuration written to %s\n"
- "#\n"), newname);
+ conf_message(_("configuration written to %s"), newname);
sym_set_change_count(0);
@@ -563,7 +669,7 @@ int conf_write(const char *name)
static int conf_split_config(void)
{
const char *name;
- char path[128];
+ char path[PATH_MAX+1];
char *s, *d, c;
struct symbol *sym;
struct stat sb;
@@ -679,7 +785,7 @@ int conf_write_autoconf(void)
const char *name;
FILE *out, *tristate, *out_h;
time_t now;
- int i, l;
+ int i;
sym_clear_all_valid();
@@ -705,30 +811,32 @@ int conf_write_autoconf(void)
return 1;
}
- sym = sym_lookup("KERNELVERSION", 0);
- sym_calc_value(sym);
time(&now);
fprintf(out, "#\n"
"# Automatically generated make config: don't edit\n"
- "# Linux kernel version: %s\n"
+ "# %s\n"
"# %s"
"#\n",
- sym_get_string_value(sym), ctime(&now));
+ rootmenu.prompt->text, ctime(&now));
fprintf(tristate, "#\n"
"# Automatically generated - do not edit\n"
"\n");
fprintf(out_h, "/*\n"
" * Automatically generated C config: don't edit\n"
- " * Linux kernel version: %s\n"
+ " * %s\n"
" * %s"
- " */\n"
- "#define AUTOCONF_INCLUDED\n",
- sym_get_string_value(sym), ctime(&now));
+ " */\n",
+ rootmenu.prompt->text, ctime(&now));
for_all_symbols(i, sym) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
continue;
+
+ /* write symbol to config file */
+ conf_write_symbol(sym, out, false);
+
+ /* update autoconf and tristate files */
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
@@ -736,50 +844,34 @@ int conf_write_autoconf(void)
case no:
break;
case mod:
- fprintf(out, "CONFIG_%s=m\n", sym->name);
- fprintf(tristate, "CONFIG_%s=M\n", sym->name);
- fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
+ fprintf(tristate, "%s%s=M\n",
+ CONFIG_, sym->name);
+ fprintf(out_h, "#define %s%s_MODULE 1\n",
+ CONFIG_, sym->name);
break;
case yes:
- fprintf(out, "CONFIG_%s=y\n", sym->name);
if (sym->type == S_TRISTATE)
- fprintf(tristate, "CONFIG_%s=Y\n",
- sym->name);
- fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
+ fprintf(tristate,"%s%s=Y\n",
+ CONFIG_, sym->name);
+ fprintf(out_h, "#define %s%s 1\n",
+ CONFIG_, sym->name);
break;
}
break;
case S_STRING:
- str = sym_get_string_value(sym);
- fprintf(out, "CONFIG_%s=\"", sym->name);
- fprintf(out_h, "#define CONFIG_%s \"", sym->name);
- while (1) {
- l = strcspn(str, "\"\\");
- if (l) {
- fwrite(str, l, 1, out);
- fwrite(str, l, 1, out_h);
- str += l;
- }
- if (!*str)
- break;
- fprintf(out, "\\%c", *str);
- fprintf(out_h, "\\%c", *str);
- str++;
- }
- fputs("\"\n", out);
- fputs("\"\n", out_h);
+ conf_write_string(true, sym->name, sym_get_string_value(sym), out_h);
break;
case S_HEX:
str = sym_get_string_value(sym);
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
- fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
- fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
+ fprintf(out_h, "#define %s%s 0x%s\n",
+ CONFIG_, sym->name, str);
break;
}
case S_INT:
str = sym_get_string_value(sym);
- fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
- fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
+ fprintf(out_h, "#define %s%s %s\n",
+ CONFIG_, sym->name, str);
break;
default:
break;
@@ -837,13 +929,73 @@ void conf_set_changed_callback(void (*fn)(void))
conf_changed_callback = fn;
}
+static void randomize_choice_values(struct symbol *csym)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct expr *e;
+ int cnt, def;
+
+ /*
+ * If choice is mod then we may have more items selected
+ * and if no then no-one.
+ * In both cases stop.
+ */
+ if (csym->curr.tri != yes)
+ return;
+
+ prop = sym_get_choice_prop(csym);
+
+ /* count entries in choice block */
+ cnt = 0;
+ expr_list_for_each_sym(prop->expr, e, sym)
+ cnt++;
+
+ /*
+ * find a random value and set it to yes,
+ * set the rest to no so we have only one set
+ */
+ def = (rand() % cnt);
+
+ cnt = 0;
+ expr_list_for_each_sym(prop->expr, e, sym) {
+ if (def == cnt++) {
+ sym->def[S_DEF_USER].tri = yes;
+ csym->def[S_DEF_USER].val = sym;
+ }
+ else {
+ sym->def[S_DEF_USER].tri = no;
+ }
+ }
+ csym->flags |= SYMBOL_DEF_USER;
+ /* clear VALID to get value calculated */
+ csym->flags &= ~(SYMBOL_VALID);
+}
+
+static void set_all_choice_values(struct symbol *csym)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct expr *e;
+
+ prop = sym_get_choice_prop(csym);
+
+ /*
+ * Set all non-assinged choice values to no
+ */
+ expr_list_for_each_sym(prop->expr, e, sym) {
+ if (!sym_has_value(sym))
+ sym->def[S_DEF_USER].tri = no;
+ }
+ csym->flags |= SYMBOL_DEF_USER;
+ /* clear VALID to get value calculated */
+ csym->flags &= ~(SYMBOL_VALID);
+}
void conf_set_all_new_symbols(enum conf_def_mode mode)
{
struct symbol *sym, *csym;
- struct property *prop;
- struct expr *e;
- int i, cnt, def;
+ int i, cnt;
for_all_symbols(i, sym) {
if (sym_has_value(sym))
@@ -862,7 +1014,8 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
sym->def[S_DEF_USER].tri = no;
break;
case def_random:
- sym->def[S_DEF_USER].tri = (tristate)(rand() % 3);
+ cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
+ sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
break;
default:
continue;
@@ -878,14 +1031,12 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
sym_clear_all_valid();
- if (mode != def_random)
- return;
/*
* We have different type of choice blocks.
- * If curr.tri equal to mod then we can select several
+ * If curr.tri equals to mod then we can select several
* choice symbols in one block.
* In this case we do nothing.
- * If curr.tri equal yes then only one symbol can be
+ * If curr.tri equals yes then only one symbol can be
* selected in a choice block and we set it to yes,
* and the rest to no.
*/
@@ -894,35 +1045,9 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
continue;
sym_calc_value(csym);
-
- if (csym->curr.tri != yes)
- continue;
-
- prop = sym_get_choice_prop(csym);
-
- /* count entries in choice block */
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym)
- cnt++;
-
- /*
- * find a random value and set it to yes,
- * set the rest to no so we have only one set
- */
- def = (rand() % cnt);
-
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym) {
- if (def == cnt++) {
- sym->def[S_DEF_USER].tri = yes;
- csym->def[S_DEF_USER].val = sym;
- }
- else {
- sym->def[S_DEF_USER].tri = no;
- }
- }
- csym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- csym->flags &= ~(SYMBOL_VALID);
+ if (mode == def_random)
+ randomize_choice_values(csym);
+ else
+ set_all_choice_values(csym);
}
}
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index d83f2322893a..001003452f68 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -64,7 +64,7 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
}
-struct expr *expr_copy(struct expr *org)
+struct expr *expr_copy(const struct expr *org)
{
struct expr *e;
@@ -1013,6 +1013,48 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2)
#endif
}
+static inline struct expr *
+expr_get_leftmost_symbol(const struct expr *e)
+{
+
+ if (e == NULL)
+ return NULL;
+
+ while (e->type != E_SYMBOL)
+ e = e->left.expr;
+
+ return expr_copy(e);
+}
+
+/*
+ * Given expression `e1' and `e2', returns the leaf of the longest
+ * sub-expression of `e1' not containing 'e2.
+ */
+struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
+{
+ struct expr *ret;
+
+ switch (e1->type) {
+ case E_OR:
+ return expr_alloc_and(
+ expr_simplify_unmet_dep(e1->left.expr, e2),
+ expr_simplify_unmet_dep(e1->right.expr, e2));
+ case E_AND: {
+ struct expr *e;
+ e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
+ e = expr_eliminate_dups(e);
+ ret = (!expr_eq(e, e1)) ? e1 : NULL;
+ expr_free(e);
+ break;
+ }
+ default:
+ ret = e1;
+ break;
+ }
+
+ return expr_get_leftmost_symbol(ret);
+}
+
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
{
if (!e) {
@@ -1087,7 +1129,7 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
{
- fwrite(str, strlen(str), 1, data);
+ xfwrite(str, strlen(str), 1, data);
}
void expr_fprint(struct expr *e, FILE *out)
@@ -1121,7 +1163,7 @@ static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *s
}
str_append(gs, str);
- if (sym)
+ if (sym && sym->type != S_UNKNOWN)
str_printf(gs, " [=%s]", sym_str);
}
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 891cd9ce9ba2..3d238db49764 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -18,7 +18,7 @@ extern "C" {
struct file {
struct file *next;
struct file *parent;
- char *name;
+ const char *name;
int lineno;
int flags;
};
@@ -83,6 +83,7 @@ struct symbol {
tristate visible;
int flags;
struct property *prop;
+ struct expr_value dir_dep;
struct expr_value rev_dep;
};
@@ -131,6 +132,7 @@ enum prop_type {
P_SELECT, /* select BAR */
P_RANGE, /* range 7..100 (for a symbol) */
P_ENV, /* value from environment variable */
+ P_SYMBOL, /* where a symbol is defined */
};
struct property {
@@ -162,6 +164,7 @@ struct menu {
struct menu *list;
struct symbol *sym;
struct property *prompt;
+ struct expr *visibility;
struct expr *dep;
unsigned int flags;
char *help;
@@ -189,7 +192,7 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
-struct expr *expr_copy(struct expr *org);
+struct expr *expr_copy(const struct expr *org);
void expr_free(struct expr *e);
int expr_eq(struct expr *e1, struct expr *e2);
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
@@ -204,6 +207,7 @@ struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
+struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2);
void expr_fprint(struct expr *e, FILE *out);
struct gstr; /* forward */
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index bef10411837f..455896164d72 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -133,7 +133,6 @@ void init_main_window(const gchar * glade_file)
GladeXML *xml;
GtkWidget *widget;
GtkTextBuffer *txtbuf;
- char title[256];
GtkStyle *style;
xml = glade_xml_new(glade_file, "window1", NULL);
@@ -210,9 +209,7 @@ void init_main_window(const gchar * glade_file)
/*"style", PANGO_STYLE_OBLIQUE, */
NULL);
- sprintf(title, _("Linux Kernel v%s Configuration"),
- getenv("KERNELVERSION"));
- gtk_window_set_title(GTK_WINDOW(main_wnd), title);
+ gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
gtk_widget_show(main_wnd);
}
@@ -671,8 +668,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *intro_text = _(
- "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
- "for Linux.\n"
+ "Welcome to gkc, the GTK+ graphical configuration tool\n"
"For each option, a blank box indicates the feature is disabled, a\n"
"check indicates it is enabled, and a dot indicates that it is to\n"
"be compiled as a module. Clicking on the box will cycle through the three states.\n"
@@ -1114,7 +1110,7 @@ static gchar **fill_row(struct menu *menu)
row[COL_OPTION] =
g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
- sym && sym_has_value(sym) ? "(NEW)" : "");
+ sym && !sym_has_value(sym) ? "(NEW)" : "");
if (opt_mode == OPT_ALL && !menu_is_visible(menu))
row[COL_COLOR] = g_strdup("DarkGray");
@@ -1343,7 +1339,8 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
#endif
if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
- (opt_mode == OPT_PROMPT && !menu_has_prompt(child1))) {
+ (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
+ (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
/* remove node */
if (gtktree_iter_find_node(dst, menu1) != NULL) {
@@ -1425,7 +1422,7 @@ static void display_tree(struct menu *menu)
if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
(opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
- (opt_mode == OPT_ALL))
+ (opt_mode == OPT_ALL && menu_get_prompt(child)))
place_node(child, fill_row(child));
#ifdef DEBUG
printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
@@ -1530,12 +1527,6 @@ int main(int ac, char *av[])
else
glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
- /* Load the interface and connect signals */
- init_main_window(glade_file);
- init_tree_model();
- init_left_tree();
- init_right_tree();
-
/* Conf stuffs */
if (ac > 1 && av[1][0] == '-') {
switch (av[1][1]) {
@@ -1555,6 +1546,12 @@ int main(int ac, char *av[])
fixup_rootmenu(&rootmenu);
conf_read(NULL);
+ /* Load the interface and connect signals */
+ init_main_window(glade_file);
+ init_tree_model();
+ init_left_tree();
+ init_right_tree();
+
switch (view_mode) {
case SINGLE_VIEW:
display_tree_part();
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
index d52b0a75d824..aa483cb32755 100644
--- a/scripts/kconfig/gconf.glade
+++ b/scripts/kconfig/gconf.glade
@@ -1,5 +1,4 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
-<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c
index dcc3fcc0cc9a..e9d8e791bf0d 100644
--- a/scripts/kconfig/kxgettext.c
+++ b/scripts/kconfig/kxgettext.c
@@ -63,11 +63,11 @@ next:
struct file_line {
struct file_line *next;
- char* file;
- int lineno;
+ const char *file;
+ int lineno;
};
-static struct file_line *file_line__new(char *file, int lineno)
+static struct file_line *file_line__new(const char *file, int lineno)
{
struct file_line *self = malloc(sizeof(*self));
@@ -90,7 +90,8 @@ struct message {
static struct message *message__list;
-static struct message *message__new(const char *msg, char *option, char *file, int lineno)
+static struct message *message__new(const char *msg, char *option,
+ const char *file, int lineno)
{
struct message *self = malloc(sizeof(*self));
@@ -130,7 +131,8 @@ static struct message *mesage__find(const char *msg)
return m;
}
-static int message__add_file_line(struct message *self, char *file, int lineno)
+static int message__add_file_line(struct message *self, const char *file,
+ int lineno)
{
int rc = -1;
struct file_line *fl = file_line__new(file, lineno);
@@ -145,7 +147,8 @@ out:
return rc;
}
-static int message__add(const char *msg, char *option, char *file, int lineno)
+static int message__add(const char *msg, char *option, const char *file,
+ int lineno)
{
int rc = 0;
char bf[16384];
diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped
index fdc7113b08d1..6eb039718259 100644
--- a/scripts/kconfig/lex.zconf.c_shipped
+++ b/scripts/kconfig/lex.zconf.c_shipped
@@ -2373,9 +2373,10 @@ void zconf_nextfile(const char *name)
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
- zconfin = zconf_fopen(name);
+ zconfin = zconf_fopen(file->name);
if (!zconfin) {
- printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
+ printf("%s:%d: can't open file \"%s\"\n",
+ zconf_curname(), zconf_lineno(), file->name);
exit(1);
}
zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
@@ -2422,7 +2423,7 @@ int zconf_lineno(void)
return current_pos.lineno;
}
-char *zconf_curname(void)
+const char *zconf_curname(void)
{
return current_pos.file ? current_pos.file->name : "<none>";
}
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index ce6549cdaccf..febf0c94d558 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -14,6 +14,7 @@
static inline const char *gettext(const char *txt) { return txt; }
static inline void textdomain(const char *domainname) {}
static inline void bindtextdomain(const char *name, const char *dir) {}
+static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
#endif
#ifdef __cplusplus
@@ -31,12 +32,18 @@ extern "C" {
#define SRCTREE "srctree"
+#ifndef PACKAGE
#define PACKAGE "linux"
+#endif
+
#define LOCALEDIR "/usr/share/locale"
#define _(text) gettext(text)
#define N_(text) (text)
+#ifndef CONFIG_
+#define CONFIG_ "CONFIG_"
+#endif
#define TF_COMMAND 0x0001
#define TF_PARAM 0x0002
@@ -61,16 +68,21 @@ struct kconf_id {
enum symbol_type stype;
};
+#ifdef YYDEBUG
+extern int zconfdebug;
+#endif
+
int zconfparse(void);
void zconfdump(FILE *out);
-
-extern int zconfdebug;
void zconf_starthelp(void);
FILE *zconf_fopen(const char *name);
void zconf_initscan(const char *name);
void zconf_nextfile(const char *name);
int zconf_lineno(void);
-char *zconf_curname(void);
+const char *zconf_curname(void);
+
+/* conf.c */
+void xfgets(char *str, int size, FILE *in);
/* confdata.c */
const char *conf_get_configname(void);
@@ -80,6 +92,13 @@ void sym_set_change_count(int count);
void sym_add_change_count(int count);
void conf_set_all_new_symbols(enum conf_def_mode mode);
+/* confdata.c and expr.c */
+static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
+{
+ if (fwrite(str, len, count, out) < count)
+ fprintf(stderr, "\nError in writing or end of file.\n");
+}
+
/* kconfig_load.c */
void kconfig_load(void);
@@ -91,6 +110,7 @@ void menu_end_menu(void);
void menu_add_entry(struct symbol *sym);
void menu_end_entry(void);
void menu_add_dep(struct expr *dep);
+void menu_add_visibility(struct expr *dep);
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
@@ -126,6 +146,8 @@ void sym_init(void);
void sym_clear_all_valid(void);
void sym_set_all_changed(void);
void sym_set_changed(struct symbol *sym);
+struct symbol *sym_choice_default(struct symbol *sym);
+const char *sym_get_string_default(struct symbol *sym);
struct symbol *sym_check_deps(struct symbol *sym);
struct property *prop_alloc(enum prop_type type, struct symbol *sym);
struct symbol *prop_get_symbol(struct property *prop);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 7cadcad8233b..17342fef38b9 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -1,12 +1,15 @@
+#include <stdarg.h>
/* confdata.c */
P(conf_parse,void,(const char *name));
P(conf_read,int,(const char *name));
P(conf_read_simple,int,(const char *name, int));
+P(conf_write_defconfig,int,(const char *name));
P(conf_write,int,(const char *name));
P(conf_write_autoconf,int,(void));
P(conf_get_changed,bool,(void));
P(conf_set_changed_callback, void,(void (*fn)(void)));
+P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap)));
/* menu.c */
P(rootmenu,struct menu,);
@@ -27,6 +30,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
P(sym_lookup,struct symbol *,(const char *name, int flags));
P(sym_find,struct symbol *,(const char *name));
+P(sym_expand_string_value,const char *,(const char *in));
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));
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
index fcef0f59d553..82cc3a85e7f8 100644
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -23,6 +23,8 @@ ccflags()
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
elif [ -f /usr/include/ncurses/curses.h ]; then
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
+ elif [ -f /usr/include/ncursesw/curses.h ]; then
+ echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
elif [ -f /usr/include/ncurses.h ]; then
echo '-DCURSES_LOC="<ncurses.h>"'
else
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index bcc6f19c3a35..a2eb80fbc896 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -31,6 +31,10 @@ static int list_width, check_x, item_x;
static void print_item(WINDOW * win, int choice, int selected)
{
int i;
+ char *list_item = malloc(list_width + 1);
+
+ strncpy(list_item, item_str(), list_width - item_x);
+ list_item[list_width - item_x] = '\0';
/* Clear 'residue' of last item */
wattrset(win, dlg.menubox.atr);
@@ -45,13 +49,14 @@ static void print_item(WINDOW * win, int choice, int selected)
wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
- mvwaddch(win, choice, item_x, item_str()[0]);
+ mvwaddch(win, choice, item_x, list_item[0]);
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
- waddstr(win, (char *)item_str() + 1);
+ waddstr(win, list_item + 1);
if (selected) {
wmove(win, choice, check_x + 1);
wrefresh(win);
}
+ free(list_item);
}
/*
@@ -175,6 +180,7 @@ do_resize:
check_x = 0;
item_foreach()
check_x = MAX(check_x, strlen(item_str()) + 4);
+ check_x = MIN(check_x, list_width);
check_x = (list_width - check_x) / 2;
item_x = check_x + 4;
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 2c83d3234d30..d433c7a24745 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -25,11 +25,9 @@
static const char mconf_readme[] = N_(
"Overview\n"
"--------\n"
-"Some kernel features may be built directly into the kernel.\n"
-"Some may be made into loadable runtime modules. Some features\n"
-"may be completely removed altogether. There are also certain\n"
-"kernel parameters which are not really features, but must be\n"
-"entered in as decimal or hexadecimal numbers or possibly text.\n"
+"This interface let you select features and parameters for the build.\n"
+"Features can either be built-in, modularized, or ignored. Parameters\n"
+"must be entered in as decimal or hexadecimal numbers or text.\n"
"\n"
"Menu items beginning with following braces represent features that\n"
" [ ] can be built in or removed\n"
@@ -74,7 +72,7 @@ static const char mconf_readme[] = N_(
"\n"
" Shortcut: Press <H> or <?>.\n"
"\n"
-"o To show hidden options, press <Z>.\n"
+"o To toggle the display of hidden options, press <Z>.\n"
"\n"
"\n"
"Radiolists (Choice lists)\n"
@@ -117,7 +115,7 @@ static const char mconf_readme[] = N_(
"-----------------------------\n"
"Menuconfig supports the use of alternate configuration files for\n"
"those who, for various reasons, find it necessary to switch\n"
-"between different kernel configurations.\n"
+"between different configurations.\n"
"\n"
"At the end of the main menu you will find two options. One is\n"
"for saving the current configuration to a file of your choosing.\n"
@@ -150,9 +148,9 @@ static const char mconf_readme[] = N_(
"\n"
"Optional personality available\n"
"------------------------------\n"
-"If you prefer to have all of the kernel options listed in a single\n"
-"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
-"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
+"If you prefer to have all of the options listed in a single menu, rather\n"
+"than the default multimenu hierarchy, run the menuconfig with\n"
+"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
"\n"
"make MENUCONFIG_MODE=single_menu menuconfig\n"
"\n"
@@ -207,12 +205,12 @@ load_config_text[] = N_(
"last retrieved. Leave blank to abort."),
load_config_help[] = N_(
"\n"
- "For various reasons, one may wish to keep several different kernel\n"
+ "For various reasons, one may wish to keep several different\n"
"configurations available on a single machine.\n"
"\n"
"If you have saved a previous configuration in a file other than the\n"
- "kernel's default, entering the name of the file here will allow you\n"
- "to modify that configuration.\n"
+ "default one, entering its name here will allow you to modify that\n"
+ "configuration.\n"
"\n"
"If you are uncertain, then you have probably never used alternate\n"
"configuration files. You should therefore leave this blank to abort.\n"),
@@ -221,8 +219,8 @@ save_config_text[] = N_(
"as an alternate. Leave blank to abort."),
save_config_help[] = N_(
"\n"
- "For various reasons, one may wish to keep different kernel\n"
- "configurations available on a single machine.\n"
+ "For various reasons, one may wish to keep different configurations\n"
+ "available on a single machine.\n"
"\n"
"Entering a file name here will allow you to later retrieve, modify\n"
"and use the current configuration as an alternate to whatever\n"
@@ -232,7 +230,7 @@ save_config_help[] = N_(
"leave this blank.\n"),
search_help[] = N_(
"\n"
- "Search for CONFIG_ symbols and display their relations.\n"
+ "Search for symbols and display their relations.\n"
"Regular expressions are allowed.\n"
"Example: search for \"^FOO\"\n"
"Result:\n"
@@ -249,7 +247,7 @@ search_help[] = N_(
"Selected by: BAR\n"
"-----------------------------------------------------------------\n"
"o The line 'Prompt:' shows the text used in the menu structure for\n"
- " this CONFIG_ symbol\n"
+ " this symbol\n"
"o The 'Defined at' line tell at what file / line number the symbol\n"
" is defined\n"
"o The 'Depends on:' line tell what symbols needs to be defined for\n"
@@ -265,9 +263,9 @@ search_help[] = N_(
"Only relevant lines are shown.\n"
"\n\n"
"Search examples:\n"
- "Examples: USB => find all CONFIG_ symbols containing USB\n"
- " ^USB => find all CONFIG_ symbols starting with USB\n"
- " USB$ => find all CONFIG_ symbols ending with USB\n"
+ "Examples: USB => find all symbols containing USB\n"
+ " ^USB => find all symbols starting with USB\n"
+ " USB$ => find all symbols ending with USB\n"
"\n");
static int indent;
@@ -290,13 +288,9 @@ static void set_config_filename(const char *config_filename)
{
static char menu_backtitle[PATH_MAX+128];
int size;
- struct symbol *sym;
- sym = sym_lookup("KERNELVERSION", 0);
- sym_calc_value(sym);
size = snprintf(menu_backtitle, sizeof(menu_backtitle),
- _("%s - Linux Kernel v%s Configuration"),
- config_filename, sym_get_string_value(sym));
+ "%s - %s", config_filename, rootmenu.prompt->text);
if (size >= sizeof(menu_backtitle))
menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
set_dialog_backtitle(menu_backtitle);
@@ -316,8 +310,8 @@ static void search_conf(void)
again:
dialog_clear();
dres = dialog_inputbox(_("Search Configuration Parameter"),
- _("Enter CONFIG_ (sub)string to search for "
- "(with or without \"CONFIG\")"),
+ _("Enter " CONFIG_ " (sub)string to search for "
+ "(with or without \"" CONFIG_ "\")"),
10, 75, "");
switch (dres) {
case 0:
@@ -329,10 +323,10 @@ again:
return;
}
- /* strip CONFIG_ if necessary */
+ /* strip the prefix if necessary */
dialog_input = dialog_input_result;
- if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
- dialog_input += 7;
+ if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
+ dialog_input += strlen(CONFIG_);
sym_arr = sym_re_search(dialog_input);
res = get_relations_str(sym_arr);
@@ -834,7 +828,7 @@ int main(int ac, char **av)
if (conf_get_changed())
res = dialog_yesno(NULL,
_("Do you wish to save your "
- "new kernel configuration?\n"
+ "new configuration?\n"
"<ESC><ESC> to continue."),
6, 60);
else
@@ -846,20 +840,20 @@ int main(int ac, char **av)
case 0:
if (conf_write(filename)) {
fprintf(stderr, _("\n\n"
- "Error during writing of the kernel configuration.\n"
- "Your kernel configuration changes were NOT saved."
+ "Error while writing of the configuration.\n"
+ "Your configuration changes were NOT saved."
"\n\n"));
return 1;
}
case -1:
printf(_("\n\n"
- "*** End of Linux kernel configuration.\n"
- "*** Execute 'make' to build the kernel or try 'make help'."
+ "*** End of the configuration.\n"
+ "*** Execute 'make' to start the build or try 'make help'."
"\n\n"));
break;
default:
fprintf(stderr, _("\n\n"
- "Your kernel configuration changes were NOT saved."
+ "Your configuration changes were NOT saved."
"\n\n"));
}
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 203632cc30bd..5fdf10dc1d8a 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -10,7 +10,7 @@
#include "lkc.h"
static const char nohelp_text[] = N_(
- "There is no help available for this kernel option.\n");
+ "There is no help available for this option.\n");
struct menu rootmenu;
static struct menu **last_entry_ptr;
@@ -58,6 +58,8 @@ void menu_add_entry(struct symbol *sym)
*last_entry_ptr = menu;
last_entry_ptr = &menu->next;
current_entry = menu;
+ if (sym)
+ menu_add_symbol(P_SYMBOL, sym, NULL);
}
void menu_end_entry(void)
@@ -136,8 +138,22 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
while (isspace(*prompt))
prompt++;
}
- if (current_entry->prompt)
+ if (current_entry->prompt && current_entry != &rootmenu)
prop_warn(prop, "prompt redefined");
+
+ /* Apply all upper menus' visibilities to actual prompts. */
+ if(type == P_PROMPT) {
+ struct menu *menu = current_entry;
+
+ while ((menu = menu->parent) != NULL) {
+ if (!menu->visibility)
+ continue;
+ prop->visible.expr
+ = expr_alloc_and(prop->visible.expr,
+ menu->visibility);
+ }
+ }
+
current_entry->prompt = prop;
}
prop->text = prompt;
@@ -150,6 +166,12 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr
return menu_add_prop(type, prompt, NULL, dep);
}
+void menu_add_visibility(struct expr *expr)
+{
+ current_entry->visibility = expr_alloc_and(current_entry->visibility,
+ expr);
+}
+
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
{
menu_add_prop(type, NULL, expr, dep);
@@ -181,7 +203,7 @@ void menu_add_option(int token, char *arg)
}
}
-static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
+static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
{
return sym2->type == S_INT || sym2->type == S_HEX ||
(sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
@@ -199,6 +221,15 @@ static void sym_check_prop(struct symbol *sym)
prop_warn(prop,
"default for config symbol '%s'"
" must be a single symbol", sym->name);
+ if (prop->expr->type != E_SYMBOL)
+ break;
+ sym2 = prop_get_symbol(prop);
+ if (sym->type == S_HEX || sym->type == S_INT) {
+ if (!menu_validate_number(sym, sym2))
+ prop_warn(prop,
+ "'%s': number is invalid",
+ sym->name);
+ }
break;
case P_SELECT:
sym2 = prop_get_symbol(prop);
@@ -218,8 +249,8 @@ static void sym_check_prop(struct symbol *sym)
if (sym->type != S_INT && sym->type != S_HEX)
prop_warn(prop, "range is only allowed "
"for int or hex symbols");
- if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
- !menu_range_valid_sym(sym, prop->expr->right.sym))
+ if (!menu_validate_number(sym, prop->expr->left.sym) ||
+ !menu_validate_number(sym, prop->expr->right.sym))
prop_warn(prop, "range is invalid");
break;
default:
@@ -318,6 +349,8 @@ void menu_finalize(struct menu *parent)
parent->next = last_menu->next;
last_menu->next = NULL;
}
+
+ sym->dir_dep.expr = parent->dep;
}
for (menu = parent->list; menu; menu = menu->next) {
if (sym && sym_is_choice(sym) &&
@@ -406,6 +439,11 @@ bool menu_is_visible(struct menu *menu)
if (!menu->prompt)
return false;
+ if (menu->visibility) {
+ if (expr_calc_value(menu->visibility) == no)
+ return no;
+ }
+
sym = menu->sym;
if (sym) {
sym_calc_value(sym);
@@ -419,9 +457,13 @@ bool menu_is_visible(struct menu *menu)
if (!sym || sym_get_tristate_value(menu->sym) == no)
return false;
- for (child = menu->list; child; child = child->next)
- if (menu_is_visible(child))
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child)) {
+ if (sym)
+ sym->flags |= SYMBOL_DEF_USER;
return true;
+ }
+ }
return false;
}
@@ -501,9 +543,19 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
bool hit;
struct property *prop;
- if (sym && sym->name)
+ if (sym && sym->name) {
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
sym_get_string_value(sym));
+ str_printf(r, "Type : %s\n", sym_type_name(sym->type));
+ if (sym->type == S_INT || sym->type == S_HEX) {
+ prop = sym_get_range_prop(sym);
+ if (prop) {
+ str_printf(r, "Range : ");
+ expr_gstr_print(prop->expr, r);
+ str_append(r, "\n");
+ }
+ }
+ }
for_all_prompts(sym, prop)
get_prompt_str(r, prop);
hit = false;
@@ -545,7 +597,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
if (menu_has_help(menu)) {
if (sym->name) {
- str_printf(help, "CONFIG_%s:\n\n", sym->name);
+ str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
str_append(help, _(menu_get_help(menu)));
str_append(help, "\n");
}
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 762caf80ce37..db56377393d7 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -5,25 +5,26 @@
* Derived from menuconfig.
*
*/
+#define _GNU_SOURCE
+#include <string.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
#include "nconf.h"
+#include <ctype.h>
static const char nconf_readme[] = N_(
"Overview\n"
"--------\n"
-"Some kernel features may be built directly into the kernel.\n"
-"Some may be made into loadable runtime modules. Some features\n"
-"may be completely removed altogether. There are also certain\n"
-"kernel parameters which are not really features, but must be\n"
-"entered in as decimal or hexadecimal numbers or possibly text.\n"
+"This interface let you select features and parameters for the build.\n"
+"Features can either be built-in, modularized, or ignored. Parameters\n"
+"must be entered in as decimal or hexadecimal numbers or text.\n"
"\n"
"Menu items beginning with following braces represent features that\n"
" [ ] can be built in or removed\n"
" < > can be built in, modularized or removed\n"
" { } can be built in or modularized (selected by other feature)\n"
" - - are selected by other feature,\n"
-" XXX cannot be selected. use Symbol Info to find out why,\n"
+" XXX cannot be selected. Use Symbol Info to find out why,\n"
"while *, M or whitespace inside braces means to build in, build as\n"
"a module or to exclude the feature respectively.\n"
"\n"
@@ -41,9 +42,13 @@ static const char nconf_readme[] = N_(
" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
" Submenus are designated by \"--->\".\n"
"\n"
-" Shortcut: Press the option's highlighted letter (hotkey).\n"
-" Pressing a hotkey more than once will sequence\n"
-" through all visible items which use that hotkey.\n"
+" Searching: pressing '/' triggers interactive search mode.\n"
+" nconfig performs a case insensitive search for the string\n"
+" in the menu prompts (no regex support).\n"
+" Pressing the up/down keys highlights the previous/next\n"
+" matching item. Backspace removes one character from the\n"
+" match string. Pressing either '/' again or ESC exits\n"
+" search mode. All other keys behave normally.\n"
"\n"
" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
" unseen options into view.\n"
@@ -88,7 +93,7 @@ static const char nconf_readme[] = N_(
"-----------------------------\n"
"nconfig supports the use of alternate configuration files for\n"
"those who, for various reasons, find it necessary to switch\n"
-"between different kernel configurations.\n"
+"between different configurations.\n"
"\n"
"At the end of the main menu you will find two options. One is\n"
"for saving the current configuration to a file of your choosing.\n"
@@ -121,9 +126,9 @@ static const char nconf_readme[] = N_(
"\n"
"Optional personality available\n"
"------------------------------\n"
-"If you prefer to have all of the kernel options listed in a single\n"
-"menu, rather than the default multimenu hierarchy, run the nconfig\n"
-"with NCONFIG_MODE environment variable set to single_menu. Example:\n"
+"If you prefer to have all of the options listed in a single menu, rather\n"
+"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n"
+"environment variable set to single_menu. Example:\n"
"\n"
"make NCONFIG_MODE=single_menu nconfig\n"
"\n"
@@ -141,21 +146,21 @@ menu_no_f_instructions[] = N_(
" <Enter> or <right-arrow> selects submenus --->.\n"
" Capital Letters are hotkeys.\n"
" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
-" Pressing SpaceBar toggles between the above options\n"
-" Press <Esc> or <left-arrow> to go back one menu, \n"
+" Pressing SpaceBar toggles between the above options.\n"
+" Press <Esc> or <left-arrow> to go back one menu,\n"
" <?> or <h> for Help, </> for Search.\n"
-" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
+" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
-" <Esc> always leaves the current window\n"),
+" <Esc> always leaves the current window.\n"),
menu_instructions[] = N_(
" Arrow keys navigate the menu.\n"
" <Enter> or <right-arrow> selects submenus --->.\n"
" Capital Letters are hotkeys.\n"
" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
" Pressing SpaceBar toggles between the above options\n"
-" Press <Esc>, <F3> or <left-arrow> to go back one menu, \n"
+" Press <Esc>, <F5> or <left-arrow> to go back one menu,\n"
" <?>, <F1> or <h> for Help, </> for Search.\n"
-" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
+" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
" <Esc> always leaves the current window\n"),
radiolist_instructions[] = N_(
@@ -178,19 +183,19 @@ setmod_text[] = N_(
"has been configured as a module.\n"
"As a result, this feature will be built as a module."),
nohelp_text[] = N_(
-"There is no help available for this kernel option.\n"),
+"There is no help available for this option.\n"),
load_config_text[] = N_(
"Enter the name of the configuration file you wish to load.\n"
"Accept the name shown to restore the configuration you\n"
"last retrieved. Leave blank to abort."),
load_config_help[] = N_(
"\n"
-"For various reasons, one may wish to keep several different kernel\n"
+"For various reasons, one may wish to keep several different\n"
"configurations available on a single machine.\n"
"\n"
"If you have saved a previous configuration in a file other than the\n"
-"kernel's default, entering the name of the file here will allow you\n"
-"to modify that configuration.\n"
+"default one, entering its name here will allow you to modify that\n"
+"configuration.\n"
"\n"
"If you are uncertain, then you have probably never used alternate\n"
"configuration files. You should therefor leave this blank to abort.\n"),
@@ -199,8 +204,8 @@ save_config_text[] = N_(
"as an alternate. Leave blank to abort."),
save_config_help[] = N_(
"\n"
-"For various reasons, one may wish to keep different kernel\n"
-"configurations available on a single machine.\n"
+"For various reasons, one may wish to keep different configurations\n"
+"available on a single machine.\n"
"\n"
"Entering a file name here will allow you to later retrieve, modify\n"
"and use the current configuration as an alternate to whatever\n"
@@ -210,8 +215,8 @@ save_config_help[] = N_(
"leave this blank.\n"),
search_help[] = N_(
"\n"
-"Search for CONFIG_ symbols and display their relations.\n"
-"Regular expressions are allowed.\n"
+"Search for symbols and display their relations. Regular expressions\n"
+"are allowed.\n"
"Example: search for \"^FOO\"\n"
"Result:\n"
"-----------------------------------------------------------------\n"
@@ -227,7 +232,7 @@ search_help[] = N_(
"Selected by: BAR\n"
"-----------------------------------------------------------------\n"
"o The line 'Prompt:' shows the text used in the menu structure for\n"
-" this CONFIG_ symbol\n"
+" this symbol\n"
"o The 'Defined at' line tell at what file / line number the symbol\n"
" is defined\n"
"o The 'Depends on:' line tell what symbols needs to be defined for\n"
@@ -243,16 +248,15 @@ search_help[] = N_(
"Only relevant lines are shown.\n"
"\n\n"
"Search examples:\n"
-"Examples: USB = > find all CONFIG_ symbols containing USB\n"
-" ^USB => find all CONFIG_ symbols starting with USB\n"
-" USB$ => find all CONFIG_ symbols ending with USB\n"
+"Examples: USB => find all symbols containing USB\n"
+" ^USB => find all symbols starting with USB\n"
+" USB$ => find all symbols ending with USB\n"
"\n");
struct mitem {
char str[256];
char tag;
void *usrptr;
- int is_hot;
int is_visible;
};
@@ -275,14 +279,6 @@ static int items_num;
static int global_exit;
/* the currently selected button */
const char *current_instructions = menu_instructions;
-/* this array is used to implement hot keys. it is updated in item_make and
- * resetted in clean_items. It would be better to use a hash, but lets keep it
- * simple... */
-#define MAX_SAME_KEY MAX_MENU_ITEMS
-struct {
- int count;
- int ptrs[MAX_MENU_ITEMS];
-} hotkeys[1<<(sizeof(char)*8)];
static void conf(struct menu *menu);
static void conf_choice(struct menu *menu);
@@ -292,6 +288,7 @@ static void conf_save(void);
static void show_help(struct menu *menu);
static int do_exit(void);
static void setup_windows(void);
+static void search_conf(void);
typedef void (*function_key_handler_t)(int *key, struct menu *menu);
static void handle_f1(int *key, struct menu *current_item);
@@ -302,6 +299,7 @@ static void handle_f5(int *key, struct menu *current_item);
static void handle_f6(int *key, struct menu *current_item);
static void handle_f7(int *key, struct menu *current_item);
static void handle_f8(int *key, struct menu *current_item);
+static void handle_f9(int *key, struct menu *current_item);
struct function_keys {
const char *key_str;
@@ -310,7 +308,7 @@ struct function_keys {
function_key_handler_t handler;
};
-static const int function_keys_num = 8;
+static const int function_keys_num = 9;
struct function_keys function_keys[] = {
{
.key_str = "F1",
@@ -320,13 +318,13 @@ struct function_keys function_keys[] = {
},
{
.key_str = "F2",
- .func = "Symbol Info",
+ .func = "Sym Info",
.key = F_SYMBOL,
.handler = handle_f2,
},
{
.key_str = "F3",
- .func = "Instructions",
+ .func = "Insts",
.key = F_INSTS,
.handler = handle_f3,
},
@@ -356,9 +354,15 @@ struct function_keys function_keys[] = {
},
{
.key_str = "F8",
+ .func = "Sym Search",
+ .key = F_SEARCH,
+ .handler = handle_f8,
+ },
+ {
+ .key_str = "F9",
.func = "Exit",
.key = F_EXIT,
- .handler = handle_f8,
+ .handler = handle_f9,
},
};
@@ -444,9 +448,16 @@ static void handle_f7(int *key, struct menu *current_item)
return;
}
-/* exit */
+/* search */
static void handle_f8(int *key, struct menu *current_item)
{
+ search_conf();
+ return;
+}
+
+/* exit */
+static void handle_f9(int *key, struct menu *current_item)
+{
do_exit();
return;
}
@@ -479,110 +490,44 @@ static void clean_items(void)
free_item(curses_menu_items[i]);
bzero(curses_menu_items, sizeof(curses_menu_items));
bzero(k_menu_items, sizeof(k_menu_items));
- bzero(hotkeys, sizeof(hotkeys));
items_num = 0;
}
-/* return the index of the next hot item, or -1 if no such item exists */
-static int get_next_hot(int c)
-{
- static int hot_index;
- static int hot_char;
-
- if (c < 0 || c > 255 || hotkeys[c].count <= 0)
- return -1;
-
- if (hot_char == c) {
- hot_index = (hot_index+1)%hotkeys[c].count;
- return hotkeys[c].ptrs[hot_index];
- } else {
- hot_char = c;
- hot_index = 0;
- return hotkeys[c].ptrs[0];
- }
-}
-
-/* can the char c be a hot key? no, if c is a common shortcut used elsewhere */
-static int canbhot(char c)
-{
- c = tolower(c);
- return isalnum(c) && c != 'y' && c != 'm' && c != 'h' &&
- c != 'n' && c != '?';
-}
-
-/* check if str already contains a hot key. */
-static int is_hot(int index)
-{
- return k_menu_items[index].is_hot;
-}
+typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
+ FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
-/* find the first possible hot key, and mark it.
- * index is the index of the item in the menu
- * return 0 on success*/
-static int make_hot(char *dest, int len, const char *org, int index)
+/* return the index of the matched item, or -1 if no such item exists */
+static int get_mext_match(const char *match_str, match_f flag)
{
- int position = -1;
- int i;
- int tmp;
- int c;
- int org_len = strlen(org);
-
- if (org == NULL || is_hot(index))
- return 1;
-
- /* make sure not to make hot keys out of markers.
- * find where to start looking for a hot key
- */
- i = 0;
- /* skip white space */
- while (i < org_len && org[i] == ' ')
- i++;
- if (i == org_len)
- return -1;
- /* if encountering '(' or '<' or '[', find the match and look from there
- **/
- if (org[i] == '[' || org[i] == '<' || org[i] == '(') {
- i++;
- for (; i < org_len; i++)
- if (org[i] == ']' || org[i] == '>' || org[i] == ')')
- break;
- }
- if (i == org_len)
- return -1;
- for (; i < org_len; i++) {
- if (canbhot(org[i]) && org[i-1] != '<' && org[i-1] != '(') {
- position = i;
- break;
- }
+ int match_start = item_index(current_item(curses_menu));
+ int index;
+
+ if (flag == FIND_NEXT_MATCH_DOWN)
+ ++match_start;
+ else if (flag == FIND_NEXT_MATCH_UP)
+ --match_start;
+
+ index = match_start;
+ index = (index + items_num) % items_num;
+ while (true) {
+ char *str = k_menu_items[index].str;
+ if (strcasestr(str, match_str) != 0)
+ return index;
+ if (flag == FIND_NEXT_MATCH_UP ||
+ flag == MATCH_TINKER_PATTERN_UP)
+ --index;
+ else
+ ++index;
+ index = (index + items_num) % items_num;
+ if (index == match_start)
+ return -1;
}
- if (position == -1)
- return 1;
-
- /* ok, char at org[position] should be a hot key to this item */
- c = tolower(org[position]);
- tmp = hotkeys[c].count;
- hotkeys[c].ptrs[tmp] = index;
- hotkeys[c].count++;
- /*
- snprintf(dest, len, "%.*s(%c)%s", position, org, org[position],
- &org[position+1]);
- */
- /* make org[position] uppercase, and all leading letter small case */
- strncpy(dest, org, len);
- for (i = 0; i < position; i++)
- dest[i] = tolower(dest[i]);
- dest[position] = toupper(dest[position]);
- k_menu_items[index].is_hot = 1;
- return 0;
}
-/* Make a new item. Add a hotkey mark in the first possible letter.
- * As ncurses does not allow any attributes inside menue item, we mark the
- * hot key as the first capitalized letter in the string */
+/* Make a new item. */
static void item_make(struct menu *menu, char tag, const char *fmt, ...)
{
va_list ap;
- char tmp_str[256];
if (items_num > MAX_MENU_ITEMS-1)
return;
@@ -597,16 +542,13 @@ static void item_make(struct menu *menu, char tag, const char *fmt, ...)
k_menu_items[items_num].is_visible = 1;
va_start(ap, fmt);
- vsnprintf(tmp_str, sizeof(tmp_str), fmt, ap);
- if (!k_menu_items[items_num].is_visible)
- memcpy(tmp_str, "XXX", 3);
+ vsnprintf(k_menu_items[items_num].str,
+ sizeof(k_menu_items[items_num].str),
+ fmt, ap);
va_end(ap);
- if (make_hot(
- k_menu_items[items_num].str,
- sizeof(k_menu_items[items_num].str), tmp_str, items_num) != 0)
- strncpy(k_menu_items[items_num].str,
- tmp_str,
- sizeof(k_menu_items[items_num].str));
+
+ if (!k_menu_items[items_num].is_visible)
+ memcpy(k_menu_items[items_num].str, "XXX", 3);
curses_menu_items[items_num] = new_item(
k_menu_items[items_num].str,
@@ -638,11 +580,9 @@ static void item_add_str(const char *fmt, ...)
va_end(ap);
snprintf(tmp_str, sizeof(tmp_str), "%s%s",
k_menu_items[index].str, new_str);
- if (make_hot(k_menu_items[index].str,
- sizeof(k_menu_items[index].str), tmp_str, index) != 0)
- strncpy(k_menu_items[index].str,
- tmp_str,
- sizeof(k_menu_items[index].str));
+ strncpy(k_menu_items[index].str,
+ tmp_str,
+ sizeof(k_menu_items[index].str));
free_item(curses_menu_items[index]);
curses_menu_items[index] = new_item(
@@ -676,6 +616,8 @@ static void *item_data(void)
struct mitem *mcur;
cur = current_item(curses_menu);
+ if (!cur)
+ return NULL;
mcur = (struct mitem *) item_userptr(cur);
return mcur->usrptr;
@@ -691,13 +633,9 @@ static char menu_backtitle[PATH_MAX+128];
static const char *set_config_filename(const char *config_filename)
{
int size;
- struct symbol *sym;
- sym = sym_lookup("KERNELVERSION", 0);
- sym_calc_value(sym);
size = snprintf(menu_backtitle, sizeof(menu_backtitle),
- _("%s - Linux Kernel v%s Configuration"),
- config_filename, sym_get_string_value(sym));
+ "%s - %s", config_filename, rootmenu.prompt->text);
if (size >= sizeof(menu_backtitle))
menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
@@ -707,25 +645,6 @@ static const char *set_config_filename(const char *config_filename)
return menu_backtitle;
}
-/* command = 0 is supress, 1 is restore */
-static void supress_stdout(int command)
-{
- static FILE *org_stdout;
- static FILE *org_stderr;
-
- if (command == 0) {
- org_stdout = stdout;
- org_stderr = stderr;
- stdout = fopen("/dev/null", "a");
- stderr = fopen("/dev/null", "a");
- } else {
- fclose(stdout);
- fclose(stderr);
- stdout = org_stdout;
- stderr = org_stderr;
- }
-}
-
/* return = 0 means we are successful.
* -1 means go on doing what you were doing
*/
@@ -737,8 +656,7 @@ static int do_exit(void)
return 0;
}
res = btn_dialog(main_window,
- _("Do you wish to save your "
- "new kernel configuration?\n"
+ _("Do you wish to save your new configuration?\n"
"<ESC> to cancel and resume nconfig."),
2,
" <save> ",
@@ -751,36 +669,19 @@ static int do_exit(void)
/* if we got here, the user really wants to exit */
switch (res) {
case 0:
- supress_stdout(0);
res = conf_write(filename);
- supress_stdout(1);
if (res)
btn_dialog(
main_window,
- _("Error during writing of the kernel "
- "configuration.\n"
- "Your kernel configuration "
- "changes were NOT saved."),
+ _("Error during writing of configuration.\n"
+ "Your configuration changes were NOT saved."),
1,
"<OK>");
- else {
- char buf[1024];
- snprintf(buf, 1024,
- _("Configuration written to %s\n"
- "End of Linux kernel configuration.\n"
- "Execute 'make' to build the kernel or try"
- " 'make help'."), filename);
- btn_dialog(
- main_window,
- buf,
- 1,
- "<OK>");
- }
break;
default:
btn_dialog(
main_window,
- _("Your kernel configuration changes were NOT saved."),
+ _("Your configuration changes were NOT saved."),
1,
"<OK>");
break;
@@ -800,8 +701,8 @@ static void search_conf(void)
again:
dres = dialog_inputbox(main_window,
_("Search Configuration Parameter"),
- _("Enter CONFIG_ (sub)string to search for "
- "(with or without \"CONFIG\")"),
+ _("Enter " CONFIG_ " (sub)string to search for "
+ "(with or without \"" CONFIG_ "\")"),
"", dialog_input_result, 99);
switch (dres) {
case 0:
@@ -814,10 +715,10 @@ again:
return;
}
- /* strip CONFIG_ if necessary */
+ /* strip the prefix if necessary */
dialog_input = dialog_input_result;
- if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
- dialog_input += 7;
+ if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
+ dialog_input += strlen(CONFIG_);
sym_arr = sym_re_search(dialog_input);
res = get_relations_str(sym_arr);
@@ -1025,23 +926,18 @@ static void reset_menu(void)
static void center_item(int selected_index, int *last_top_row)
{
int toprow;
- int maxy, maxx;
- scale_menu(curses_menu, &maxy, &maxx);
set_top_row(curses_menu, *last_top_row);
toprow = top_row(curses_menu);
- if (selected_index >= toprow && selected_index < toprow+maxy) {
- /* we can only move the selected item. no need to scroll */
- set_current_item(curses_menu,
- curses_menu_items[selected_index]);
- } else {
- toprow = max(selected_index-maxy/2, 0);
- if (toprow >= item_count(curses_menu)-maxy)
+ if (selected_index < toprow ||
+ selected_index >= toprow+mwin_max_lines) {
+ toprow = max(selected_index-mwin_max_lines/2, 0);
+ if (toprow >= item_count(curses_menu)-mwin_max_lines)
toprow = item_count(curses_menu)-mwin_max_lines;
set_top_row(curses_menu, toprow);
- set_current_item(curses_menu,
- curses_menu_items[selected_index]);
}
+ set_current_item(curses_menu,
+ curses_menu_items[selected_index]);
*last_top_row = toprow;
post_menu(curses_menu);
refresh_all_windows(main_window);
@@ -1073,7 +969,7 @@ static void show_menu(const char *prompt, const char *instructions,
/* position the menu at the middle of the screen */
scale_menu(curses_menu, &maxy, &maxx);
maxx = min(maxx, mwin_max_cols-2);
- maxy = mwin_max_lines-2;
+ maxy = mwin_max_lines;
menu_window = derwin(main_window,
maxy,
maxx,
@@ -1097,10 +993,77 @@ static void show_menu(const char *prompt, const char *instructions,
refresh_all_windows(main_window);
}
+static void adj_match_dir(match_f *match_direction)
+{
+ if (*match_direction == FIND_NEXT_MATCH_DOWN)
+ *match_direction =
+ MATCH_TINKER_PATTERN_DOWN;
+ else if (*match_direction == FIND_NEXT_MATCH_UP)
+ *match_direction =
+ MATCH_TINKER_PATTERN_UP;
+ /* else, do no change.. */
+}
-static void conf(struct menu *menu)
+struct match_state
{
+ int in_search;
+ match_f match_direction;
char pattern[256];
+};
+
+/* Return 0 means I have handled the key. In such a case, ans should hold the
+ * item to center, or -1 otherwise.
+ * Else return -1 .
+ */
+static int do_match(int key, struct match_state *state, int *ans)
+{
+ char c = (char) key;
+ int terminate_search = 0;
+ *ans = -1;
+ if (key == '/' || (state->in_search && key == 27)) {
+ move(0, 0);
+ refresh();
+ clrtoeol();
+ state->in_search = 1-state->in_search;
+ bzero(state->pattern, sizeof(state->pattern));
+ state->match_direction = MATCH_TINKER_PATTERN_DOWN;
+ return 0;
+ } else if (!state->in_search)
+ return 1;
+
+ if (isalnum(c) || isgraph(c) || c == ' ') {
+ state->pattern[strlen(state->pattern)] = c;
+ state->pattern[strlen(state->pattern)] = '\0';
+ adj_match_dir(&state->match_direction);
+ *ans = get_mext_match(state->pattern,
+ state->match_direction);
+ } else if (key == KEY_DOWN) {
+ state->match_direction = FIND_NEXT_MATCH_DOWN;
+ *ans = get_mext_match(state->pattern,
+ state->match_direction);
+ } else if (key == KEY_UP) {
+ state->match_direction = FIND_NEXT_MATCH_UP;
+ *ans = get_mext_match(state->pattern,
+ state->match_direction);
+ } else if (key == KEY_BACKSPACE || key == 127) {
+ state->pattern[strlen(state->pattern)-1] = '\0';
+ adj_match_dir(&state->match_direction);
+ } else
+ terminate_search = 1;
+
+ if (terminate_search) {
+ state->in_search = 0;
+ bzero(state->pattern, sizeof(state->pattern));
+ move(0, 0);
+ refresh();
+ clrtoeol();
+ return -1;
+ }
+ return 0;
+}
+
+static void conf(struct menu *menu)
+{
struct menu *submenu = 0;
const char *prompt = menu_get_prompt(menu);
struct symbol *sym;
@@ -1108,8 +1071,11 @@ static void conf(struct menu *menu)
int res;
int current_index = 0;
int last_top_row = 0;
-
- bzero(pattern, sizeof(pattern));
+ struct match_state match_state = {
+ .in_search = 0,
+ .match_direction = MATCH_TINKER_PATTERN_DOWN,
+ .pattern = "",
+ };
while (!global_exit) {
reset_menu();
@@ -1122,7 +1088,22 @@ static void conf(struct menu *menu)
_(menu_instructions),
current_index, &last_top_row);
keypad((menu_win(curses_menu)), TRUE);
- while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
+ while (!global_exit) {
+ if (match_state.in_search) {
+ mvprintw(0, 0,
+ "searching: %s", match_state.pattern);
+ clrtoeol();
+ }
+ refresh_all_windows(main_window);
+ res = wgetch(menu_win(curses_menu));
+ if (!res)
+ break;
+ if (do_match(res, &match_state, &current_index) == 0) {
+ if (current_index != -1)
+ center_item(current_index,
+ &last_top_row);
+ continue;
+ }
if (process_special_keys(&res,
(struct menu *) item_data()))
break;
@@ -1153,19 +1134,13 @@ static void conf(struct menu *menu)
if (res == 10 || res == 27 ||
res == 32 || res == 'n' || res == 'y' ||
res == KEY_LEFT || res == KEY_RIGHT ||
- res == 'm' || res == '/')
+ res == 'm')
break;
- else if (canbhot(res)) {
- /* check for hot keys: */
- int tmp = get_next_hot(res);
- if (tmp != -1)
- center_item(tmp, &last_top_row);
- }
refresh_all_windows(main_window);
}
refresh_all_windows(main_window);
- /* if ESC or left*/
+ /* if ESC or left*/
if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
break;
@@ -1233,23 +1208,30 @@ static void conf(struct menu *menu)
if (item_is_tag('t'))
sym_set_tristate_value(sym, mod);
break;
- case '/':
- search_conf();
- break;
}
}
}
+static void conf_message_callback(const char *fmt, va_list ap)
+{
+ char buf[1024];
+
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ btn_dialog(main_window, buf, 1, "<OK>");
+}
+
static void show_help(struct menu *menu)
{
struct gstr help = str_new();
if (menu && menu->sym && menu_has_help(menu)) {
if (menu->sym->name) {
- str_printf(&help, "CONFIG_%s:\n\n", menu->sym->name);
+ str_printf(&help, "%s%s:\n\n", CONFIG_, menu->sym->name);
str_append(&help, _(menu_get_help(menu)));
str_append(&help, "\n");
get_symbol_str(&help, menu->sym);
+ } else {
+ str_append(&help, _(menu_get_help(menu)));
}
} else {
str_append(&help, nohelp_text);
@@ -1266,6 +1248,11 @@ static void conf_choice(struct menu *menu)
int selected_index = 0;
int last_top_row = 0;
int res, i = 0;
+ struct match_state match_state = {
+ .in_search = 0,
+ .match_direction = MATCH_TINKER_PATTERN_DOWN,
+ .pattern = "",
+ };
active = sym_get_choice_value(menu->sym);
/* this is mostly duplicated from the conf() function. */
@@ -1279,9 +1266,13 @@ static void conf_choice(struct menu *menu)
if (child->sym == sym_get_choice_value(menu->sym))
item_make(child, ':', "<X> %s",
_(menu_get_prompt(child)));
- else
+ else if (child->sym)
item_make(child, ':', " %s",
_(menu_get_prompt(child)));
+ else
+ item_make(child, ':', "*** %s ***",
+ _(menu_get_prompt(child)));
+
if (child->sym == active){
last_top_row = top_row(curses_menu);
selected_index = i;
@@ -1292,7 +1283,22 @@ static void conf_choice(struct menu *menu)
_(radiolist_instructions),
selected_index,
&last_top_row);
- while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
+ while (!global_exit) {
+ if (match_state.in_search) {
+ mvprintw(0, 0, "searching: %s",
+ match_state.pattern);
+ clrtoeol();
+ }
+ refresh_all_windows(main_window);
+ res = wgetch(menu_win(curses_menu));
+ if (!res)
+ break;
+ if (do_match(res, &match_state, &selected_index) == 0) {
+ if (selected_index != -1)
+ center_item(selected_index,
+ &last_top_row);
+ continue;
+ }
if (process_special_keys(
&res,
(struct menu *) item_data()))
@@ -1322,13 +1328,8 @@ static void conf_choice(struct menu *menu)
break;
}
if (res == 10 || res == 27 || res == ' ' ||
- res == KEY_LEFT)
+ res == KEY_LEFT){
break;
- else if (canbhot(res)) {
- /* check for hot keys: */
- int tmp = get_next_hot(res);
- if (tmp != -1)
- center_item(tmp, &last_top_row);
}
refresh_all_windows(main_window);
}
@@ -1337,7 +1338,7 @@ static void conf_choice(struct menu *menu)
break;
child = item_data();
- if (!child || !menu_is_visible(child))
+ if (!child || !menu_is_visible(child) || !child->sym)
continue;
switch (res) {
case ' ':
@@ -1447,16 +1448,8 @@ static void conf_save(void)
case 0:
if (!dialog_input_result[0])
return;
- supress_stdout(0);
res = conf_write(dialog_input_result);
- supress_stdout(1);
if (!res) {
- char buf[1024];
- sprintf(buf, "%s %s",
- _("configuration file saved to: "),
- dialog_input_result);
- btn_dialog(main_window,
- buf, 1, "<OK>");
set_config_filename(dialog_input_result);
return;
}
@@ -1483,7 +1476,7 @@ void setup_windows(void)
/* set up the menu and menu window */
main_window = newwin(LINES-2, COLS-2, 2, 1);
keypad(main_window, TRUE);
- mwin_max_lines = LINES-6;
+ mwin_max_lines = LINES-7;
mwin_max_cols = COLS-6;
/* panels order is from bottom to top */
@@ -1530,9 +1523,10 @@ int main(int ac, char **av)
/* set btns menu */
curses_menu = new_menu(curses_menu_items);
menu_opts_off(curses_menu, O_SHOWDESC);
- menu_opts_off(curses_menu, O_SHOWMATCH);
+ menu_opts_on(curses_menu, O_SHOWMATCH);
menu_opts_on(curses_menu, O_ONEVALUE);
menu_opts_on(curses_menu, O_NONCYCLIC);
+ menu_opts_on(curses_menu, O_IGNORECASE);
set_menu_mark(curses_menu, " ");
set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
@@ -1548,8 +1542,7 @@ int main(int ac, char **av)
_(menu_no_f_instructions));
}
-
-
+ conf_set_message_callback(conf_message_callback);
/* do the work */
while (!global_exit) {
conf(&rootmenu);
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
index 115edb437fb1..f8137b3a5382 100644
--- a/scripts/kconfig/nconf.gui.c
+++ b/scripts/kconfig/nconf.gui.c
@@ -137,7 +137,7 @@ void set_colors()
if (has_colors()) {
normal_color_theme();
} else {
- /* give deafults */
+ /* give defaults */
no_colors_theme();
}
}
@@ -167,7 +167,7 @@ void print_in_middle(WINDOW *win,
length = strlen(string);
temp = (width - length) / 2;
x = startx + (int)temp;
- wattrset(win, color);
+ (void) wattrset(win, color);
mvwprintw(win, y, x, "%s", string);
refresh();
}
@@ -226,7 +226,7 @@ void fill_window(WINDOW *win, const char *text)
int len = get_line_length(line);
strncpy(tmp, line, min(len, x));
tmp[len] = '\0';
- mvwprintw(win, i, 0, tmp);
+ mvwprintw(win, i, 0, "%s", tmp);
}
}
@@ -297,11 +297,11 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
- wattrset(win, attributes[DIALOG_BOX]);
+ (void) wattrset(win, attributes[DIALOG_BOX]);
box(win, 0, 0);
/* print message */
- wattrset(msg_win, attributes[DIALOG_TEXT]);
+ (void) wattrset(msg_win, attributes[DIALOG_TEXT]);
fill_window(msg_win, msg);
set_menu_win(menu, win);
@@ -392,16 +392,16 @@ int dialog_inputbox(WINDOW *main_window,
form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
keypad(form_win, TRUE);
- wattrset(form_win, attributes[INPUT_FIELD]);
+ (void) wattrset(form_win, attributes[INPUT_FIELD]);
- wattrset(win, attributes[INPUT_BOX]);
+ (void) wattrset(win, attributes[INPUT_BOX]);
box(win, 0, 0);
- wattrset(win, attributes[INPUT_HEADING]);
+ (void) wattrset(win, attributes[INPUT_HEADING]);
if (title)
mvwprintw(win, 0, 3, "%s", title);
/* print message */
- wattrset(prompt_win, attributes[INPUT_TEXT]);
+ (void) wattrset(prompt_win, attributes[INPUT_TEXT]);
fill_window(prompt_win, prompt);
mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
@@ -531,7 +531,7 @@ void show_scroll_win(WINDOW *main_window,
/* create the pad */
pad = newpad(total_lines+10, total_cols+10);
- wattrset(pad, attributes[SCROLLWIN_TEXT]);
+ (void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
fill_window(pad, text);
win_lines = min(total_lines+4, LINES-2);
@@ -546,9 +546,9 @@ void show_scroll_win(WINDOW *main_window,
win = newwin(win_lines, win_cols, y, x);
keypad(win, TRUE);
/* show the help in the help window, and show the help panel */
- wattrset(win, attributes[SCROLLWIN_BOX]);
+ (void) wattrset(win, attributes[SCROLLWIN_BOX]);
box(win, 0, 0);
- wattrset(win, attributes[SCROLLWIN_HEADING]);
+ (void) wattrset(win, attributes[SCROLLWIN_HEADING]);
mvwprintw(win, 0, 3, " %s ", title);
panel = new_panel(win);
diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h
index fb4296666004..58fbda8fc0dc 100644
--- a/scripts/kconfig/nconf.h
+++ b/scripts/kconfig/nconf.h
@@ -69,7 +69,8 @@ typedef enum {
F_BACK = 5,
F_SAVE = 6,
F_LOAD = 7,
- F_EXIT = 8
+ F_SEARCH = 8,
+ F_EXIT = 9,
} function_key;
void set_colors(void);
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 00c51507cfcc..06dd2e33581d 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -3,25 +3,42 @@
* Released under the terms of the GNU GPL v2.0.
*/
-#include <qapplication.h>
+#include <qglobal.h>
+
+#if QT_VERSION < 0x040000
#include <qmainwindow.h>
+#include <qvbox.h>
+#include <qvaluelist.h>
+#include <qtextbrowser.h>
+#include <qaction.h>
+#include <qheader.h>
+#include <qfiledialog.h>
+#include <qdragobject.h>
+#include <qpopupmenu.h>
+#else
+#include <q3mainwindow.h>
+#include <q3vbox.h>
+#include <q3valuelist.h>
+#include <q3textbrowser.h>
+#include <q3action.h>
+#include <q3header.h>
+#include <q3filedialog.h>
+#include <q3dragobject.h>
+#include <q3popupmenu.h>
+#endif
+
+#include <qapplication.h>
#include <qdesktopwidget.h>
#include <qtoolbar.h>
#include <qlayout.h>
-#include <qvbox.h>
#include <qsplitter.h>
-#include <qlistview.h>
-#include <qtextbrowser.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qmenubar.h>
#include <qmessagebox.h>
-#include <qaction.h>
-#include <qheader.h>
-#include <qfiledialog.h>
-#include <qdragobject.h>
#include <qregexp.h>
+#include <qevent.h>
#include <stdlib.h>
@@ -39,7 +56,7 @@
static QApplication *configApp;
static ConfigSettings *configSettings;
-QAction *ConfigMainWindow::saveAction;
+Q3Action *ConfigMainWindow::saveAction;
static inline QString qgettext(const char* str)
{
@@ -54,15 +71,14 @@ static inline QString qgettext(const QString& str)
/**
* Reads a list of integer values from the application settings.
*/
-QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
+Q3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
{
- QValueList<int> result;
+ Q3ValueList<int> result;
QStringList entryList = readListEntry(key, ok);
- if (ok) {
- QStringList::Iterator it;
- for (it = entryList.begin(); it != entryList.end(); ++it)
- result.push_back((*it).toInt());
- }
+ QStringList::Iterator it;
+
+ for (it = entryList.begin(); it != entryList.end(); ++it)
+ result.push_back((*it).toInt());
return result;
}
@@ -70,10 +86,10 @@ QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
/**
* Writes a list of integer values to the application settings.
*/
-bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
+bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& value)
{
QStringList stringList;
- QValueList<int>::ConstIterator it;
+ Q3ValueList<int>::ConstIterator it;
for (it = value.begin(); it != value.end(); ++it)
stringList.push_back(QString::number(*it));
@@ -81,7 +97,6 @@ bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value
}
-#if QT_VERSION >= 300
/*
* set the new data
* TODO check the value
@@ -92,7 +107,6 @@ void ConfigItem::okRename(int col)
sym_set_string_value(menu->sym, text(dataColIdx).latin1());
listView()->updateList(this);
}
-#endif
/*
* update the displayed of a menu entry
@@ -149,7 +163,7 @@ void ConfigItem::updateMenu(void)
case S_TRISTATE:
char ch;
- if (!sym_is_changable(sym) && !list->showAll) {
+ if (!sym_is_changable(sym) && list->optMode == normalOpt) {
setPixmap(promptColIdx, 0);
setText(noColIdx, QString::null);
setText(modColIdx, QString::null);
@@ -196,11 +210,9 @@ void ConfigItem::updateMenu(void)
data = sym_get_string_value(sym);
-#if QT_VERSION >= 300
int i = list->mapIdx(dataColIdx);
if (i >= 0)
setRenameEnabled(i, TRUE);
-#endif
setText(dataColIdx, data);
if (type == S_STRING)
prompt = QString("%1: %2").arg(prompt).arg(data);
@@ -320,7 +332,7 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
- showAll(false), showName(false), showRange(false), showData(false),
+ showName(false), showRange(false), showData(false), optMode(normalOpt),
rootEntry(0), headerPopup(0)
{
int i;
@@ -337,10 +349,10 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
if (name) {
configSettings->beginGroup(name);
- showAll = configSettings->readBoolEntry("/showAll", false);
showName = configSettings->readBoolEntry("/showName", false);
showRange = configSettings->readBoolEntry("/showRange", false);
showData = configSettings->readBoolEntry("/showData", false);
+ optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false);
configSettings->endGroup();
connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
}
@@ -352,6 +364,17 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
reinit();
}
+bool ConfigList::menuSkip(struct menu *menu)
+{
+ if (optMode == normalOpt && menu_is_visible(menu))
+ return false;
+ if (optMode == promptOpt && menu_has_prompt(menu))
+ return false;
+ if (optMode == allOpt)
+ return false;
+ return true;
+}
+
void ConfigList::reinit(void)
{
removeColumn(dataColIdx);
@@ -380,7 +403,7 @@ void ConfigList::saveSettings(void)
configSettings->writeEntry("/showName", showName);
configSettings->writeEntry("/showRange", showRange);
configSettings->writeEntry("/showData", showData);
- configSettings->writeEntry("/showAll", showAll);
+ configSettings->writeEntry("/optionMode", (int)optMode);
configSettings->endGroup();
}
}
@@ -422,7 +445,7 @@ void ConfigList::updateList(ConfigItem* item)
if (!rootEntry) {
if (mode != listMode)
goto update;
- QListViewItemIterator it(this);
+ Q3ListViewItemIterator it(this);
ConfigItem* item;
for (; it.current(); ++it) {
@@ -517,11 +540,9 @@ void ConfigList::changeValue(ConfigItem* item)
case S_INT:
case S_HEX:
case S_STRING:
-#if QT_VERSION >= 300
if (colMap[dataColIdx] >= 0)
item->startRename(colMap[dataColIdx]);
else
-#endif
parent()->lineEdit->show(item);
break;
}
@@ -553,7 +574,7 @@ void ConfigList::setParentMenu(void)
return;
setRootMenu(menu_get_parent_menu(rootEntry->parent));
- QListViewItemIterator it(this);
+ Q3ListViewItemIterator it(this);
for (; (item = (ConfigItem*)it.current()); it++) {
if (item->menu == oldroot) {
setCurrentItem(item);
@@ -606,7 +627,7 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
}
visible = menu_is_visible(child);
- if (showAll || visible) {
+ if (!menuSkip(child)) {
if (!child->sym && !child->list && !child->prompt)
continue;
if (!item || item->menu != child)
@@ -635,7 +656,7 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
void ConfigList::keyPressEvent(QKeyEvent* ev)
{
- QListViewItem* i = currentItem();
+ Q3ListViewItem* i = currentItem();
ConfigItem* item;
struct menu *menu;
enum prop_type type;
@@ -801,10 +822,10 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
{
if (e->y() <= header()->geometry().bottom()) {
if (!headerPopup) {
- QAction *action;
+ Q3Action *action;
- headerPopup = new QPopupMenu(this);
- action = new QAction(NULL, _("Show Name"), 0, this);
+ headerPopup = new Q3PopupMenu(this);
+ action = new Q3Action(NULL, _("Show Name"), 0, this);
action->setToggleAction(TRUE);
connect(action, SIGNAL(toggled(bool)),
parent(), SLOT(setShowName(bool)));
@@ -812,7 +833,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
action, SLOT(setOn(bool)));
action->setOn(showName);
action->addTo(headerPopup);
- action = new QAction(NULL, _("Show Range"), 0, this);
+ action = new Q3Action(NULL, _("Show Range"), 0, this);
action->setToggleAction(TRUE);
connect(action, SIGNAL(toggled(bool)),
parent(), SLOT(setShowRange(bool)));
@@ -820,7 +841,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
action, SLOT(setOn(bool)));
action->setOn(showRange);
action->addTo(headerPopup);
- action = new QAction(NULL, _("Show Data"), 0, this);
+ action = new Q3Action(NULL, _("Show Data"), 0, this);
action->setToggleAction(TRUE);
connect(action, SIGNAL(toggled(bool)),
parent(), SLOT(setShowData(bool)));
@@ -835,7 +856,10 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
e->ignore();
}
-ConfigView* ConfigView::viewList;
+ConfigView*ConfigView::viewList;
+QAction *ConfigView::showNormalAction;
+QAction *ConfigView::showAllAction;
+QAction *ConfigView::showPromptAction;
ConfigView::ConfigView(QWidget* parent, const char *name)
: Parent(parent, name)
@@ -860,13 +884,16 @@ ConfigView::~ConfigView(void)
}
}
-void ConfigView::setShowAll(bool b)
+void ConfigView::setOptionMode(QAction *act)
{
- if (list->showAll != b) {
- list->showAll = b;
- list->updateListAll();
- emit showAllChanged(b);
- }
+ if (act == showNormalAction)
+ list->optMode = normalOpt;
+ else if (act == showAllAction)
+ list->optMode = allOpt;
+ else
+ list->optMode = promptOpt;
+
+ list->updateListAll();
}
void ConfigView::setShowName(bool b)
@@ -898,7 +925,7 @@ void ConfigView::setShowData(bool b)
void ConfigList::setAllOpen(bool open)
{
- QListViewItemIterator it(this);
+ Q3ListViewItemIterator it(this);
for (; it.current(); it++)
it.current()->setOpen(open);
@@ -921,7 +948,7 @@ void ConfigView::updateListAll(void)
}
ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
- : Parent(parent, name), sym(0), menu(0)
+ : Parent(parent, name), sym(0), _menu(0)
{
if (name) {
configSettings->beginGroup(name);
@@ -944,7 +971,7 @@ void ConfigInfoView::setShowDebug(bool b)
{
if (_showDebug != b) {
_showDebug = b;
- if (menu)
+ if (_menu)
menuInfo();
else if (sym)
symbolInfo();
@@ -954,44 +981,16 @@ void ConfigInfoView::setShowDebug(bool b)
void ConfigInfoView::setInfo(struct menu *m)
{
- if (menu == m)
+ if (_menu == m)
return;
- menu = m;
+ _menu = m;
sym = NULL;
- if (!menu)
+ if (!_menu)
clear();
else
menuInfo();
}
-void ConfigInfoView::setSource(const QString& name)
-{
- const char *p = name.latin1();
-
- menu = NULL;
- sym = NULL;
-
- switch (p[0]) {
- case 'm':
- struct menu *m;
-
- if (sscanf(p, "m%p", &m) == 1 && menu != m) {
- menu = m;
- menuInfo();
- emit menuSelected(menu);
- }
- break;
- case 's':
- struct symbol *s;
-
- if (sscanf(p, "s%p", &s) == 1 && sym != s) {
- sym = s;
- symbolInfo();
- }
- break;
- }
-}
-
void ConfigInfoView::symbolInfo(void)
{
QString str;
@@ -1013,11 +1012,11 @@ void ConfigInfoView::menuInfo(void)
struct symbol* sym;
QString head, debug, help;
- sym = menu->sym;
+ sym = _menu->sym;
if (sym) {
- if (menu->prompt) {
+ if (_menu->prompt) {
head += "<big><b>";
- head += print_filter(_(menu->prompt->text));
+ head += print_filter(_(_menu->prompt->text));
head += "</b></big>";
if (sym->name) {
head += " (";
@@ -1043,23 +1042,23 @@ void ConfigInfoView::menuInfo(void)
debug = debug_info(sym);
struct gstr help_gstr = str_new();
- menu_get_ext_help(menu, &help_gstr);
+ menu_get_ext_help(_menu, &help_gstr);
help = print_filter(str_get(&help_gstr));
str_free(&help_gstr);
- } else if (menu->prompt) {
+ } else if (_menu->prompt) {
head += "<big><b>";
- head += print_filter(_(menu->prompt->text));
+ head += print_filter(_(_menu->prompt->text));
head += "</b></big><br><br>";
if (showDebug()) {
- if (menu->prompt->visible.expr) {
+ if (_menu->prompt->visible.expr) {
debug += "&nbsp;&nbsp;dep: ";
- expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
+ expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
debug += "<br><br>";
}
}
}
if (showDebug())
- debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
+ debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
setText(head + debug + help);
}
@@ -1162,10 +1161,10 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
*text += str2;
}
-QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
+Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
{
- QPopupMenu* popup = Parent::createPopupMenu(pos);
- QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup);
+ Q3PopupMenu* popup = Parent::createPopupMenu(pos);
+ Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup);
action->setToggleAction(TRUE);
connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
@@ -1222,7 +1221,7 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
y = configSettings->readNumEntry("/window y", 0, &ok);
if (ok)
move(x, y);
- QValueList<int> sizes = configSettings->readSizes("/split", &ok);
+ Q3ValueList<int> sizes = configSettings->readSizes("/split", &ok);
if (ok)
split->setSizes(sizes);
configSettings->endGroup();
@@ -1275,8 +1274,14 @@ ConfigMainWindow::ConfigMainWindow(void)
char title[256];
QDesktopWidget *d = configApp->desktop();
- snprintf(title, sizeof(title), _("Linux Kernel v%s Configuration"),
- getenv("KERNELVERSION"));
+ snprintf(title, sizeof(title), "%s%s",
+ rootmenu.prompt->text,
+#if QT_VERSION < 0x040000
+ " (Qt3)"
+#else
+ ""
+#endif
+ );
setCaption(title);
width = configSettings->readNumEntry("/window width", d->width() - 64);
@@ -1309,60 +1314,79 @@ ConfigMainWindow::ConfigMainWindow(void)
configList->setFocus();
menu = menuBar();
- toolBar = new QToolBar("Tools", this);
+ toolBar = new Q3ToolBar("Tools", this);
- backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this);
+ backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this);
connect(backAction, SIGNAL(activated()), SLOT(goBack()));
backAction->setEnabled(FALSE);
- QAction *quitAction = new QAction("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
+ Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
connect(quitAction, SIGNAL(activated()), SLOT(close()));
- QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
+ Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
- saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
+ saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
conf_set_changed_callback(conf_changed);
// Set saveAction's initial state
conf_changed();
- QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this);
+ Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this);
connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
- QAction *searchAction = new QAction("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
+ Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
- QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
+ Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
- QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
+ Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
- QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
+ Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
- QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this);
+ Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this);
showNameAction->setToggleAction(TRUE);
connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
showNameAction->setOn(configView->showName());
- QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this);
+ Q3Action *showRangeAction = new Q3Action(NULL, _("Show Range"), 0, this);
showRangeAction->setToggleAction(TRUE);
connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
showRangeAction->setOn(configList->showRange);
- QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this);
+ Q3Action *showDataAction = new Q3Action(NULL, _("Show Data"), 0, this);
showDataAction->setToggleAction(TRUE);
connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
showDataAction->setOn(configList->showData);
- QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this);
- showAllAction->setToggleAction(TRUE);
- connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool)));
- connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool)));
- showAllAction->setOn(configList->showAll);
- QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this);
+
+ QActionGroup *optGroup = new QActionGroup(this);
+ optGroup->setExclusive(TRUE);
+ connect(optGroup, SIGNAL(selected(QAction *)), configView,
+ SLOT(setOptionMode(QAction *)));
+ connect(optGroup, SIGNAL(selected(QAction *)), menuView,
+ SLOT(setOptionMode(QAction *)));
+
+#if QT_VERSION >= 0x040000
+ configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup);
+ configView->showAllAction = new QAction(_("Show All Options"), optGroup);
+ configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup);
+#else
+ configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup);
+ configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup);
+ configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup);
+#endif
+ configView->showNormalAction->setToggleAction(TRUE);
+ configView->showNormalAction->setOn(configList->optMode == normalOpt);
+ configView->showAllAction->setToggleAction(TRUE);
+ configView->showAllAction->setOn(configList->optMode == allOpt);
+ configView->showPromptAction->setToggleAction(TRUE);
+ configView->showPromptAction->setOn(configList->optMode == promptOpt);
+
+ Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this);
showDebugAction->setToggleAction(TRUE);
connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
showDebugAction->setOn(helpText->showDebug());
- QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this);
+ Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this);
connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
- QAction *showAboutAction = new QAction(NULL, _("About"), 0, this);
+ Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this);
connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
// init tool bar
@@ -1376,7 +1400,7 @@ ConfigMainWindow::ConfigMainWindow(void)
fullViewAction->addTo(toolBar);
// create config menu
- QPopupMenu* config = new QPopupMenu(this);
+ Q3PopupMenu* config = new Q3PopupMenu(this);
menu->insertItem(_("&File"), config);
loadAction->addTo(config);
saveAction->addTo(config);
@@ -1385,22 +1409,22 @@ ConfigMainWindow::ConfigMainWindow(void)
quitAction->addTo(config);
// create edit menu
- QPopupMenu* editMenu = new QPopupMenu(this);
+ Q3PopupMenu* editMenu = new Q3PopupMenu(this);
menu->insertItem(_("&Edit"), editMenu);
searchAction->addTo(editMenu);
// create options menu
- QPopupMenu* optionMenu = new QPopupMenu(this);
+ Q3PopupMenu* optionMenu = new Q3PopupMenu(this);
menu->insertItem(_("&Option"), optionMenu);
showNameAction->addTo(optionMenu);
showRangeAction->addTo(optionMenu);
showDataAction->addTo(optionMenu);
optionMenu->insertSeparator();
- showAllAction->addTo(optionMenu);
- showDebugAction->addTo(optionMenu);
+ optGroup->addTo(optionMenu);
+ optionMenu->insertSeparator();
// create help menu
- QPopupMenu* helpMenu = new QPopupMenu(this);
+ Q3PopupMenu* helpMenu = new Q3PopupMenu(this);
menu->insertSeparator();
menu->insertItem(_("&Help"), helpMenu);
showIntroAction->addTo(helpMenu);
@@ -1435,7 +1459,7 @@ ConfigMainWindow::ConfigMainWindow(void)
showSplitView();
// UI setup done, restore splitter positions
- QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
+ Q3ValueList<int> sizes = configSettings->readSizes("/split1", &ok);
if (ok)
split1->setSizes(sizes);
@@ -1446,7 +1470,7 @@ ConfigMainWindow::ConfigMainWindow(void)
void ConfigMainWindow::loadConfig(void)
{
- QString s = QFileDialog::getOpenFileName(conf_get_configname(), NULL, this);
+ QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);
if (s.isNull())
return;
if (conf_read(QFile::encodeName(s)))
@@ -1462,7 +1486,7 @@ void ConfigMainWindow::saveConfig(void)
void ConfigMainWindow::saveConfigAs(void)
{
- QString s = QFileDialog::getSaveFileName(conf_get_configname(), NULL, this);
+ QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);
if (s.isNull())
return;
if (conf_write(QFile::encodeName(s)))
@@ -1491,7 +1515,7 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
ConfigList* list = NULL;
ConfigItem* item;
- if (!menu_is_visible(menu) && !configView->showAll())
+ if (configList->menuSkip(menu))
return;
switch (configList->mode) {
@@ -1631,7 +1655,7 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
void ConfigMainWindow::showIntro(void)
{
- static const QString str = _("Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
+ static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
"For each option, a blank box indicates the feature is disabled, a check\n"
"indicates it is enabled, and a dot indicates that it is to be compiled\n"
"as a module. Clicking on the box will cycle through the three states.\n\n"
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index b3b5657b6b35..91677d900dbd 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -3,26 +3,25 @@
* Released under the terms of the GNU GPL v2.0.
*/
+#if QT_VERSION < 0x040000
#include <qlistview.h>
-#if QT_VERSION >= 300
-#include <qsettings.h>
#else
-class QSettings {
-public:
- void beginGroup(const QString& group) { }
- void endGroup(void) { }
- bool readBoolEntry(const QString& key, bool def = FALSE, bool* ok = 0) const
- { if (ok) *ok = FALSE; return def; }
- int readNumEntry(const QString& key, int def = 0, bool* ok = 0) const
- { if (ok) *ok = FALSE; return def; }
- QString readEntry(const QString& key, const QString& def = QString::null, bool* ok = 0) const
- { if (ok) *ok = FALSE; return def; }
- QStringList readListEntry(const QString& key, bool* ok = 0) const
- { if (ok) *ok = FALSE; return QStringList(); }
- template <class t>
- bool writeEntry(const QString& key, t value)
- { return TRUE; }
-};
+#include <q3listview.h>
+#endif
+#include <qsettings.h>
+
+#if QT_VERSION < 0x040000
+#define Q3ValueList QValueList
+#define Q3PopupMenu QPopupMenu
+#define Q3ListView QListView
+#define Q3ListViewItem QListViewItem
+#define Q3VBox QVBox
+#define Q3TextBrowser QTextBrowser
+#define Q3MainWindow QMainWindow
+#define Q3Action QAction
+#define Q3ToolBar QToolBar
+#define Q3ListViewItemIterator QListViewItemIterator
+#define Q3FileDialog QFileDialog
#endif
class ConfigView;
@@ -31,11 +30,10 @@ class ConfigItem;
class ConfigLineEdit;
class ConfigMainWindow;
-
class ConfigSettings : public QSettings {
public:
- QValueList<int> readSizes(const QString& key, bool *ok);
- bool writeSizes(const QString& key, const QValueList<int>& value);
+ Q3ValueList<int> readSizes(const QString& key, bool *ok);
+ bool writeSizes(const QString& key, const Q3ValueList<int>& value);
};
enum colIdx {
@@ -44,10 +42,13 @@ enum colIdx {
enum listMode {
singleMode, menuMode, symbolMode, fullMode, listMode
};
+enum optionMode {
+ normalOpt = 0, allOpt, promptOpt
+};
-class ConfigList : public QListView {
+class ConfigList : public Q3ListView {
Q_OBJECT
- typedef class QListView Parent;
+ typedef class Q3ListView Parent;
public:
ConfigList(ConfigView* p, const char *name = 0);
void reinit(void);
@@ -115,6 +116,8 @@ public:
void setAllOpen(bool open);
void setParentMenu(void);
+ bool menuSkip(struct menu *);
+
template <class P>
void updateMenuList(P*, struct menu*);
@@ -124,22 +127,23 @@ public:
QPixmap choiceYesPix, choiceNoPix;
QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
- bool showAll, showName, showRange, showData;
+ bool showName, showRange, showData;
enum listMode mode;
+ enum optionMode optMode;
struct menu *rootEntry;
QColorGroup disabledColorGroup;
QColorGroup inactivedColorGroup;
- QPopupMenu* headerPopup;
+ Q3PopupMenu* headerPopup;
private:
int colMap[colNr];
int colRevMap[colNr];
};
-class ConfigItem : public QListViewItem {
- typedef class QListViewItem Parent;
+class ConfigItem : public Q3ListViewItem {
+ typedef class Q3ListViewItem Parent;
public:
- ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v)
+ ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v)
: Parent(parent, after), menu(m), visible(v), goParent(false)
{
init();
@@ -149,16 +153,14 @@ public:
{
init();
}
- ConfigItem(QListView *parent, ConfigItem *after, bool v)
+ ConfigItem(Q3ListView *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
@@ -213,26 +215,24 @@ public:
ConfigItem *item;
};
-class ConfigView : public QVBox {
+class ConfigView : public Q3VBox {
Q_OBJECT
- typedef class QVBox Parent;
+ typedef class Q3VBox Parent;
public:
ConfigView(QWidget* parent, const char *name = 0);
~ConfigView(void);
static void updateList(ConfigItem* item);
static void updateListAll(void);
- bool showAll(void) const { return list->showAll; }
bool showName(void) const { return list->showName; }
bool showRange(void) const { return list->showRange; }
bool showData(void) const { return list->showData; }
public slots:
- void setShowAll(bool);
void setShowName(bool);
void setShowRange(bool);
void setShowData(bool);
+ void setOptionMode(QAction *);
signals:
- void showAllChanged(bool);
void showNameChanged(bool);
void showRangeChanged(bool);
void showDataChanged(bool);
@@ -242,11 +242,15 @@ public:
static ConfigView* viewList;
ConfigView* nextView;
+
+ static QAction *showNormalAction;
+ static QAction *showAllAction;
+ static QAction *showPromptAction;
};
-class ConfigInfoView : public QTextBrowser {
+class ConfigInfoView : public Q3TextBrowser {
Q_OBJECT
- typedef class QTextBrowser Parent;
+ typedef class Q3TextBrowser Parent;
public:
ConfigInfoView(QWidget* parent, const char *name = 0);
bool showDebug(void) const { return _showDebug; }
@@ -254,7 +258,6 @@ public:
public slots:
void setInfo(struct menu *menu);
void saveSettings(void);
- void setSource(const QString& name);
void setShowDebug(bool);
signals:
@@ -267,11 +270,11 @@ protected:
QString debug_info(struct symbol *sym);
static QString print_filter(const QString &str);
static void expr_print_help(void *data, struct symbol *sym, const char *str);
- QPopupMenu* createPopupMenu(const QPoint& pos);
+ Q3PopupMenu* createPopupMenu(const QPoint& pos);
void contentsContextMenuEvent(QContextMenuEvent *e);
struct symbol *sym;
- struct menu *menu;
+ struct menu *_menu;
bool _showDebug;
};
@@ -295,10 +298,10 @@ protected:
struct symbol **result;
};
-class ConfigMainWindow : public QMainWindow {
+class ConfigMainWindow : public Q3MainWindow {
Q_OBJECT
- static QAction *saveAction;
+ static Q3Action *saveAction;
static void conf_changed(void);
public:
ConfigMainWindow(void);
@@ -327,8 +330,8 @@ protected:
ConfigView *configView;
ConfigList *configList;
ConfigInfoView *helpText;
- QToolBar *toolBar;
- QAction *backAction;
+ Q3ToolBar *toolBar;
+ Q3Action *backAction;
QSplitter* split1;
QSplitter* split2;
};
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index 0d800820c3cd..fd81fc33d633 100644
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -42,6 +42,8 @@
# mv config_strip .config
# make oldconfig
#
+use strict;
+
my $config = ".config";
my $uname = `uname -r`;
@@ -113,14 +115,18 @@ find_config;
# Get the build source and top level Kconfig file (passed in)
my $ksource = $ARGV[0];
my $kconfig = $ARGV[1];
+my $lsmod_file = $ARGV[2];
+
+my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
+chomp @makefiles;
-my @makefiles = `find $ksource -name Makefile`;
my %depends;
my %selects;
my %prompts;
my %objects;
my $var;
-my $cont = 0;
+my $iflevel = 0;
+my @ifdeps;
# prevent recursion
my %read_kconfigs;
@@ -132,19 +138,54 @@ sub read_kconfig {
my $config;
my @kconfigs;
- open(KIN, "$ksource/$kconfig") || die "Can't open $kconfig";
+ my $cont = 0;
+ my $line;
+
+ my $source = "$ksource/$kconfig";
+ my $last_source = "";
+
+ # Check for any environment variables used
+ while ($source =~ /\$(\w+)/ && $last_source ne $source) {
+ my $env = $1;
+ $last_source = $source;
+ $source =~ s/\$$env/$ENV{$env}/;
+ }
+
+ open(KIN, "$source") || die "Can't open $kconfig";
while (<KIN>) {
chomp;
+ # Make sure that lines ending with \ continue
+ if ($cont) {
+ $_ = $line . " " . $_;
+ }
+
+ if (s/\\$//) {
+ $cont = 1;
+ $line = $_;
+ next;
+ }
+
+ $cont = 0;
+
# collect any Kconfig sources
if (/^source\s*"(.*)"/) {
$kconfigs[$#kconfigs+1] = $1;
}
# configs found
- if (/^\s*config\s+(\S+)\s*$/) {
+ if (/^\s*(menu)?config\s+(\S+)\s*$/) {
$state = "NEW";
- $config = $1;
+ $config = $2;
+
+ for (my $i = 0; $i < $iflevel; $i++) {
+ if ($i) {
+ $depends{$config} .= " " . $ifdeps[$i];
+ } else {
+ $depends{$config} = $ifdeps[$i];
+ }
+ $state = "DEP";
+ }
# collect the depends for the config
} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
@@ -164,7 +205,22 @@ sub read_kconfig {
# configs without prompts must be selected
} elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
# note if the config has a prompt
- $prompt{$config} = 1;
+ $prompts{$config} = 1;
+
+ # Check for if statements
+ } elsif (/^if\s+(.*\S)\s*$/) {
+ my $deps = $1;
+ # remove beginning and ending non text
+ $deps =~ s/^[^a-zA-Z0-9_]*//;
+ $deps =~ s/[^a-zA-Z0-9_]*$//;
+
+ my @deps = split /[^a-zA-Z0-9_]+/, $deps;
+
+ $ifdeps[$iflevel++] = join ':', @deps;
+
+ } elsif (/^endif/) {
+
+ $iflevel-- if ($iflevel);
# stop on "help"
} elsif (/^\s*help\s*$/) {
@@ -188,7 +244,8 @@ if ($kconfig) {
# Read all Makefiles to map the configs to the objects
foreach my $makefile (@makefiles) {
- chomp $makefile;
+
+ my $cont = 0;
open(MIN,$makefile) || die "Can't open $makefile";
while (<MIN>) {
@@ -215,7 +272,7 @@ foreach my $makefile (@makefiles) {
foreach my $obj (split /\s+/,$objs) {
$obj =~ s/-/_/g;
if ($obj =~ /(.*)\.o$/) {
- # Objects may bes enabled by more than one config.
+ # Objects may be enabled by more than one config.
# Store configs in an array.
my @arr;
@@ -237,8 +294,36 @@ foreach my $makefile (@makefiles) {
my %modules;
-# see what modules are loaded on this system
-open(LIN,"/sbin/lsmod|") || die "Cant lsmod";
+if (defined($lsmod_file)) {
+ if ( ! -f $lsmod_file) {
+ die "$lsmod_file not found";
+ }
+ if ( -x $lsmod_file) {
+ # the file is executable, run it
+ open(LIN, "$lsmod_file|");
+ } else {
+ # Just read the contents
+ open(LIN, "$lsmod_file");
+ }
+} else {
+
+ # see what modules are loaded on this system
+ my $lsmod;
+
+ foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
+ if ( -x "$dir/lsmod" ) {
+ $lsmod = "$dir/lsmod";
+ last;
+ }
+}
+ if (!defined($lsmod)) {
+ # try just the path
+ $lsmod = "lsmod";
+ }
+
+ open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod";
+}
+
while (<LIN>) {
next if (/^Module/); # Skip the first line.
if (/^(\S+)/) {
@@ -252,7 +337,7 @@ close (LIN);
my %configs;
foreach my $module (keys(%modules)) {
if (defined($objects{$module})) {
- @arr = @{$objects{$module}};
+ my @arr = @{$objects{$module}};
foreach my $conf (@arr) {
$configs{$conf} = $module;
}
@@ -307,7 +392,7 @@ while ($repeat) {
parse_config_dep_select $depends{$config};
}
- if (defined($prompt{$config}) || !defined($selects{$config})) {
+ if (defined($prompts{$config}) || !defined($selects{$config})) {
next;
}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 2e7a048e0cfc..a796c95fe8a0 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -205,6 +205,16 @@ static void sym_calc_visibility(struct symbol *sym)
}
if (sym_is_choice_value(sym))
return;
+ /* defaulting to "yes" if no explicit "depends on" are given */
+ tri = yes;
+ if (sym->dir_dep.expr)
+ tri = expr_calc_value(sym->dir_dep.expr);
+ if (tri == mod)
+ tri = yes;
+ if (sym->dir_dep.tri != tri) {
+ sym->dir_dep.tri = tri;
+ sym_set_changed(sym);
+ }
tri = no;
if (sym->rev_dep.expr)
tri = expr_calc_value(sym->rev_dep.expr);
@@ -216,44 +226,63 @@ static void sym_calc_visibility(struct symbol *sym)
}
}
-static struct symbol *sym_calc_choice(struct symbol *sym)
+/*
+ * Find the default symbol for a choice.
+ * First try the default values for the choice symbol
+ * Next locate the first visible choice value
+ * Return NULL if none was found
+ */
+struct symbol *sym_choice_default(struct symbol *sym)
{
struct symbol *def_sym;
struct property *prop;
struct expr *e;
- /* is the user choice visible? */
- def_sym = sym->def[S_DEF_USER].val;
- if (def_sym) {
- sym_calc_visibility(def_sym);
- if (def_sym->visible != no)
- return def_sym;
- }
-
/* any of the defaults visible? */
for_all_defaults(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri == no)
continue;
def_sym = prop_get_symbol(prop);
- sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
}
/* just get the first visible value */
prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, def_sym) {
- sym_calc_visibility(def_sym);
+ expr_list_for_each_sym(prop->expr, e, def_sym)
if (def_sym->visible != no)
return def_sym;
- }
- /* no choice? reset tristate value */
- sym->curr.tri = no;
+ /* failed to locate any defaults */
return NULL;
}
+static struct symbol *sym_calc_choice(struct symbol *sym)
+{
+ struct symbol *def_sym;
+ struct property *prop;
+ struct expr *e;
+
+ /* first calculate all choice values' visibilities */
+ prop = sym_get_choice_prop(sym);
+ expr_list_for_each_sym(prop->expr, e, def_sym)
+ sym_calc_visibility(def_sym);
+
+ /* is the user choice visible? */
+ def_sym = sym->def[S_DEF_USER].val;
+ if (def_sym && def_sym->visible != no)
+ return def_sym;
+
+ def_sym = sym_choice_default(sym);
+
+ if (def_sym == NULL)
+ /* no choice? reset tristate value */
+ sym->curr.tri = no;
+
+ return def_sym;
+}
+
void sym_calc_value(struct symbol *sym)
{
struct symbol_value newval, oldval;
@@ -321,6 +350,18 @@ void sym_calc_value(struct symbol *sym)
}
}
calc_newval:
+ if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
+ struct expr *e;
+ e = expr_simplify_unmet_dep(sym->rev_dep.expr,
+ sym->dir_dep.expr);
+ fprintf(stderr, "warning: (");
+ expr_fprint(e, stderr);
+ fprintf(stderr, ") selects %s which has unmet direct dependencies (",
+ sym->name);
+ expr_fprint(sym->dir_dep.expr, stderr);
+ fprintf(stderr, ")\n");
+ expr_free(e);
+ }
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
}
if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
@@ -365,12 +406,13 @@ void sym_calc_value(struct symbol *sym)
if (sym_is_choice(sym)) {
struct symbol *choice_sym;
- int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
prop = sym_get_choice_prop(sym);
expr_list_for_each_sym(prop->expr, e, choice_sym) {
- choice_sym->flags |= flags;
- if (flags & SYMBOL_CHANGED)
+ if ((sym->flags & SYMBOL_WRITE) &&
+ choice_sym->visible != no)
+ choice_sym->flags |= SYMBOL_WRITE;
+ if (sym->flags & SYMBOL_CHANGED)
sym_set_changed(choice_sym);
}
}
@@ -623,6 +665,80 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
return true;
}
+/*
+ * Find the default value associated to a symbol.
+ * For tristate symbol handle the modules=n case
+ * in which case "m" becomes "y".
+ * If the symbol does not have any default then fallback
+ * to the fixed default values.
+ */
+const char *sym_get_string_default(struct symbol *sym)
+{
+ struct property *prop;
+ struct symbol *ds;
+ const char *str;
+ tristate val;
+
+ sym_calc_visibility(sym);
+ sym_calc_value(modules_sym);
+ val = symbol_no.curr.tri;
+ str = symbol_empty.curr.val;
+
+ /* If symbol has a default value look it up */
+ prop = sym_get_default_prop(sym);
+ if (prop != NULL) {
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ /* The visibility may limit the value from yes => mod */
+ val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
+ break;
+ default:
+ /*
+ * The following fails to handle the situation
+ * where a default value is further limited by
+ * the valid range.
+ */
+ ds = prop_get_symbol(prop);
+ if (ds != NULL) {
+ sym_calc_value(ds);
+ str = (const char *)ds->curr.val;
+ }
+ }
+ }
+
+ /* Handle select statements */
+ val = EXPR_OR(val, sym->rev_dep.tri);
+
+ /* transpose mod to yes if modules are not enabled */
+ if (val == mod)
+ if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
+ val = yes;
+
+ /* transpose mod to yes if type is bool */
+ if (sym->type == S_BOOLEAN && val == mod)
+ val = yes;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (val) {
+ case no: return "n";
+ case mod: return "m";
+ case yes: return "y";
+ }
+ case S_INT:
+ case S_HEX:
+ return str;
+ case S_STRING:
+ return str;
+ case S_OTHER:
+ case S_UNKNOWN:
+ break;
+ }
+ return "";
+}
+
const char *sym_get_string_value(struct symbol *sym)
{
tristate val;
@@ -728,6 +844,55 @@ struct symbol *sym_find(const char *name)
return symbol;
}
+/*
+ * Expand symbol's names embedded in the string given in argument. Symbols'
+ * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
+ * the empty string.
+ */
+const char *sym_expand_string_value(const char *in)
+{
+ const char *src;
+ char *res;
+ size_t reslen;
+
+ reslen = strlen(in) + 1;
+ res = malloc(reslen);
+ res[0] = '\0';
+
+ while ((src = strchr(in, '$'))) {
+ char *p, name[SYMBOL_MAXLENGTH];
+ const char *symval = "";
+ struct symbol *sym;
+ size_t newlen;
+
+ strncat(res, in, src - in);
+ src++;
+
+ p = name;
+ while (isalnum(*src) || *src == '_')
+ *p++ = *src++;
+ *p = '\0';
+
+ sym = sym_find(name);
+ if (sym != NULL) {
+ sym_calc_value(sym);
+ symval = sym_get_string_value(sym);
+ }
+
+ newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
+ if (newlen > reslen) {
+ reslen = newlen;
+ res = realloc(res, reslen);
+ }
+
+ strcat(res, symval);
+ in = src;
+ }
+ strcat(res, in);
+
+ return res;
+}
+
struct symbol **sym_re_search(const char *pattern)
{
struct symbol *sym, **sym_arr = NULL;
@@ -765,6 +930,112 @@ struct symbol **sym_re_search(const char *pattern)
return sym_arr;
}
+/*
+ * When we check for recursive dependencies we use a stack to save
+ * current state so we can print out relevant info to user.
+ * The entries are located on the call stack so no need to free memory.
+ * Note inser() remove() must always match to properly clear the stack.
+ */
+static struct dep_stack {
+ struct dep_stack *prev, *next;
+ struct symbol *sym;
+ struct property *prop;
+ struct expr *expr;
+} *check_top;
+
+static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
+{
+ memset(stack, 0, sizeof(*stack));
+ if (check_top)
+ check_top->next = stack;
+ stack->prev = check_top;
+ stack->sym = sym;
+ check_top = stack;
+}
+
+static void dep_stack_remove(void)
+{
+ check_top = check_top->prev;
+ if (check_top)
+ check_top->next = NULL;
+}
+
+/*
+ * Called when we have detected a recursive dependency.
+ * check_top point to the top of the stact so we use
+ * the ->prev pointer to locate the bottom of the stack.
+ */
+static void sym_check_print_recursive(struct symbol *last_sym)
+{
+ struct dep_stack *stack;
+ struct symbol *sym, *next_sym;
+ struct menu *menu = NULL;
+ struct property *prop;
+ struct dep_stack cv_stack;
+
+ if (sym_is_choice_value(last_sym)) {
+ dep_stack_insert(&cv_stack, last_sym);
+ last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
+ }
+
+ for (stack = check_top; stack != NULL; stack = stack->prev)
+ if (stack->sym == last_sym)
+ break;
+ if (!stack) {
+ fprintf(stderr, "unexpected recursive dependency error\n");
+ return;
+ }
+
+ for (; stack; stack = stack->next) {
+ sym = stack->sym;
+ next_sym = stack->next ? stack->next->sym : last_sym;
+ prop = stack->prop;
+ if (prop == NULL)
+ prop = stack->sym->prop;
+
+ /* for choice values find the menu entry (used below) */
+ if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
+ for (prop = sym->prop; prop; prop = prop->next) {
+ menu = prop->menu;
+ if (prop->menu)
+ break;
+ }
+ }
+ if (stack->sym == last_sym)
+ fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
+ prop->file->name, prop->lineno);
+ if (stack->expr) {
+ fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
+ prop->file->name, prop->lineno,
+ sym->name ? sym->name : "<choice>",
+ prop_get_type_name(prop->type),
+ next_sym->name ? next_sym->name : "<choice>");
+ } else if (stack->prop) {
+ fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
+ prop->file->name, prop->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ } else if (sym_is_choice(sym)) {
+ fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
+ menu->file->name, menu->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ } else if (sym_is_choice_value(sym)) {
+ fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
+ menu->file->name, menu->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ } else {
+ fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
+ prop->file->name, prop->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ }
+ }
+
+ if (check_top == &cv_stack)
+ dep_stack_remove();
+}
static struct symbol *sym_check_expr_deps(struct expr *e)
{
@@ -801,24 +1072,33 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
{
struct symbol *sym2;
struct property *prop;
+ struct dep_stack stack;
+
+ dep_stack_insert(&stack, sym);
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
if (sym2)
- return sym2;
+ goto out;
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->type == P_CHOICE || prop->type == P_SELECT)
continue;
+ stack.prop = prop;
sym2 = sym_check_expr_deps(prop->visible.expr);
if (sym2)
break;
if (prop->type != P_DEFAULT || sym_is_choice(sym))
continue;
+ stack.expr = prop->expr;
sym2 = sym_check_expr_deps(prop->expr);
if (sym2)
break;
+ stack.expr = NULL;
}
+out:
+ dep_stack_remove();
+
return sym2;
}
@@ -827,6 +1107,9 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
struct symbol *sym, *sym2;
struct property *prop;
struct expr *e;
+ struct dep_stack stack;
+
+ dep_stack_insert(&stack, choice);
prop = sym_get_choice_prop(choice);
expr_list_for_each_sym(prop->expr, e, sym)
@@ -840,10 +1123,8 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
expr_list_for_each_sym(prop->expr, e, sym) {
sym2 = sym_check_sym_deps(sym);
- if (sym2) {
- fprintf(stderr, " -> %s", sym->name);
+ if (sym2)
break;
- }
}
out:
expr_list_for_each_sym(prop->expr, e, sym)
@@ -853,6 +1134,8 @@ out:
prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
sym2 = choice;
+ dep_stack_remove();
+
return sym2;
}
@@ -862,18 +1145,20 @@ struct symbol *sym_check_deps(struct symbol *sym)
struct property *prop;
if (sym->flags & SYMBOL_CHECK) {
- fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
- sym->prop->file->name, sym->prop->lineno,
- sym->name ? sym->name : "<choice>");
+ sym_check_print_recursive(sym);
return sym;
}
if (sym->flags & SYMBOL_CHECKED)
return NULL;
if (sym_is_choice_value(sym)) {
+ struct dep_stack stack;
+
/* for choice groups start the check with main choice symbol */
+ dep_stack_insert(&stack, sym);
prop = sym_get_choice_prop(sym);
sym2 = sym_check_deps(prop_get_symbol(prop));
+ dep_stack_remove();
} else if (sym_is_choice(sym)) {
sym2 = sym_check_choice_deps(sym);
} else {
@@ -882,14 +1167,8 @@ struct symbol *sym_check_deps(struct symbol *sym)
sym->flags &= ~SYMBOL_CHECK;
}
- if (sym2) {
- fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
- if (sym2 == sym) {
- fprintf(stderr, "\n");
- zconfnerrs++;
- sym2 = NULL;
- }
- }
+ if (sym2 && sym2 == sym)
+ sym2 = NULL;
return sym2;
}
@@ -943,6 +1222,8 @@ const char *prop_get_type_name(enum prop_type type)
return "select";
case P_RANGE:
return "range";
+ case P_SYMBOL:
+ return "symbol";
case P_UNKNOWN:
break;
}
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index 81c100d953ef..6330cc871a47 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -12,15 +12,18 @@
struct file *file_lookup(const char *name)
{
struct file *file;
+ const char *file_name = sym_expand_string_value(name);
for (file = file_list; file; file = file->next) {
- if (!strcmp(name, file->name))
+ if (!strcmp(name, file->name)) {
+ free((void *)file_name);
return file;
+ }
}
file = malloc(sizeof(*file));
memset(file, 0, sizeof(*file));
- file->name = strdup(name);
+ file->name = file_name;
file->next = file_list;
file_list = file;
return file;
@@ -72,7 +75,7 @@ int file_write_dep(const char *name)
}
-/* Allocate initial growable sting */
+/* Allocate initial growable string */
struct gstr str_new(void)
{
struct gstr gs;
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
index d8bc74249622..c9e690eb7545 100644
--- a/scripts/kconfig/zconf.gperf
+++ b/scripts/kconfig/zconf.gperf
@@ -38,6 +38,7 @@ hex, T_TYPE, TF_COMMAND, S_HEX
string, T_TYPE, TF_COMMAND, S_STRING
select, T_SELECT, TF_COMMAND
range, T_RANGE, TF_COMMAND
+visible, T_VISIBLE, TF_COMMAND
option, T_OPTION, TF_COMMAND
on, T_ON, TF_PARAM
modules, T_OPT_MODULES, TF_OPTION
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
index c1748faf4634..4055d5de1750 100644
--- a/scripts/kconfig/zconf.hash.c_shipped
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -32,7 +32,7 @@
struct kconf_id;
static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
-/* maximum key range = 47, duplicates = 0 */
+/* maximum key range = 50, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -46,32 +46,32 @@ kconf_id_hash (register const char *str, register unsigned int len)
{
static unsigned char asso_values[] =
{
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 11, 5,
- 0, 0, 5, 49, 5, 20, 49, 49, 5, 20,
- 5, 0, 30, 49, 0, 15, 0, 10, 0, 49,
- 25, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 40, 5,
+ 0, 0, 5, 52, 0, 20, 52, 52, 10, 20,
+ 5, 0, 35, 52, 0, 30, 0, 15, 0, 52,
+ 15, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52
};
register int hval = len;
@@ -102,25 +102,26 @@ struct kconf_id_strings_t
char kconf_id_strings_str12[sizeof("default")];
char kconf_id_strings_str13[sizeof("def_bool")];
char kconf_id_strings_str14[sizeof("help")];
- char kconf_id_strings_str15[sizeof("bool")];
char kconf_id_strings_str16[sizeof("config")];
char kconf_id_strings_str17[sizeof("def_tristate")];
- char kconf_id_strings_str18[sizeof("boolean")];
+ char kconf_id_strings_str18[sizeof("hex")];
char kconf_id_strings_str19[sizeof("defconfig_list")];
- char kconf_id_strings_str21[sizeof("string")];
char kconf_id_strings_str22[sizeof("if")];
char kconf_id_strings_str23[sizeof("int")];
- char kconf_id_strings_str26[sizeof("select")];
char kconf_id_strings_str27[sizeof("modules")];
char kconf_id_strings_str28[sizeof("tristate")];
char kconf_id_strings_str29[sizeof("menu")];
- char kconf_id_strings_str31[sizeof("source")];
char kconf_id_strings_str32[sizeof("comment")];
- char kconf_id_strings_str33[sizeof("hex")];
char kconf_id_strings_str35[sizeof("menuconfig")];
- char kconf_id_strings_str36[sizeof("prompt")];
- char kconf_id_strings_str37[sizeof("depends")];
+ char kconf_id_strings_str36[sizeof("string")];
+ char kconf_id_strings_str37[sizeof("visible")];
+ char kconf_id_strings_str41[sizeof("prompt")];
+ char kconf_id_strings_str42[sizeof("depends")];
+ char kconf_id_strings_str44[sizeof("bool")];
+ char kconf_id_strings_str46[sizeof("select")];
+ char kconf_id_strings_str47[sizeof("boolean")];
char kconf_id_strings_str48[sizeof("mainmenu")];
+ char kconf_id_strings_str51[sizeof("source")];
};
static struct kconf_id_strings_t kconf_id_strings_contents =
{
@@ -136,25 +137,26 @@ static struct kconf_id_strings_t kconf_id_strings_contents =
"default",
"def_bool",
"help",
- "bool",
"config",
"def_tristate",
- "boolean",
+ "hex",
"defconfig_list",
- "string",
"if",
"int",
- "select",
"modules",
"tristate",
"menu",
- "source",
"comment",
- "hex",
"menuconfig",
+ "string",
+ "visible",
"prompt",
"depends",
- "mainmenu"
+ "bool",
+ "select",
+ "boolean",
+ "mainmenu",
+ "source"
};
#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
#ifdef __GNUC__
@@ -168,11 +170,11 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{
enum
{
- TOTAL_KEYWORDS = 31,
+ TOTAL_KEYWORDS = 32,
MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 14,
MIN_HASH_VALUE = 2,
- MAX_HASH_VALUE = 48
+ MAX_HASH_VALUE = 51
};
static struct kconf_id wordlist[] =
@@ -191,31 +193,35 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_HELP, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str15, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_CONFIG, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_TYPE, TF_COMMAND, S_HEX},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19, T_OPT_DEFCONFIG_LIST,TF_OPTION},
- {-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_TYPE, TF_COMMAND, S_STRING},
+ {-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT},
- {-1}, {-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND},
+ {-1}, {-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND},
- {-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SOURCE, TF_COMMAND},
+ {-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_HEX},
- {-1},
+ {-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_PROMPT, TF_COMMAND},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_DEPENDS, TF_COMMAND},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_TYPE, TF_COMMAND, S_STRING},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_VISIBLE, TF_COMMAND},
+ {-1}, {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_PROMPT, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_DEPENDS, TF_COMMAND},
{-1},
- {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND}
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str44, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_SELECT, TF_COMMAND},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND},
+ {-1}, {-1},
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_SOURCE, TF_COMMAND}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
index d8f7236cb0a3..3dbaec185cc4 100644
--- a/scripts/kconfig/zconf.l
+++ b/scripts/kconfig/zconf.l
@@ -304,9 +304,10 @@ void zconf_nextfile(const char *name)
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
- yyin = zconf_fopen(name);
+ yyin = zconf_fopen(file->name);
if (!yyin) {
- printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
+ printf("%s:%d: can't open file \"%s\"\n",
+ zconf_curname(), zconf_lineno(), file->name);
exit(1);
}
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
@@ -353,7 +354,7 @@ int zconf_lineno(void)
return current_pos.lineno;
}
-char *zconf_curname(void)
+const char *zconf_curname(void)
{
return current_pos.file ? current_pos.file->name : "<none>";
}
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index 32a9eefd842c..4c5495ea205e 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -160,18 +160,19 @@ static struct menu *current_menu, *current_entry;
T_DEFAULT = 275,
T_SELECT = 276,
T_RANGE = 277,
- T_OPTION = 278,
- T_ON = 279,
- T_WORD = 280,
- T_WORD_QUOTE = 281,
- T_UNEQUAL = 282,
- T_CLOSE_PAREN = 283,
- T_OPEN_PAREN = 284,
- T_EOL = 285,
- T_OR = 286,
- T_AND = 287,
- T_EQUAL = 288,
- T_NOT = 289
+ T_VISIBLE = 278,
+ T_OPTION = 279,
+ T_ON = 280,
+ T_WORD = 281,
+ T_WORD_QUOTE = 282,
+ T_UNEQUAL = 283,
+ T_CLOSE_PAREN = 284,
+ T_OPEN_PAREN = 285,
+ T_EOL = 286,
+ T_OR = 287,
+ T_AND = 288,
+ T_EQUAL = 289,
+ T_NOT = 290
};
#endif
@@ -417,22 +418,22 @@ union yyalloc
#endif
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 3
+#define YYFINAL 11
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 259
+#define YYLAST 290
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 35
+#define YYNTOKENS 36
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 46
+#define YYNNTS 50
/* YYNRULES -- Number of rules. */
-#define YYNRULES 110
+#define YYNRULES 118
/* YYNRULES -- Number of states. */
-#define YYNSTATES 180
+#define YYNSTATES 191
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 289
+#define YYMAXUTOK 290
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -468,7 +469,8 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35
};
#if YYDEBUG
@@ -476,73 +478,75 @@ static const yytype_uint8 yytranslate[] =
YYRHS. */
static const yytype_uint16 yyprhs[] =
{
- 0, 0, 3, 5, 6, 9, 12, 15, 20, 23,
- 28, 33, 37, 39, 41, 43, 45, 47, 49, 51,
- 53, 55, 57, 59, 61, 63, 67, 70, 74, 77,
- 81, 84, 85, 88, 91, 94, 97, 100, 103, 107,
- 112, 117, 122, 128, 132, 133, 137, 138, 141, 145,
- 148, 150, 154, 155, 158, 161, 164, 167, 170, 175,
- 179, 182, 187, 188, 191, 195, 197, 201, 202, 205,
- 208, 211, 215, 218, 220, 224, 225, 228, 231, 234,
- 238, 242, 245, 248, 251, 252, 255, 258, 261, 266,
- 267, 270, 272, 274, 277, 280, 283, 285, 288, 289,
- 292, 294, 298, 302, 306, 309, 313, 317, 319, 321,
- 322
+ 0, 0, 3, 6, 8, 11, 13, 14, 17, 20,
+ 23, 26, 31, 36, 40, 42, 44, 46, 48, 50,
+ 52, 54, 56, 58, 60, 62, 64, 66, 68, 72,
+ 75, 79, 82, 86, 89, 90, 93, 96, 99, 102,
+ 105, 108, 112, 117, 122, 127, 133, 137, 138, 142,
+ 143, 146, 150, 153, 155, 159, 160, 163, 166, 169,
+ 172, 175, 180, 184, 187, 192, 193, 196, 200, 202,
+ 206, 207, 210, 213, 216, 220, 224, 228, 230, 234,
+ 235, 238, 241, 244, 248, 252, 255, 258, 261, 262,
+ 265, 268, 271, 276, 277, 280, 283, 286, 287, 290,
+ 292, 294, 297, 300, 303, 305, 308, 309, 312, 314,
+ 318, 322, 326, 329, 333, 337, 339, 341, 342
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 36, 0, -1, 37, -1, -1, 37, 39, -1, 37,
- 53, -1, 37, 64, -1, 37, 3, 74, 76, -1,
- 37, 75, -1, 37, 25, 1, 30, -1, 37, 38,
- 1, 30, -1, 37, 1, 30, -1, 16, -1, 18,
- -1, 19, -1, 21, -1, 17, -1, 22, -1, 20,
- -1, 30, -1, 59, -1, 68, -1, 42, -1, 44,
- -1, 66, -1, 25, 1, 30, -1, 1, 30, -1,
- 10, 25, 30, -1, 41, 45, -1, 11, 25, 30,
- -1, 43, 45, -1, -1, 45, 46, -1, 45, 47,
- -1, 45, 72, -1, 45, 70, -1, 45, 40, -1,
- 45, 30, -1, 19, 73, 30, -1, 18, 74, 77,
- 30, -1, 20, 78, 77, 30, -1, 21, 25, 77,
- 30, -1, 22, 79, 79, 77, 30, -1, 23, 48,
- 30, -1, -1, 48, 25, 49, -1, -1, 33, 74,
- -1, 7, 80, 30, -1, 50, 54, -1, 75, -1,
- 51, 56, 52, -1, -1, 54, 55, -1, 54, 72,
- -1, 54, 70, -1, 54, 30, -1, 54, 40, -1,
- 18, 74, 77, 30, -1, 19, 73, 30, -1, 17,
- 30, -1, 20, 25, 77, 30, -1, -1, 56, 39,
- -1, 14, 78, 76, -1, 75, -1, 57, 60, 58,
- -1, -1, 60, 39, -1, 60, 64, -1, 60, 53,
- -1, 4, 74, 30, -1, 61, 71, -1, 75, -1,
- 62, 65, 63, -1, -1, 65, 39, -1, 65, 64,
- -1, 65, 53, -1, 6, 74, 30, -1, 9, 74,
- 30, -1, 67, 71, -1, 12, 30, -1, 69, 13,
- -1, -1, 71, 72, -1, 71, 30, -1, 71, 40,
- -1, 16, 24, 78, 30, -1, -1, 74, 77, -1,
- 25, -1, 26, -1, 5, 30, -1, 8, 30, -1,
- 15, 30, -1, 30, -1, 76, 30, -1, -1, 14,
- 78, -1, 79, -1, 79, 33, 79, -1, 79, 27,
- 79, -1, 29, 78, 28, -1, 34, 78, -1, 78,
- 31, 78, -1, 78, 32, 78, -1, 25, -1, 26,
- -1, -1, 25, -1
+ 37, 0, -1, 81, 38, -1, 38, -1, 63, 39,
+ -1, 39, -1, -1, 39, 41, -1, 39, 55, -1,
+ 39, 67, -1, 39, 80, -1, 39, 26, 1, 31,
+ -1, 39, 40, 1, 31, -1, 39, 1, 31, -1,
+ 16, -1, 18, -1, 19, -1, 21, -1, 17, -1,
+ 22, -1, 20, -1, 23, -1, 31, -1, 61, -1,
+ 71, -1, 44, -1, 46, -1, 69, -1, 26, 1,
+ 31, -1, 1, 31, -1, 10, 26, 31, -1, 43,
+ 47, -1, 11, 26, 31, -1, 45, 47, -1, -1,
+ 47, 48, -1, 47, 49, -1, 47, 75, -1, 47,
+ 73, -1, 47, 42, -1, 47, 31, -1, 19, 78,
+ 31, -1, 18, 79, 82, 31, -1, 20, 83, 82,
+ 31, -1, 21, 26, 82, 31, -1, 22, 84, 84,
+ 82, 31, -1, 24, 50, 31, -1, -1, 50, 26,
+ 51, -1, -1, 34, 79, -1, 7, 85, 31, -1,
+ 52, 56, -1, 80, -1, 53, 58, 54, -1, -1,
+ 56, 57, -1, 56, 75, -1, 56, 73, -1, 56,
+ 31, -1, 56, 42, -1, 18, 79, 82, 31, -1,
+ 19, 78, 31, -1, 17, 31, -1, 20, 26, 82,
+ 31, -1, -1, 58, 41, -1, 14, 83, 81, -1,
+ 80, -1, 59, 62, 60, -1, -1, 62, 41, -1,
+ 62, 67, -1, 62, 55, -1, 3, 79, 81, -1,
+ 4, 79, 31, -1, 64, 76, 74, -1, 80, -1,
+ 65, 68, 66, -1, -1, 68, 41, -1, 68, 67,
+ -1, 68, 55, -1, 6, 79, 31, -1, 9, 79,
+ 31, -1, 70, 74, -1, 12, 31, -1, 72, 13,
+ -1, -1, 74, 75, -1, 74, 31, -1, 74, 42,
+ -1, 16, 25, 83, 31, -1, -1, 76, 77, -1,
+ 76, 31, -1, 23, 82, -1, -1, 79, 82, -1,
+ 26, -1, 27, -1, 5, 31, -1, 8, 31, -1,
+ 15, 31, -1, 31, -1, 81, 31, -1, -1, 14,
+ 83, -1, 84, -1, 84, 34, 84, -1, 84, 28,
+ 84, -1, 30, 83, 29, -1, 35, 83, -1, 83,
+ 32, 83, -1, 83, 33, 83, -1, 26, -1, 27,
+ -1, -1, 26, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 107, 107, 109, 111, 112, 113, 114, 115, 116,
- 117, 121, 125, 125, 125, 125, 125, 125, 125, 129,
- 130, 131, 132, 133, 134, 138, 139, 145, 153, 159,
- 167, 177, 179, 180, 181, 182, 183, 184, 187, 195,
- 201, 211, 217, 223, 226, 228, 239, 240, 245, 254,
- 259, 267, 270, 272, 273, 274, 275, 276, 279, 285,
- 296, 302, 312, 314, 319, 327, 335, 338, 340, 341,
- 342, 347, 354, 359, 367, 370, 372, 373, 374, 377,
- 385, 392, 399, 405, 412, 414, 415, 416, 419, 427,
- 429, 434, 435, 438, 439, 440, 444, 445, 448, 449,
- 452, 453, 454, 455, 456, 457, 458, 461, 462, 465,
- 466
+ 0, 108, 108, 108, 110, 110, 112, 114, 115, 116,
+ 117, 118, 119, 123, 127, 127, 127, 127, 127, 127,
+ 127, 127, 131, 132, 133, 134, 135, 136, 140, 141,
+ 147, 155, 161, 169, 179, 181, 182, 183, 184, 185,
+ 186, 189, 197, 203, 213, 219, 225, 228, 230, 241,
+ 242, 247, 256, 261, 269, 272, 274, 275, 276, 277,
+ 278, 281, 287, 298, 304, 314, 316, 321, 329, 337,
+ 340, 342, 343, 344, 349, 356, 363, 368, 376, 379,
+ 381, 382, 383, 386, 394, 401, 408, 414, 421, 423,
+ 424, 425, 428, 436, 438, 439, 442, 449, 451, 456,
+ 457, 460, 461, 462, 466, 467, 470, 471, 474, 475,
+ 476, 477, 478, 479, 480, 483, 484, 487, 488
};
#endif
@@ -555,19 +559,19 @@ static const char *const yytname[] =
"T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
"T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
"T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
- "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
+ "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
"T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
- "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt",
- "option_error", "config_entry_start", "config_stmt",
+ "T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
+ "common_stmt", "option_error", "config_entry_start", "config_stmt",
"menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
"config_option", "symbol_option", "symbol_option_list",
"symbol_option_arg", "choice", "choice_entry", "choice_end",
"choice_stmt", "choice_option_list", "choice_option", "choice_block",
- "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry",
- "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment",
- "comment_stmt", "help_start", "help", "depends_list", "depends",
- "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol",
- "word_opt", 0
+ "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu",
+ "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
+ "comment", "comment_stmt", "help_start", "help", "depends_list",
+ "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
+ "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0
};
#endif
@@ -579,42 +583,42 @@ static const yytype_uint16 yytoknum[] =
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
- 285, 286, 287, 288, 289
+ 285, 286, 287, 288, 289, 290
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 35, 36, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 38, 38, 38, 38, 38, 38, 38, 39,
- 39, 39, 39, 39, 39, 40, 40, 41, 42, 43,
- 44, 45, 45, 45, 45, 45, 45, 45, 46, 46,
- 46, 46, 46, 47, 48, 48, 49, 49, 50, 51,
- 52, 53, 54, 54, 54, 54, 54, 54, 55, 55,
- 55, 55, 56, 56, 57, 58, 59, 60, 60, 60,
- 60, 61, 62, 63, 64, 65, 65, 65, 65, 66,
- 67, 68, 69, 70, 71, 71, 71, 71, 72, 73,
- 73, 74, 74, 75, 75, 75, 76, 76, 77, 77,
- 78, 78, 78, 78, 78, 78, 78, 79, 79, 80,
- 80
+ 0, 36, 37, 37, 38, 38, 39, 39, 39, 39,
+ 39, 39, 39, 39, 40, 40, 40, 40, 40, 40,
+ 40, 40, 41, 41, 41, 41, 41, 41, 42, 42,
+ 43, 44, 45, 46, 47, 47, 47, 47, 47, 47,
+ 47, 48, 48, 48, 48, 48, 49, 50, 50, 51,
+ 51, 52, 53, 54, 55, 56, 56, 56, 56, 56,
+ 56, 57, 57, 57, 57, 58, 58, 59, 60, 61,
+ 62, 62, 62, 62, 63, 64, 65, 66, 67, 68,
+ 68, 68, 68, 69, 70, 71, 72, 73, 74, 74,
+ 74, 74, 75, 76, 76, 76, 77, 78, 78, 79,
+ 79, 80, 80, 80, 81, 81, 82, 82, 83, 83,
+ 83, 83, 83, 83, 83, 84, 84, 85, 85
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
- 0, 2, 1, 0, 2, 2, 2, 4, 2, 4,
- 4, 3, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 3, 2, 3, 2, 3,
- 2, 0, 2, 2, 2, 2, 2, 2, 3, 4,
- 4, 4, 5, 3, 0, 3, 0, 2, 3, 2,
- 1, 3, 0, 2, 2, 2, 2, 2, 4, 3,
- 2, 4, 0, 2, 3, 1, 3, 0, 2, 2,
- 2, 3, 2, 1, 3, 0, 2, 2, 2, 3,
- 3, 2, 2, 2, 0, 2, 2, 2, 4, 0,
- 2, 1, 1, 2, 2, 2, 1, 2, 0, 2,
- 1, 3, 3, 3, 2, 3, 3, 1, 1, 0,
- 1
+ 0, 2, 2, 1, 2, 1, 0, 2, 2, 2,
+ 2, 4, 4, 3, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 3, 2,
+ 3, 2, 3, 2, 0, 2, 2, 2, 2, 2,
+ 2, 3, 4, 4, 4, 5, 3, 0, 3, 0,
+ 2, 3, 2, 1, 3, 0, 2, 2, 2, 2,
+ 2, 4, 3, 2, 4, 0, 2, 3, 1, 3,
+ 0, 2, 2, 2, 3, 3, 3, 1, 3, 0,
+ 2, 2, 2, 3, 3, 2, 2, 2, 0, 2,
+ 2, 2, 4, 0, 2, 2, 2, 0, 2, 1,
+ 1, 2, 2, 2, 1, 2, 0, 2, 1, 3,
+ 3, 3, 2, 3, 3, 1, 1, 0, 1
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -622,158 +626,172 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 3, 0, 0, 1, 0, 0, 0, 0, 0, 109,
- 0, 0, 0, 0, 0, 0, 12, 16, 13, 14,
- 18, 15, 17, 0, 19, 0, 4, 31, 22, 31,
- 23, 52, 62, 5, 67, 20, 84, 75, 6, 24,
- 84, 21, 8, 11, 91, 92, 0, 0, 93, 0,
- 110, 0, 94, 0, 0, 0, 107, 108, 0, 0,
- 0, 100, 95, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 96, 7, 71, 79, 48, 80, 27,
- 29, 0, 104, 0, 0, 64, 0, 0, 9, 10,
- 0, 0, 0, 0, 89, 0, 0, 0, 44, 0,
- 37, 36, 32, 33, 0, 35, 34, 0, 0, 89,
- 0, 56, 57, 53, 55, 54, 63, 51, 50, 68,
- 70, 66, 69, 65, 86, 87, 85, 76, 78, 74,
- 77, 73, 97, 103, 105, 106, 102, 101, 26, 82,
- 0, 98, 0, 98, 98, 98, 0, 0, 0, 83,
- 60, 98, 0, 98, 0, 0, 0, 38, 90, 0,
- 0, 98, 46, 43, 25, 0, 59, 0, 88, 99,
- 39, 40, 41, 0, 0, 45, 58, 61, 42, 47
+ 6, 0, 104, 0, 3, 0, 6, 6, 99, 100,
+ 0, 1, 0, 0, 0, 0, 117, 0, 0, 0,
+ 0, 0, 0, 14, 18, 15, 16, 20, 17, 19,
+ 21, 0, 22, 0, 7, 34, 25, 34, 26, 55,
+ 65, 8, 70, 23, 93, 79, 9, 27, 88, 24,
+ 10, 0, 105, 2, 74, 13, 0, 101, 0, 118,
+ 0, 102, 0, 0, 0, 115, 116, 0, 0, 0,
+ 108, 103, 0, 0, 0, 0, 0, 0, 0, 88,
+ 0, 0, 75, 83, 51, 84, 30, 32, 0, 112,
+ 0, 0, 67, 0, 0, 11, 12, 0, 0, 0,
+ 0, 97, 0, 0, 0, 47, 0, 40, 39, 35,
+ 36, 0, 38, 37, 0, 0, 97, 0, 59, 60,
+ 56, 58, 57, 66, 54, 53, 71, 73, 69, 72,
+ 68, 106, 95, 0, 94, 80, 82, 78, 81, 77,
+ 90, 91, 89, 111, 113, 114, 110, 109, 29, 86,
+ 0, 106, 0, 106, 106, 106, 0, 0, 0, 87,
+ 63, 106, 0, 106, 0, 96, 0, 0, 41, 98,
+ 0, 0, 106, 49, 46, 28, 0, 62, 0, 107,
+ 92, 42, 43, 44, 0, 0, 48, 61, 64, 45,
+ 50
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 1, 2, 25, 26, 101, 27, 28, 29, 30,
- 65, 102, 103, 147, 175, 31, 32, 117, 33, 67,
- 113, 68, 34, 121, 35, 69, 36, 37, 129, 38,
- 71, 39, 40, 41, 104, 105, 70, 106, 142, 143,
- 42, 74, 156, 60, 61, 51
+ -1, 3, 4, 5, 33, 34, 108, 35, 36, 37,
+ 38, 74, 109, 110, 157, 186, 39, 40, 124, 41,
+ 76, 120, 77, 42, 128, 43, 78, 6, 44, 45,
+ 137, 46, 80, 47, 48, 49, 111, 112, 81, 113,
+ 79, 134, 152, 153, 50, 7, 165, 69, 70, 60
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -80
+#define YYPACT_NINF -90
static const yytype_int16 yypact[] =
{
- -80, 2, 132, -80, -13, -1, -1, -2, -1, 9,
- 33, -1, 27, 40, -3, 38, -80, -80, -80, -80,
- -80, -80, -80, 71, -80, 77, -80, -80, -80, -80,
- -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
- -80, -80, -80, -80, -80, -80, 57, 61, -80, 63,
- -80, 76, -80, 87, 101, 133, -80, -80, -3, -3,
- 195, -6, -80, 136, 149, 39, 104, 65, 150, 5,
- 194, 5, 167, -80, 176, -80, -80, -80, -80, -80,
- -80, 68, -80, -3, -3, 176, 72, 72, -80, -80,
- 177, 187, 78, -1, -1, -3, 196, 72, -80, 222,
- -80, -80, -80, -80, 221, -80, -80, 205, -1, -1,
- 211, -80, -80, -80, -80, -80, -80, -80, -80, -80,
- -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
- -80, -80, -80, -80, 206, -80, -80, -80, -80, -80,
- -3, 223, 209, 223, 197, 223, 72, 7, 210, -80,
- -80, 223, 212, 223, 201, -3, 213, -80, -80, 214,
- 215, 223, 208, -80, -80, 216, -80, 217, -80, 113,
- -80, -80, -80, 218, -1, -80, -80, -80, -80, -80
+ 4, 42, -90, 96, -90, 111, -90, 15, -90, -90,
+ 75, -90, 82, 42, 104, 42, 110, 107, 42, 115,
+ 125, -4, 121, -90, -90, -90, -90, -90, -90, -90,
+ -90, 162, -90, 163, -90, -90, -90, -90, -90, -90,
+ -90, -90, -90, -90, -90, -90, -90, -90, -90, -90,
+ -90, 139, -90, -90, 138, -90, 142, -90, 143, -90,
+ 152, -90, 164, 167, 168, -90, -90, -4, -4, 77,
+ -18, -90, 177, 185, 33, 71, 195, 247, 236, -2,
+ 236, 171, -90, -90, -90, -90, -90, -90, 41, -90,
+ -4, -4, 138, 97, 97, -90, -90, 186, 187, 194,
+ 42, 42, -4, 196, 97, -90, 219, -90, -90, -90,
+ -90, 210, -90, -90, 204, 42, 42, 199, -90, -90,
+ -90, -90, -90, -90, -90, -90, -90, -90, -90, -90,
+ -90, 222, -90, 223, -90, -90, -90, -90, -90, -90,
+ -90, -90, -90, -90, 215, -90, -90, -90, -90, -90,
+ -4, 222, 228, 222, -5, 222, 97, 35, 229, -90,
+ -90, 222, 232, 222, -4, -90, 135, 233, -90, -90,
+ 234, 235, 222, 240, -90, -90, 237, -90, 239, -13,
+ -90, -90, -90, -90, 244, 42, -90, -90, -90, -90,
+ -90
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -80, -80, -80, -80, 122, -34, -80, -80, -80, -80,
- 220, -80, -80, -80, -80, -80, -80, -80, 59, -80,
- -80, -80, -80, -80, -80, -80, -80, -80, -80, 125,
- -80, -80, -80, -80, -80, 183, 219, 22, 142, -5,
- 147, 192, 69, -54, -79, -80
+ -90, -90, 269, 271, -90, 23, -70, -90, -90, -90,
+ -90, 243, -90, -90, -90, -90, -90, -90, -90, -48,
+ -90, -90, -90, -90, -90, -90, -90, -90, -90, -90,
+ -90, -20, -90, -90, -90, -90, -90, 206, 205, -68,
+ -90, -90, 169, -1, 27, -7, 118, -66, -89, -90
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -82
+#define YYTABLE_NINF -86
static const yytype_int16 yytable[] =
{
- 46, 47, 3, 49, 81, 82, 53, 136, 137, 6,
- 7, 8, 9, 10, 11, 12, 13, 43, 146, 14,
- 15, 86, 56, 57, 44, 45, 58, 87, 48, 134,
- 135, 59, 162, 112, 50, 24, 125, 163, 125, -28,
- 90, 144, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, 91, 54, -28, -28, 92, -28, 93, 94, 95,
- 96, 97, 98, 52, 99, 55, 90, 161, 62, 100,
- -49, -49, 63, -49, -49, -49, -49, 91, 64, -49,
- -49, 92, 107, 108, 109, 110, 154, 73, 141, 115,
- 99, 75, 126, 76, 126, 111, 133, 56, 57, 83,
- 84, 169, 140, 151, -30, 90, 77, -30, -30, -30,
- -30, -30, -30, -30, -30, -30, 91, 78, -30, -30,
- 92, -30, 93, 94, 95, 96, 97, 98, 120, 99,
- 128, 79, -2, 4, 100, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 83, 84, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 7, 8, 23, 10, 11,
- 12, 13, 24, 80, 14, 15, 88, -81, 90, 179,
- -81, -81, -81, -81, -81, -81, -81, -81, -81, 89,
- 24, -81, -81, 92, -81, -81, -81, -81, -81, -81,
- 116, 119, 99, 127, 122, 90, 130, 124, -72, -72,
- -72, -72, -72, -72, -72, -72, 132, 138, -72, -72,
- 92, 155, 158, 159, 160, 118, 123, 139, 131, 99,
- 165, 145, 167, 148, 124, 73, 83, 84, 83, 84,
- 173, 168, 83, 84, 149, 150, 153, 155, 84, 157,
- 164, 174, 166, 170, 171, 172, 176, 177, 178, 66,
- 114, 152, 85, 0, 0, 0, 0, 0, 0, 72
+ 10, 88, 89, 54, 146, 147, 119, 1, 122, 164,
+ 93, 141, 56, 142, 58, 156, 94, 62, 1, 90,
+ 91, 131, 65, 66, 144, 145, 67, 90, 91, 132,
+ 127, 68, 136, -31, 97, 2, 154, -31, -31, -31,
+ -31, -31, -31, -31, -31, 98, 52, -31, -31, 99,
+ -31, 100, 101, 102, 103, 104, -31, 105, 129, 106,
+ 138, 173, 92, 141, 107, 142, 174, 172, 8, 9,
+ 143, -33, 97, 90, 91, -33, -33, -33, -33, -33,
+ -33, -33, -33, 98, 166, -33, -33, 99, -33, 100,
+ 101, 102, 103, 104, -33, 105, 11, 106, 179, 151,
+ 123, 126, 107, 135, 125, 130, 2, 139, 2, 90,
+ 91, -5, 12, 55, 161, 13, 14, 15, 16, 17,
+ 18, 19, 20, 65, 66, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 57, 59, 31, 61, -4,
+ 12, 63, 32, 13, 14, 15, 16, 17, 18, 19,
+ 20, 64, 71, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 72, 73, 31, 180, 90, 91, 52,
+ 32, -85, 97, 82, 83, -85, -85, -85, -85, -85,
+ -85, -85, -85, 84, 190, -85, -85, 99, -85, -85,
+ -85, -85, -85, -85, -85, 85, 97, 106, 86, 87,
+ -52, -52, 140, -52, -52, -52, -52, 98, 95, -52,
+ -52, 99, 114, 115, 116, 117, 96, 148, 149, 150,
+ 158, 106, 155, 159, 97, 163, 118, -76, -76, -76,
+ -76, -76, -76, -76, -76, 160, 164, -76, -76, 99,
+ 13, 14, 15, 16, 17, 18, 19, 20, 91, 106,
+ 21, 22, 14, 15, 140, 17, 18, 19, 20, 168,
+ 175, 21, 22, 177, 181, 182, 183, 32, 187, 167,
+ 188, 169, 170, 171, 185, 189, 53, 51, 32, 176,
+ 75, 178, 121, 0, 133, 162, 0, 0, 0, 0,
+ 184
};
static const yytype_int16 yycheck[] =
{
- 5, 6, 0, 8, 58, 59, 11, 86, 87, 4,
- 5, 6, 7, 8, 9, 10, 11, 30, 97, 14,
- 15, 27, 25, 26, 25, 26, 29, 33, 30, 83,
- 84, 34, 25, 67, 25, 30, 70, 30, 72, 0,
- 1, 95, 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 25, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 30, 25, 25, 1, 146, 30, 30,
- 5, 6, 1, 8, 9, 10, 11, 12, 1, 14,
- 15, 16, 17, 18, 19, 20, 140, 30, 93, 67,
- 25, 30, 70, 30, 72, 30, 28, 25, 26, 31,
- 32, 155, 24, 108, 0, 1, 30, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 30, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 69, 25,
- 71, 30, 0, 1, 30, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 31, 32, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 5, 6, 25, 8, 9,
- 10, 11, 30, 30, 14, 15, 30, 0, 1, 174,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 30,
- 30, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 68, 69, 25, 71, 69, 1, 71, 30, 4, 5,
- 6, 7, 8, 9, 10, 11, 30, 30, 14, 15,
- 16, 14, 143, 144, 145, 68, 69, 30, 71, 25,
- 151, 25, 153, 1, 30, 30, 31, 32, 31, 32,
- 161, 30, 31, 32, 13, 30, 25, 14, 32, 30,
- 30, 33, 30, 30, 30, 30, 30, 30, 30, 29,
- 67, 109, 60, -1, -1, -1, -1, -1, -1, 40
+ 1, 67, 68, 10, 93, 94, 76, 3, 76, 14,
+ 28, 81, 13, 81, 15, 104, 34, 18, 3, 32,
+ 33, 23, 26, 27, 90, 91, 30, 32, 33, 31,
+ 78, 35, 80, 0, 1, 31, 102, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 31, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 78, 26,
+ 80, 26, 69, 133, 31, 133, 31, 156, 26, 27,
+ 29, 0, 1, 32, 33, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 150, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 0, 26, 164, 100,
+ 77, 78, 31, 80, 77, 78, 31, 80, 31, 32,
+ 33, 0, 1, 31, 115, 4, 5, 6, 7, 8,
+ 9, 10, 11, 26, 27, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 31, 26, 26, 31, 0,
+ 1, 26, 31, 4, 5, 6, 7, 8, 9, 10,
+ 11, 26, 31, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 1, 1, 26, 31, 32, 33, 31,
+ 31, 0, 1, 31, 31, 4, 5, 6, 7, 8,
+ 9, 10, 11, 31, 185, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 31, 1, 26, 31, 31,
+ 5, 6, 31, 8, 9, 10, 11, 12, 31, 14,
+ 15, 16, 17, 18, 19, 20, 31, 31, 31, 25,
+ 1, 26, 26, 13, 1, 26, 31, 4, 5, 6,
+ 7, 8, 9, 10, 11, 31, 14, 14, 15, 16,
+ 4, 5, 6, 7, 8, 9, 10, 11, 33, 26,
+ 14, 15, 5, 6, 31, 8, 9, 10, 11, 31,
+ 31, 14, 15, 31, 31, 31, 31, 31, 31, 151,
+ 31, 153, 154, 155, 34, 31, 7, 6, 31, 161,
+ 37, 163, 76, -1, 79, 116, -1, -1, -1, -1,
+ 172
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 36, 37, 0, 1, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 25, 30, 38, 39, 41, 42, 43,
- 44, 50, 51, 53, 57, 59, 61, 62, 64, 66,
- 67, 68, 75, 30, 25, 26, 74, 74, 30, 74,
- 25, 80, 30, 74, 25, 25, 25, 26, 29, 34,
- 78, 79, 30, 1, 1, 45, 45, 54, 56, 60,
- 71, 65, 71, 30, 76, 30, 30, 30, 30, 30,
- 30, 78, 78, 31, 32, 76, 27, 33, 30, 30,
- 1, 12, 16, 18, 19, 20, 21, 22, 23, 25,
- 30, 40, 46, 47, 69, 70, 72, 17, 18, 19,
- 20, 30, 40, 55, 70, 72, 39, 52, 75, 39,
- 53, 58, 64, 75, 30, 40, 72, 39, 53, 63,
- 64, 75, 30, 28, 78, 78, 79, 79, 30, 30,
- 24, 74, 73, 74, 78, 25, 79, 48, 1, 13,
- 30, 74, 73, 25, 78, 14, 77, 30, 77, 77,
- 77, 79, 25, 30, 30, 77, 30, 77, 30, 78,
- 30, 30, 30, 77, 33, 49, 30, 30, 30, 74
+ 0, 3, 31, 37, 38, 39, 63, 81, 26, 27,
+ 79, 0, 1, 4, 5, 6, 7, 8, 9, 10,
+ 11, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 26, 31, 40, 41, 43, 44, 45, 46, 52,
+ 53, 55, 59, 61, 64, 65, 67, 69, 70, 71,
+ 80, 39, 31, 38, 81, 31, 79, 31, 79, 26,
+ 85, 31, 79, 26, 26, 26, 27, 30, 35, 83,
+ 84, 31, 1, 1, 47, 47, 56, 58, 62, 76,
+ 68, 74, 31, 31, 31, 31, 31, 31, 83, 83,
+ 32, 33, 81, 28, 34, 31, 31, 1, 12, 16,
+ 18, 19, 20, 21, 22, 24, 26, 31, 42, 48,
+ 49, 72, 73, 75, 17, 18, 19, 20, 31, 42,
+ 57, 73, 75, 41, 54, 80, 41, 55, 60, 67,
+ 80, 23, 31, 74, 77, 41, 55, 66, 67, 80,
+ 31, 42, 75, 29, 83, 83, 84, 84, 31, 31,
+ 25, 79, 78, 79, 83, 26, 84, 50, 1, 13,
+ 31, 79, 78, 26, 14, 82, 83, 82, 31, 82,
+ 82, 82, 84, 26, 31, 31, 82, 31, 82, 83,
+ 31, 31, 31, 31, 82, 34, 51, 31, 31, 31,
+ 79
};
#define yyerrok (yyerrstatus = 0)
@@ -1284,7 +1302,7 @@ yydestruct (yymsg, yytype, yyvaluep)
switch (yytype)
{
- case 51: /* "choice_entry" */
+ case 53: /* "choice_entry" */
{
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1294,7 +1312,7 @@ yydestruct (yymsg, yytype, yyvaluep)
};
break;
- case 57: /* "if_entry" */
+ case 59: /* "if_entry" */
{
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1304,7 +1322,7 @@ yydestruct (yymsg, yytype, yyvaluep)
};
break;
- case 62: /* "menu_entry" */
+ case 65: /* "menu_entry" */
{
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1614,39 +1632,39 @@ yyreduce:
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
- case 8:
+ case 10:
{ zconf_error("unexpected end statement"); ;}
break;
- case 9:
+ case 11:
{ zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;}
break;
- case 10:
+ case 12:
{
zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
;}
break;
- case 11:
+ case 13:
{ zconf_error("invalid statement"); ;}
break;
- case 25:
+ case 28:
{ zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;}
break;
- case 26:
+ case 29:
{ zconf_error("invalid option"); ;}
break;
- case 27:
+ case 30:
{
struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
@@ -1656,7 +1674,7 @@ yyreduce:
;}
break;
- case 28:
+ case 31:
{
menu_end_entry();
@@ -1664,7 +1682,7 @@ yyreduce:
;}
break;
- case 29:
+ case 32:
{
struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
@@ -1674,7 +1692,7 @@ yyreduce:
;}
break;
- case 30:
+ case 33:
{
if (current_entry->prompt)
@@ -1686,7 +1704,7 @@ yyreduce:
;}
break;
- case 38:
+ case 41:
{
menu_set_type((yyvsp[(1) - (3)].id)->stype);
@@ -1696,7 +1714,7 @@ yyreduce:
;}
break;
- case 39:
+ case 42:
{
menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
@@ -1704,7 +1722,7 @@ yyreduce:
;}
break;
- case 40:
+ case 43:
{
menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
@@ -1716,7 +1734,7 @@ yyreduce:
;}
break;
- case 41:
+ case 44:
{
menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
@@ -1724,7 +1742,7 @@ yyreduce:
;}
break;
- case 42:
+ case 45:
{
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
@@ -1732,7 +1750,7 @@ yyreduce:
;}
break;
- case 45:
+ case 48:
{
struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
@@ -1744,17 +1762,17 @@ yyreduce:
;}
break;
- case 46:
+ case 49:
{ (yyval.string) = NULL; ;}
break;
- case 47:
+ case 50:
{ (yyval.string) = (yyvsp[(2) - (2)].string); ;}
break;
- case 48:
+ case 51:
{
struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
@@ -1765,14 +1783,14 @@ yyreduce:
;}
break;
- case 49:
+ case 52:
{
(yyval.menu) = menu_add_menu();
;}
break;
- case 50:
+ case 53:
{
if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
@@ -1782,7 +1800,7 @@ yyreduce:
;}
break;
- case 58:
+ case 61:
{
menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
@@ -1790,7 +1808,7 @@ yyreduce:
;}
break;
- case 59:
+ case 62:
{
if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
@@ -1803,7 +1821,7 @@ yyreduce:
;}
break;
- case 60:
+ case 63:
{
current_entry->sym->flags |= SYMBOL_OPTIONAL;
@@ -1811,7 +1829,7 @@ yyreduce:
;}
break;
- case 61:
+ case 64:
{
if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
@@ -1823,7 +1841,7 @@ yyreduce:
;}
break;
- case 64:
+ case 67:
{
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
@@ -1833,7 +1851,7 @@ yyreduce:
;}
break;
- case 65:
+ case 68:
{
if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
@@ -1843,7 +1861,14 @@ yyreduce:
;}
break;
- case 71:
+ case 74:
+
+ {
+ menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+;}
+ break;
+
+ case 75:
{
menu_add_entry(NULL);
@@ -1852,14 +1877,14 @@ yyreduce:
;}
break;
- case 72:
+ case 76:
{
(yyval.menu) = menu_add_menu();
;}
break;
- case 73:
+ case 77:
{
if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
@@ -1869,7 +1894,7 @@ yyreduce:
;}
break;
- case 79:
+ case 83:
{
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
@@ -1877,7 +1902,7 @@ yyreduce:
;}
break;
- case 80:
+ case 84:
{
menu_add_entry(NULL);
@@ -1886,14 +1911,14 @@ yyreduce:
;}
break;
- case 81:
+ case 85:
{
menu_end_entry();
;}
break;
- case 82:
+ case 86:
{
printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
@@ -1901,14 +1926,14 @@ yyreduce:
;}
break;
- case 83:
+ case 87:
{
current_entry->help = (yyvsp[(2) - (2)].string);
;}
break;
- case 88:
+ case 92:
{
menu_add_dep((yyvsp[(3) - (4)].expr));
@@ -1916,84 +1941,91 @@ yyreduce:
;}
break;
- case 90:
+ case 96:
+
+ {
+ menu_add_visibility((yyvsp[(2) - (2)].expr));
+;}
+ break;
+
+ case 98:
{
menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
;}
break;
- case 93:
+ case 101:
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
break;
- case 94:
+ case 102:
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
break;
- case 95:
+ case 103:
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
break;
- case 98:
+ case 106:
{ (yyval.expr) = NULL; ;}
break;
- case 99:
+ case 107:
{ (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
break;
- case 100:
+ case 108:
{ (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;}
break;
- case 101:
+ case 109:
{ (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
break;
- case 102:
+ case 110:
{ (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
break;
- case 103:
+ case 111:
{ (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
break;
- case 104:
+ case 112:
{ (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;}
break;
- case 105:
+ case 113:
{ (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
- case 106:
+ case 114:
{ (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
- case 107:
+ case 115:
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;}
break;
- case 108:
+ case 116:
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;}
break;
- case 109:
+ case 117:
{ (yyval.string) = NULL; ;}
break;
@@ -2239,6 +2271,10 @@ void conf_parse(const char *name)
prop = prop_alloc(P_DEFAULT, modules_sym);
prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
}
+
+ rootmenu.prompt->text = _(rootmenu.prompt->text);
+ rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
+
menu_finalize(&rootmenu);
for_all_symbols(i, sym) {
if (sym_check_deps(sym))
@@ -2259,6 +2295,7 @@ static const char *zconf_tokenname(int token)
case T_IF: return "if";
case T_ENDIF: return "endif";
case T_DEPENDS: return "depends";
+ case T_VISIBLE: return "visible";
}
return "<token>";
}
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 23dfd3baa7a1..49fb4ab664c3 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -36,7 +36,7 @@ static struct menu *current_menu, *current_entry;
#define YYERROR_VERBOSE
#endif
%}
-%expect 26
+%expect 30
%union
{
@@ -68,6 +68,7 @@ static struct menu *current_menu, *current_entry;
%token <id>T_DEFAULT
%token <id>T_SELECT
%token <id>T_RANGE
+%token <id>T_VISIBLE
%token <id>T_OPTION
%token <id>T_ON
%token <string> T_WORD
@@ -104,14 +105,15 @@ static struct menu *current_menu, *current_entry;
%}
%%
-input: stmt_list;
+input: nl start | start;
+
+start: mainmenu_stmt stmt_list | stmt_list;
stmt_list:
/* empty */
| stmt_list common_stmt
| stmt_list choice_stmt
| stmt_list menu_stmt
- | stmt_list T_MAINMENU prompt nl
| stmt_list end { zconf_error("unexpected end statement"); }
| stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
| stmt_list option_name error T_EOL
@@ -122,7 +124,7 @@ stmt_list:
;
option_name:
- T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
+ T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
;
common_stmt:
@@ -342,6 +344,13 @@ if_block:
| if_block choice_stmt
;
+/* mainmenu entry */
+
+mainmenu_stmt: T_MAINMENU prompt nl
+{
+ menu_add_prompt(P_MENU, $2, NULL);
+};
+
/* menu entry */
menu: T_MENU prompt T_EOL
@@ -351,7 +360,7 @@ menu: T_MENU prompt T_EOL
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
};
-menu_entry: menu depends_list
+menu_entry: menu visibility_list depends_list
{
$$ = menu_add_menu();
};
@@ -422,6 +431,19 @@ depends: T_DEPENDS T_ON expr T_EOL
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
};
+/* visibility option */
+
+visibility_list:
+ /* empty */
+ | visibility_list visible
+ | visibility_list T_EOL
+;
+
+visible: T_VISIBLE if_expr
+{
+ menu_add_visibility($2);
+};
+
/* prompt statement */
prompt_stmt_opt:
@@ -494,6 +516,10 @@ void conf_parse(const char *name)
prop = prop_alloc(P_DEFAULT, modules_sym);
prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
}
+
+ rootmenu.prompt->text = _(rootmenu.prompt->text);
+ rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
+
menu_finalize(&rootmenu);
for_all_symbols(i, sym) {
if (sym_check_deps(sym))
@@ -514,6 +540,7 @@ static const char *zconf_tokenname(int token)
case T_IF: return "if";
case T_ENDIF: return "endif";
case T_DEPENDS: return "depends";
+ case T_VISIBLE: return "visible";
}
return "<token>";
}
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 241310e59cd6..9f85012acf0d 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -5,7 +5,7 @@ use strict;
## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ##
## Copyright (C) 2001 Simon Huggins ##
-## Copyright (C) 2005-2009 Randy Dunlap ##
+## Copyright (C) 2005-2010 Randy Dunlap ##
## ##
## #define enhancements by Armin Kuster <akuster@mvista.com> ##
## Copyright (c) 2000 MontaVista Software, Inc. ##
@@ -13,8 +13,6 @@ use strict;
## This software falls under the GNU General Public License. ##
## Please read the COPYING file for more information ##
-# w.o. 03-11-2000: added the '-filelist' option.
-
# 18/01/2001 - Cleanups
# Functions prototyped as foo(void) same as foo()
# Stop eval'ing where we don't need to.
@@ -46,12 +44,13 @@ use strict;
# Note: This only supports 'c'.
# usage:
-# kernel-doc [ -docbook | -html | -text | -man ] [ -no-doc-sections ]
+# kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ]
# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
# or
# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
#
# Set output format using one of -docbook -html -text or -man. Default is man.
+# The -list format is for internal use by docproc.
#
# -no-doc-sections
# Do not output DOC: sections
@@ -156,6 +155,8 @@ use strict;
# '@parameter' - name of a parameter
# '%CONST' - name of a constant.
+## init lots of data
+
my $errors = 0;
my $warnings = 0;
my $anon_struct_union = 0;
@@ -212,21 +213,21 @@ my %highlights_text = ( $type_constant, "\$1",
$type_param, "\$1" );
my $blankline_text = "";
-
-sub usage {
- print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ] [ -no-doc-sections ]\n";
- print " [ -function funcname [ -function funcname ...] ]\n";
- print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
- print " c source file(s) > outputfile\n";
- print " -v : verbose output, more warnings & other info listed\n";
- exit 1;
-}
+# list mode
+my %highlights_list = ( $type_constant, "\$1",
+ $type_func, "\$1",
+ $type_struct, "\$1",
+ $type_param, "\$1" );
+my $blankline_list = "";
# read arguments
if ($#ARGV == -1) {
usage();
}
+my $kernelversion;
+my $dohighlight = "";
+
my $verbose = 0;
my $output_mode = "man";
my $no_doc_sections = 0;
@@ -239,13 +240,13 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
'November', 'December')[(localtime)[4]] .
" " . ((localtime)[5]+1900);
-# Essentially these are globals
+# Essentially these are globals.
# They probably want to be tidied up, made more localised or something.
# CAVEAT EMPTOR! Some of the others I localised may not want to be, which
# could cause "use of undefined value" or other bugs.
my ($function, %function_table, %parametertypes, $declaration_purpose);
my ($type, $declaration_name, $return_type);
-my ($newsection, $newcontents, $prototype, $filelist, $brcount, %source_map);
+my ($newsection, $newcontents, $prototype, $brcount, %source_map);
if (defined($ENV{'KBUILD_VERBOSE'})) {
$verbose = "$ENV{'KBUILD_VERBOSE'}";
@@ -320,6 +321,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
$output_mode = "xml";
%highlights = %highlights_xml;
$blankline = $blankline_xml;
+ } elsif ($cmd eq "-list") {
+ $output_mode = "list";
+ %highlights = %highlights_list;
+ $blankline = $blankline_list;
} elsif ($cmd eq "-gnome") {
$output_mode = "gnome";
%highlights = %highlights_gnome;
@@ -338,13 +343,23 @@ while ($ARGV[0] =~ m/^-(.*)/) {
$verbose = 1;
} elsif (($cmd eq "-h") || ($cmd eq "--help")) {
usage();
- } elsif ($cmd eq '-filelist') {
- $filelist = shift @ARGV;
} elsif ($cmd eq '-no-doc-sections') {
$no_doc_sections = 1;
}
}
+# continue execution near EOF;
+
+sub usage {
+ print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n";
+ print " [ -no-doc-sections ]\n";
+ print " [ -function funcname [ -function funcname ...] ]\n";
+ print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
+ print " c source file(s) > outputfile\n";
+ print " -v : verbose output, more warnings & other info listed\n";
+ exit 1;
+}
+
# get kernel version from env
sub get_kernel_version() {
my $version = 'unknown kernel version';
@@ -354,15 +369,6 @@ sub get_kernel_version() {
}
return $version;
}
-my $kernelversion = get_kernel_version();
-
-# generate a sequence of code that will splice in highlighting information
-# using the s// operator.
-my $dohighlight = "";
-foreach my $pattern (keys %highlights) {
-# print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
- $dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
-}
##
# dumps section contents to arrays/hashes intended for that purpose.
@@ -445,7 +451,7 @@ sub output_highlight {
if ($output_mode eq "html" || $output_mode eq "xml") {
$contents = local_unescape($contents);
# convert data read & converted thru xml_escape() into &xyz; format:
- $contents =~ s/\\\\\\/&/g;
+ $contents =~ s/\\\\\\/\&/g;
}
# print STDERR "contents b4:$contents\n";
eval $dohighlight;
@@ -762,7 +768,11 @@ sub output_struct_xml(%) {
print $args{'type'} . " " . $args{'struct'} . " {\n";
foreach $parameter (@{$args{'parameterlist'}}) {
if ($parameter =~ /^#/) {
- print "$parameter\n";
+ my $prm = $parameter;
+ # convert data read & converted thru xml_escape() into &xyz; format:
+ # This allows us to have #define macros interspersed in a struct.
+ $prm =~ s/\\\\\\/\&/g;
+ print "$prm\n";
next;
}
@@ -1365,6 +1375,42 @@ sub output_blockhead_text(%) {
}
}
+## list mode output functions
+
+sub output_function_list(%) {
+ my %args = %{$_[0]};
+
+ print $args{'function'} . "\n";
+}
+
+# output enum in list
+sub output_enum_list(%) {
+ my %args = %{$_[0]};
+ print $args{'enum'} . "\n";
+}
+
+# output typedef in list
+sub output_typedef_list(%) {
+ my %args = %{$_[0]};
+ print $args{'typedef'} . "\n";
+}
+
+# output struct as list
+sub output_struct_list(%) {
+ my %args = %{$_[0]};
+
+ print $args{'struct'} . "\n";
+}
+
+sub output_blockhead_list(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "DOC: $section\n";
+ }
+}
+
##
# generic output function for all types (function, struct/union, typedef, enum);
# calls the generated, variable output_ function name based on
@@ -1428,6 +1474,8 @@ sub dump_struct($$) {
$nested =~ s/\/\*.*?\*\///gos;
# strip kmemcheck_bitfield_{begin,end}.*;
$members =~ s/kmemcheck_bitfield_.*?;//gos;
+ # strip attributes
+ $members =~ s/__aligned\s*\(\d+\)//gos;
create_parameterlist($members, ';', $file);
check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
@@ -1456,6 +1504,8 @@ sub dump_enum($$) {
my $file = shift;
$x =~ s@/\*.*?\*/@@gos; # strip comments.
+ $x =~ s/^#\s*define\s+.*$//; # strip #define macros inside enums
+
if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
$declaration_name = $1;
my $members = $2;
@@ -1653,6 +1703,8 @@ sub push_parameter($$$) {
}
}
+ $param = xml_escape($param);
+
# strip spaces from $param so that it is one continous string
# on @parameterlist;
# this fixes a problem where check_sections() cannot find
@@ -1679,7 +1731,7 @@ sub check_sections($$$$$$) {
foreach $px (0 .. $#prms) {
$prm_clean = $prms[$px];
$prm_clean =~ s/\[.*\]//;
- $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//;
+ $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
# ignore array size in a parameter string;
# however, the original param string may contain
# spaces, e.g.: addr[6 + 2]
@@ -1732,6 +1784,7 @@ sub dump_function($$) {
$prototype =~ s/^noinline +//;
$prototype =~ s/__devinit +//;
$prototype =~ s/__init +//;
+ $prototype =~ s/__init_or_module +//;
$prototype =~ s/^#\s*define\s+//; #ak added
$prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
@@ -1796,42 +1849,6 @@ sub dump_function($$) {
});
}
-sub process_file($);
-
-# Read the file that maps relative names to absolute names for
-# separate source and object directories and for shadow trees.
-if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
- my ($relname, $absname);
- while(<SOURCE_MAP>) {
- chop();
- ($relname, $absname) = (split())[0..1];
- $relname =~ s:^/+::;
- $source_map{$relname} = $absname;
- }
- close(SOURCE_MAP);
-}
-
-if ($filelist) {
- open(FLIST,"<$filelist") or die "Can't open file list $filelist";
- while(<FLIST>) {
- chop;
- process_file($_);
- }
-}
-
-foreach (@ARGV) {
- chomp;
- process_file($_);
-}
-if ($verbose && $errors) {
- print STDERR "$errors errors\n";
-}
-if ($verbose && $warnings) {
- print STDERR "$warnings warnings\n";
-}
-
-exit($errors);
-
sub reset_state {
$function = "";
%constants = ();
@@ -2023,6 +2040,8 @@ sub process_file($) {
return;
}
+ $. = 1;
+
$section_counter = 0;
while (<IN>) {
if ($state == 0) {
@@ -2113,7 +2132,7 @@ sub process_file($) {
$section = $newsection;
} elsif (/$doc_end/) {
- if ($contents ne "") {
+ if (($contents ne "") && ($contents ne "\n")) {
dump_section($file, $section, xml_escape($contents));
$section = $section_default;
$contents = "";
@@ -2236,3 +2255,39 @@ sub process_file($) {
}
}
}
+
+
+$kernelversion = get_kernel_version();
+
+# generate a sequence of code that will splice in highlighting information
+# using the s// operator.
+foreach my $pattern (keys %highlights) {
+# print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
+ $dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
+}
+
+# Read the file that maps relative names to absolute names for
+# separate source and object directories and for shadow trees.
+if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
+ my ($relname, $absname);
+ while(<SOURCE_MAP>) {
+ chop();
+ ($relname, $absname) = (split())[0..1];
+ $relname =~ s:^/+::;
+ $source_map{$relname} = $absname;
+ }
+ close(SOURCE_MAP);
+}
+
+foreach (@ARGV) {
+ chomp;
+ process_file($_);
+}
+if ($verbose && $errors) {
+ print STDERR "$errors errors\n";
+}
+if ($verbose && $warnings) {
+ print STDERR "$warnings warnings\n";
+}
+
+exit($errors);
diff --git a/scripts/markup_oops.pl b/scripts/markup_oops.pl
index 90e1d9aa35b5..827896f56501 100644
--- a/scripts/markup_oops.pl
+++ b/scripts/markup_oops.pl
@@ -168,7 +168,7 @@ while (<STDIN>) {
$function = $1;
$func_offset = $2;
}
- if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\] \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]/) {
+ if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\] \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+0x([0-9a-f]+)\/0x[a-f0-9]/) {
$function = $1;
$func_offset = $2;
}
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index 67d59c7a18dc..5325423ceab4 100644
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
@@ -44,7 +44,9 @@ all:
Makefile:;
-\$(all) %/: all
+\$(all): all
@:
+%/: all
+ @:
EOF
diff --git a/scripts/mkuboot.sh b/scripts/mkuboot.sh
index 2e3d3cd916b8..446739c7843a 100755
--- a/scripts/mkuboot.sh
+++ b/scripts/mkuboot.sh
@@ -11,7 +11,7 @@ if [ -z "${MKIMAGE}" ]; then
if [ -z "${MKIMAGE}" ]; then
# Doesn't exist
echo '"mkimage" command not found - U-Boot images will not be built' >&2
- exit 0;
+ exit 1;
fi
fi
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 220213e603db..88f3f07205f8 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -796,6 +796,51 @@ static int do_platform_entry(const char *filename,
return 1;
}
+static int do_mdio_entry(const char *filename,
+ struct mdio_device_id *id, char *alias)
+{
+ int i;
+
+ alias += sprintf(alias, MDIO_MODULE_PREFIX);
+
+ for (i = 0; i < 32; i++) {
+ if (!((id->phy_id_mask >> (31-i)) & 1))
+ *(alias++) = '?';
+ else if ((id->phy_id >> (31-i)) & 1)
+ *(alias++) = '1';
+ else
+ *(alias++) = '0';
+ }
+
+ /* Terminate the string */
+ *alias = 0;
+
+ return 1;
+}
+
+/* Looks like: zorro:iN. */
+static int do_zorro_entry(const char *filename, struct zorro_device_id *id,
+ char *alias)
+{
+ id->id = TO_NATIVE(id->id);
+ strcpy(alias, "zorro:");
+ ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id);
+ return 1;
+}
+
+/* looks like: "pnp:dD" */
+static int do_isapnp_entry(const char *filename,
+ struct isapnp_device_id *id, char *alias)
+{
+ sprintf(alias, "pnp:d%c%c%c%x%x%x%x*",
+ 'A' + ((id->vendor >> 2) & 0x3f) - 1,
+ 'A' + (((id->vendor & 3) << 3) | ((id->vendor >> 13) & 7)) - 1,
+ 'A' + ((id->vendor >> 8) & 0x1f) - 1,
+ (id->function >> 4) & 0x0f, id->function & 0x0f,
+ (id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f);
+ return 1;
+}
+
/* Ignore any prefix, eg. some architectures prepend _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -839,16 +884,16 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
char *zeros = NULL;
/* We're looking for a section relative symbol */
- if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum)
+ if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
return;
/* Handle all-NULL symbols allocated into .bss */
- if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) {
+ if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
zeros = calloc(1, sym->st_size);
symval = zeros;
} else {
symval = (void *)info->hdr
- + info->sechdrs[sym->st_shndx].sh_offset
+ + info->sechdrs[get_secindex(info, sym)].sh_offset
+ sym->st_value;
}
@@ -943,6 +988,18 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
do_table(symval, sym->st_size,
sizeof(struct platform_device_id), "platform",
do_platform_entry, mod);
+ else if (sym_is(symname, "__mod_mdio_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct mdio_device_id), "mdio",
+ do_mdio_entry, mod);
+ else if (sym_is(symname, "__mod_zorro_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct zorro_device_id), "zorro",
+ do_zorro_entry, mod);
+ else if (sym_is(symname, "__mod_isapnp_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct isapnp_device_id), "isa",
+ do_isapnp_entry, mod);
free(zeros);
}
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 3318692e4e76..97d2259ae999 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -14,6 +14,7 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <ctype.h>
+#include <string.h>
#include "modpost.h"
#include "../../include/generated/autoconf.h"
#include "../../include/linux/license.h"
@@ -253,7 +254,7 @@ static enum export export_no(const char *s)
return export_unknown;
}
-static enum export export_from_sec(struct elf_info *elf, Elf_Section sec)
+static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
{
if (sec == elf->export_sec)
return export_plain;
@@ -373,6 +374,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
Elf_Ehdr *hdr;
Elf_Shdr *sechdrs;
Elf_Sym *sym;
+ const char *secstrings;
+ unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U;
hdr = grab_file(filename, &info->size);
if (!hdr) {
@@ -417,8 +420,27 @@ static int parse_elf(struct elf_info *info, const char *filename)
return 0;
}
+ if (hdr->e_shnum == 0) {
+ /*
+ * There are more than 64k sections,
+ * read count from .sh_size.
+ * note: it doesn't need shndx2secindex()
+ */
+ info->num_sections = TO_NATIVE(sechdrs[0].sh_size);
+ }
+ else {
+ info->num_sections = hdr->e_shnum;
+ }
+ if (hdr->e_shstrndx == SHN_XINDEX) {
+ info->secindex_strings =
+ shndx2secindex(TO_NATIVE(sechdrs[0].sh_link));
+ }
+ else {
+ info->secindex_strings = hdr->e_shstrndx;
+ }
+
/* Fix endianness in section headers */
- for (i = 0; i < hdr->e_shnum; i++) {
+ for (i = 0; i < info->num_sections; i++) {
sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags);
@@ -431,9 +453,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize);
}
/* Find symbol table. */
- for (i = 1; i < hdr->e_shnum; i++) {
- const char *secstrings
- = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+ secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset;
+ for (i = 1; i < info->num_sections; i++) {
const char *secname;
int nobits = sechdrs[i].sh_type == SHT_NOBITS;
@@ -461,14 +482,26 @@ static int parse_elf(struct elf_info *info, const char *filename)
else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
info->export_gpl_future_sec = i;
- if (sechdrs[i].sh_type != SHT_SYMTAB)
- continue;
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ unsigned int sh_link_idx;
+ symtab_idx = i;
+ info->symtab_start = (void *)hdr +
+ sechdrs[i].sh_offset;
+ info->symtab_stop = (void *)hdr +
+ sechdrs[i].sh_offset + sechdrs[i].sh_size;
+ sh_link_idx = shndx2secindex(sechdrs[i].sh_link);
+ info->strtab = (void *)hdr +
+ sechdrs[sh_link_idx].sh_offset;
+ }
- 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;
+ /* 32bit section no. table? ("more than 64k sections") */
+ if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) {
+ symtab_shndx_idx = i;
+ info->symtab_shndx_start = (void *)hdr +
+ sechdrs[i].sh_offset;
+ info->symtab_shndx_stop = (void *)hdr +
+ sechdrs[i].sh_offset + sechdrs[i].sh_size;
+ }
}
if (!info->symtab_start)
fatal("%s has no symtab?\n", filename);
@@ -480,6 +513,21 @@ static int parse_elf(struct elf_info *info, const char *filename)
sym->st_value = TO_NATIVE(sym->st_value);
sym->st_size = TO_NATIVE(sym->st_size);
}
+
+ if (symtab_shndx_idx != ~0U) {
+ Elf32_Word *p;
+ if (symtab_idx !=
+ shndx2secindex(sechdrs[symtab_shndx_idx].sh_link))
+ fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n",
+ filename,
+ shndx2secindex(sechdrs[symtab_shndx_idx].sh_link),
+ symtab_idx);
+ /* Fix endianness */
+ for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop;
+ p++)
+ *p = TO_NATIVE(*p);
+ }
+
return 1;
}
@@ -503,6 +551,11 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)
strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 ||
strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0)
return 1;
+ if (info->hdr->e_machine == EM_PPC64)
+ /* Special register function linked on all modules during final link of .ko */
+ if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 ||
+ strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0)
+ return 1;
/* Do not ignore this symbol */
return 0;
}
@@ -514,7 +567,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
Elf_Sym *sym, const char *symname)
{
unsigned int crc;
- enum export export = export_from_sec(info, sym->st_shndx);
+ enum export export = export_from_sec(info, get_secindex(info, sym));
switch (sym->st_shndx) {
case SHN_COMMON:
@@ -656,19 +709,19 @@ static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
return "(unknown)";
}
-static const char *sec_name(struct elf_info *elf, int shndx)
+static const char *sec_name(struct elf_info *elf, int secindex)
{
Elf_Shdr *sechdrs = elf->sechdrs;
return (void *)elf->hdr +
- elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
- sechdrs[shndx].sh_name;
+ elf->sechdrs[elf->secindex_strings].sh_offset +
+ sechdrs[secindex].sh_name;
}
static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
{
return (void *)elf->hdr +
- elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
- sechdr->sh_name;
+ elf->sechdrs[elf->secindex_strings].sh_offset +
+ sechdr->sh_name;
}
/* if sym is empty or point to a string
@@ -737,6 +790,8 @@ static const char *section_white_list[] =
{
".comment*",
".debug*",
+ ".zdebug*", /* Compressed debug sections. */
+ ".GCC-command-line", /* mn10300 */
".mdebug*", /* alpha, score, mips etc. */
".pdr", /* alpha, score, mips etc. */
".stab*",
@@ -981,6 +1036,13 @@ static const struct sectioncheck *section_mismatch(
* fromsec = .data*
* atsym =__param*
*
+ * Pattern 1a:
+ * module_param_call() ops can refer to __init set function if permissions=0
+ * The pattern is identified by:
+ * tosec = .init.text
+ * fromsec = .data*
+ * atsym = __param_ops_*
+ *
* Pattern 2:
* Many drivers utilise a *driver container with references to
* add, remove, probe functions etc.
@@ -1015,6 +1077,12 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
(strncmp(fromsym, "__param", strlen("__param")) == 0))
return 0;
+ /* Check for pattern 1a */
+ if (strcmp(tosec, ".init.text") == 0 &&
+ match(fromsec, data_sections) &&
+ (strncmp(fromsym, "__param_ops_", strlen("__param_ops_")) == 0))
+ return 0;
+
/* Check for pattern 2 */
if (match(tosec, init_exit_sections) &&
match(fromsec, data_sections) &&
@@ -1047,11 +1115,14 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
Elf_Sym *near = NULL;
Elf64_Sword distance = 20;
Elf64_Sword d;
+ unsigned int relsym_secindex;
if (relsym->st_name != 0)
return relsym;
+
+ relsym_secindex = get_secindex(elf, relsym);
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
- if (sym->st_shndx != relsym->st_shndx)
+ if (get_secindex(elf, sym) != relsym_secindex)
continue;
if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
continue;
@@ -1113,9 +1184,9 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
const char *symsec;
- if (sym->st_shndx >= SHN_LORESERVE)
+ if (is_shndx_special(sym->st_shndx))
continue;
- symsec = sec_name(elf, sym->st_shndx);
+ symsec = sec_name(elf, get_secindex(elf, sym));
if (strcmp(symsec, sec) != 0)
continue;
if (!is_valid_name(elf, sym))
@@ -1138,6 +1209,9 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
* .cpuinit.data => __cpudata
* .memexitconst => __memconst
* etc.
+ *
+ * The memory of returned value has been allocated on a heap. The user of this
+ * method should free it after usage.
*/
static char *sec2annotation(const char *s)
{
@@ -1160,9 +1234,9 @@ static char *sec2annotation(const char *s)
strcat(p, "data ");
else
strcat(p, " ");
- return r; /* we leak her but we do not care */
+ return r;
} else {
- return "";
+ return strdup("");
}
}
@@ -1190,6 +1264,8 @@ static void report_sec_mismatch(const char *modname,
{
const char *from, *from_p;
const char *to, *to_p;
+ char *prl_from;
+ char *prl_to;
switch (from_is_func) {
case 0: from = "variable"; from_p = ""; break;
@@ -1213,16 +1289,21 @@ static void report_sec_mismatch(const char *modname,
switch (mismatch->mismatch) {
case TEXT_TO_ANY_INIT:
+ prl_from = sec2annotation(fromsec);
+ prl_to = sec2annotation(tosec);
fprintf(stderr,
"The function %s%s() references\n"
"the %s %s%s%s.\n"
"This is often because %s lacks a %s\n"
"annotation or the annotation of %s is wrong.\n",
- sec2annotation(fromsec), fromsym,
- to, sec2annotation(tosec), tosym, to_p,
- fromsym, sec2annotation(tosec), tosym);
+ prl_from, fromsym,
+ to, prl_to, tosym, to_p,
+ fromsym, prl_to, tosym);
+ free(prl_from);
+ free(prl_to);
break;
case DATA_TO_ANY_INIT: {
+ prl_to = sec2annotation(tosec);
const char *const *s = mismatch->symbol_white_list;
fprintf(stderr,
"The variable %s references\n"
@@ -1230,20 +1311,24 @@ static void report_sec_mismatch(const char *modname,
"If the reference is valid then annotate the\n"
"variable with __init* or __refdata (see linux/init.h) "
"or name the variable:\n",
- fromsym, to, sec2annotation(tosec), tosym, to_p);
+ fromsym, to, prl_to, tosym, to_p);
while (*s)
fprintf(stderr, "%s, ", *s++);
fprintf(stderr, "\n");
+ free(prl_to);
break;
}
case TEXT_TO_ANY_EXIT:
+ prl_to = sec2annotation(tosec);
fprintf(stderr,
"The function %s() references a %s in an exit section.\n"
"Often the %s %s%s has valid usage outside the exit section\n"
"and the fix is to remove the %sannotation of %s.\n",
- fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym);
+ fromsym, to, to, tosym, to_p, prl_to, tosym);
+ free(prl_to);
break;
case DATA_TO_ANY_EXIT: {
+ prl_to = sec2annotation(tosec);
const char *const *s = mismatch->symbol_white_list;
fprintf(stderr,
"The variable %s references\n"
@@ -1251,24 +1336,31 @@ static void report_sec_mismatch(const char *modname,
"If the reference is valid then annotate the\n"
"variable with __exit* (see linux/init.h) or "
"name the variable:\n",
- fromsym, to, sec2annotation(tosec), tosym, to_p);
+ fromsym, to, prl_to, tosym, to_p);
while (*s)
fprintf(stderr, "%s, ", *s++);
fprintf(stderr, "\n");
+ free(prl_to);
break;
}
case XXXINIT_TO_SOME_INIT:
case XXXEXIT_TO_SOME_EXIT:
+ prl_from = sec2annotation(fromsec);
+ prl_to = sec2annotation(tosec);
fprintf(stderr,
"The %s %s%s%s references\n"
"a %s %s%s%s.\n"
"If %s is only used by %s then\n"
"annotate %s with a matching annotation.\n",
- from, sec2annotation(fromsec), fromsym, from_p,
- to, sec2annotation(tosec), tosym, to_p,
+ from, prl_from, fromsym, from_p,
+ to, prl_to, tosym, to_p,
tosym, fromsym, tosym);
+ free(prl_from);
+ free(prl_to);
break;
case ANY_INIT_TO_ANY_EXIT:
+ prl_from = sec2annotation(fromsec);
+ prl_to = sec2annotation(tosec);
fprintf(stderr,
"The %s %s%s%s references\n"
"a %s %s%s%s.\n"
@@ -1277,11 +1369,15 @@ static void report_sec_mismatch(const char *modname,
"uses functionality in the exit path.\n"
"The fix is often to remove the %sannotation of\n"
"%s%s so it may be used outside an exit section.\n",
- from, sec2annotation(fromsec), fromsym, from_p,
- to, sec2annotation(tosec), tosym, to_p,
- sec2annotation(tosec), tosym, to_p);
+ from, prl_from, fromsym, from_p,
+ to, prl_to, tosym, to_p,
+ prl_to, tosym, to_p);
+ free(prl_from);
+ free(prl_to);
break;
case ANY_EXIT_TO_ANY_INIT:
+ prl_from = sec2annotation(fromsec);
+ prl_to = sec2annotation(tosec);
fprintf(stderr,
"The %s %s%s%s references\n"
"a %s %s%s%s.\n"
@@ -1290,16 +1386,20 @@ static void report_sec_mismatch(const char *modname,
"uses functionality in the init path.\n"
"The fix is often to remove the %sannotation of\n"
"%s%s so it may be used outside an init section.\n",
- from, sec2annotation(fromsec), fromsym, from_p,
- to, sec2annotation(tosec), tosym, to_p,
- sec2annotation(tosec), tosym, to_p);
+ from, prl_from, fromsym, from_p,
+ to, prl_to, tosym, to_p,
+ prl_to, tosym, to_p);
+ free(prl_from);
+ free(prl_to);
break;
case EXPORT_TO_INIT_EXIT:
+ prl_to = sec2annotation(tosec);
fprintf(stderr,
"The symbol %s is exported and annotated %s\n"
"Fix this by removing the %sannotation of %s "
"or drop the export.\n",
- tosym, sec2annotation(tosec), sec2annotation(tosec), tosym);
+ tosym, prl_to, prl_to, tosym);
+ free(prl_to);
break;
}
fprintf(stderr, "\n");
@@ -1311,7 +1411,7 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf,
const char *tosec;
const struct sectioncheck *mismatch;
- tosec = sec_name(elf, sym->st_shndx);
+ tosec = sec_name(elf, get_secindex(elf, sym));
mismatch = section_mismatch(fromsec, tosec);
if (mismatch) {
Elf_Sym *to;
@@ -1339,10 +1439,10 @@ static unsigned int *reloc_location(struct elf_info *elf,
Elf_Shdr *sechdr, Elf_Rela *r)
{
Elf_Shdr *sechdrs = elf->sechdrs;
- int section = sechdr->sh_info;
+ int section = shndx2secindex(sechdr->sh_info);
return (void *)elf->hdr + sechdrs[section].sh_offset +
- (r->r_offset - sechdrs[section].sh_addr);
+ r->r_offset;
}
static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
@@ -1447,7 +1547,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
r.r_addend = TO_NATIVE(rela->r_addend);
sym = elf->symtab_start + r_sym;
/* Skip special sections */
- if (sym->st_shndx >= SHN_LORESERVE)
+ if (is_shndx_special(sym->st_shndx))
continue;
check_section_mismatch(modname, elf, &r, sym, fromsec);
}
@@ -1505,7 +1605,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
}
sym = elf->symtab_start + r_sym;
/* Skip special sections */
- if (sym->st_shndx >= SHN_LORESERVE)
+ if (is_shndx_special(sym->st_shndx))
continue;
check_section_mismatch(modname, elf, &r, sym, fromsec);
}
@@ -1530,7 +1630,7 @@ static void check_sec_ref(struct module *mod, const char *modname,
Elf_Shdr *sechdrs = elf->sechdrs;
/* Walk through all sections */
- for (i = 0; i < elf->hdr->e_shnum; i++) {
+ for (i = 0; i < elf->num_sections; i++) {
check_section(modname, elf, &elf->sechdrs[i]);
/* We want to process only relocation sections and not .init */
if (sechdrs[i].sh_type == SHT_RELA)
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index be987a44f250..0388cfccac8d 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -129,8 +129,51 @@ struct elf_info {
const char *strtab;
char *modinfo;
unsigned int modinfo_len;
+
+ /* support for 32bit section numbers */
+
+ unsigned int num_sections; /* max_secindex + 1 */
+ unsigned int secindex_strings;
+ /* if Nth symbol table entry has .st_shndx = SHN_XINDEX,
+ * take shndx from symtab_shndx_start[N] instead */
+ Elf32_Word *symtab_shndx_start;
+ Elf32_Word *symtab_shndx_stop;
};
+static inline int is_shndx_special(unsigned int i)
+{
+ return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
+}
+
+/* shndx is in [0..SHN_LORESERVE) U (SHN_HIRESERVE, 0xfffffff], thus:
+ * shndx == 0 <=> sechdrs[0]
+ * ......
+ * shndx == SHN_LORESERVE-1 <=> sechdrs[SHN_LORESERVE-1]
+ * shndx == SHN_HIRESERVE+1 <=> sechdrs[SHN_LORESERVE]
+ * shndx == SHN_HIRESERVE+2 <=> sechdrs[SHN_LORESERVE+1]
+ * ......
+ * fyi: sym->st_shndx is uint16, SHN_LORESERVE = ff00, SHN_HIRESERVE = ffff,
+ * so basically we map 0000..feff -> 0000..feff
+ * ff00..ffff -> (you are a bad boy, dont do it)
+ * 10000..xxxx -> ff00..(xxxx-0x100)
+ */
+static inline unsigned int shndx2secindex(unsigned int i)
+{
+ if (i <= SHN_HIRESERVE)
+ return i;
+ return i - (SHN_HIRESERVE + 1 - SHN_LORESERVE);
+}
+
+/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
+static inline unsigned int get_secindex(const struct elf_info *info,
+ const Elf_Sym *sym)
+{
+ if (sym->st_shndx != SHN_XINDEX)
+ return sym->st_shndx;
+ return shndx2secindex(info->symtab_shndx_start[sym -
+ info->symtab_start]);
+}
+
/* file2alias.c */
extern unsigned int cross_build;
void handle_moddevtable(struct module *mod, struct elf_info *info,
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
index 361d0f71184b..a71be6b7cdec 100755
--- a/scripts/namespace.pl
+++ b/scripts/namespace.pl
@@ -84,6 +84,64 @@ 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
+my %nmexception = (
+ 'fs/ext3/bitmap' => 1,
+ 'fs/ext4/bitmap' => 1,
+ 'arch/x86/lib/thunk_32' => 1,
+ 'arch/x86/lib/cmpxchg' => 1,
+ 'arch/x86/vdso/vdso32/note' => 1,
+ 'lib/irq_regs' => 1,
+ 'usr/initramfs_data' => 1,
+ 'drivers/scsi/aic94xx/aic94xx_dump' => 1,
+ 'drivers/scsi/libsas/sas_dump' => 1,
+ 'lib/dec_and_lock' => 1,
+ 'drivers/ide/ide-probe-mini' => 1,
+ 'usr/initramfs_data' => 1,
+ 'drivers/acpi/acpia/exdump' => 1,
+ 'drivers/acpi/acpia/rsdump' => 1,
+ 'drivers/acpi/acpia/nsdumpdv' => 1,
+ 'drivers/acpi/acpia/nsdump' => 1,
+ 'arch/ia64/sn/kernel/sn2/io' => 1,
+ 'arch/ia64/kernel/gate-data' => 1,
+ 'security/capability' => 1,
+ 'fs/ntfs/sysctl' => 1,
+ 'fs/jfs/jfs_debug' => 1,
+);
+
+my %nameexception = (
+ 'mod_use_count_' => 1,
+ '__initramfs_end' => 1,
+ '__initramfs_start' => 1,
+ '_einittext' => 1,
+ '_sinittext' => 1,
+ 'kallsyms_names' => 1,
+ 'kallsyms_num_syms' => 1,
+ 'kallsyms_addresses'=> 1,
+ '__this_module' => 1,
+ '_etext' => 1,
+ '_edata' => 1,
+ '_end' => 1,
+ '__bss_start' => 1,
+ '_text' => 1,
+ '_stext' => 1,
+ '__gp' => 1,
+ 'ia64_unw_start' => 1,
+ 'ia64_unw_end' => 1,
+ '__init_begin' => 1,
+ '__init_end' => 1,
+ '__bss_stop' => 1,
+ '__nosave_begin' => 1,
+ '__nosave_end' => 1,
+ 'pg0' => 1,
+ 'vdso_enabled' => 1,
+ '__stack_chk_fail' => 1,
+ 'VDSO32_PRELINK' => 1,
+ 'VDSO32_vsyscall' => 1,
+ 'VDSO32_rt_sigreturn'=>1,
+ 'VDSO32_sigreturn' => 1,
+);
+
+
&find(\&linux_objects, '.'); # find the objects and do_nm on them
&list_multiply_defined();
&resolve_external_references();
@@ -105,7 +163,8 @@ sub linux_objects
if (/.*\.o$/ &&
! (
m:/built-in.o$:
- || m:arch/x86/kernel/vsyscall-syms.o$:
+ || m:arch/x86/vdso/:
+ || m:arch/x86/boot/:
|| m:arch/ia64/ia32/ia32.o$:
|| m:arch/ia64/kernel/gate-syms.o$:
|| m:arch/ia64/lib/__divdi3.o$:
@@ -148,6 +207,7 @@ sub linux_objects
|| m:^.*/\.tmp_:
|| m:^\.tmp_:
|| m:/vmlinux-obj.o$:
+ || m:^tools/:
)
) {
do_nm($basename, $_);
@@ -167,11 +227,11 @@ sub do_nm
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";
+ ($source = $basename) =~ s/\.o$//;
+ if (-e "$source.c" || -e "$source.S") {
+ $source = "$objtree$File::Find::dir/$source";
} else {
- $source = "$srctree$source";
+ $source = "$srctree$File::Find::dir/$source";
}
if (! -e "$source.c" && ! -e "$source.S") {
# No obvious source, exclude the object if it is conglomerate
@@ -214,6 +274,7 @@ sub do_nm
# T global label/procedure
# U external reference
# W weak external reference to text that has been resolved
+ # V similar to W, but the value of the weak symbol becomes zero with no error.
# a assembler equate
# b static variable, uninitialised
# d static variable, initialised
@@ -222,8 +283,9 @@ sub do_nm
# s static variable, uninitialised, small bss
# t static label/procedures
# w weak external reference to text that has not been resolved
+ # v similar to w
# ? undefined type, used a lot by modules
- if ($type !~ /^[ABCDGRSTUWabdgrstw?]$/) {
+ if ($type !~ /^[ABCDGRSTUWVabdgrstwv?]$/) {
printf STDERR "nm output for $fullname contains unknown type '$_'\n";
}
elsif ($name =~ /\./) {
@@ -234,7 +296,7 @@ sub do_nm
# 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]/ &&
+ if ($type =~ /[ABCDGRSTWV]/ &&
$name ne 'init_module' &&
$name ne 'cleanup_module' &&
$name ne 'Using_Versions' &&
@@ -270,27 +332,9 @@ sub do_nm
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;
+ printf "No nm data for $fullname\n"
+ unless $nmexception{$fullname};
+ return;
}
$nmdata{$fullname} = \@nmdata;
}
@@ -319,18 +363,14 @@ sub list_multiply_defined
foreach my $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/x86/kernel/vsyscall-int80_32.o" &&
- $def{$name}[1] eq "arch/x86/kernel/vsyscall-sysenter_32.o") {
- &drop_def("arch/x86/kernel/vsyscall-sysenter_32.o", $name);
- next;
+ if ($#{$def{$name}} == 1 &&
+ ($name =~ /^sys_/ || $name =~ /^compat_sys_/ ||
+ $name =~ /^sys32_/)) {
+ if($def{$name}[0] eq "kernel/sys_ni.o" ||
+ $def{$name}[1] eq "kernel/sys_ni.o") {
+ &drop_def("kernel/sys_ni.o", $name);
+ next;
+ }
}
printf "$name is multiply defined in :-\n";
@@ -372,31 +412,7 @@ sub resolve_external_references
$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"
+ elsif ( ! $nameexception{$name}
&& $name !~ /^__sched_text_/
&& $name !~ /^__start_/
&& $name !~ /^__end_/
@@ -407,7 +423,6 @@ sub resolve_external_references
&& $name !~ /^__.*per_cpu_end/
&& $name !~ /^__alt_instructions/
&& $name !~ /^__setup_/
- && $name !~ /^jiffies/
&& $name !~ /^__mod_timer/
&& $name !~ /^__mod_page_state/
&& $name !~ /^init_module/
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index 62fcc3a7f4d3..d0b931b994fc 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -44,7 +44,7 @@ rpm-pkg rpm: $(objtree)/kernel.spec FORCE
fi
$(MAKE) clean
$(PREV) ln -sf $(srctree) $(KERNELPATH)
- $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion > $(objtree)/.scmversion
+ $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion --save-scmversion
$(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/.
$(PREV) rm $(KERNELPATH)
rm -f $(objtree)/.scmversion
@@ -111,13 +111,38 @@ tar%pkg: FORCE
clean-dirs += $(objtree)/tar-install/
+# perf-pkg - generate a source tarball with perf source
+# ---------------------------------------------------------------------------
+
+perf-tar=perf-$(KERNELVERSION)
+
+quiet_cmd_perf_tar = TAR
+ cmd_perf_tar = \
+git archive --prefix=$(perf-tar)/ HEAD^{tree} \
+ $$(cat $(srctree)/tools/perf/MANIFEST) -o $(perf-tar).tar; \
+mkdir -p $(perf-tar); \
+git rev-parse HEAD > $(perf-tar)/HEAD; \
+tar rf $(perf-tar).tar $(perf-tar)/HEAD; \
+rm -r $(perf-tar); \
+$(if $(findstring tar-src,$@),, \
+$(if $(findstring bz2,$@),bzip2, \
+$(if $(findstring gz,$@),gzip, \
+$(error unknown target $@))) \
+ -f -9 $(perf-tar).tar)
+
+perf-%pkg: FORCE
+ $(call cmd,perf_tar)
+
# Help text displayed when executing 'make help'
# ---------------------------------------------------------------------------
help: FORCE
- @echo ' rpm-pkg - Build both source and binary RPM kernel packages'
- @echo ' binrpm-pkg - Build only the binary kernel package'
- @echo ' deb-pkg - Build the kernel as an deb package'
- @echo ' tar-pkg - Build the kernel as an uncompressed tarball'
- @echo ' targz-pkg - Build the kernel as a gzip compressed tarball'
- @echo ' tarbz2-pkg - Build the kernel as a bzip2 compressed tarball'
+ @echo ' rpm-pkg - Build both source and binary RPM kernel packages'
+ @echo ' binrpm-pkg - Build only the binary kernel package'
+ @echo ' deb-pkg - Build the kernel as an deb package'
+ @echo ' tar-pkg - Build the kernel as an uncompressed tarball'
+ @echo ' targz-pkg - Build the kernel as a gzip compressed tarball'
+ @echo ' tarbz2-pkg - Build the kernel as a bzip2 compressed tarball'
+ @echo ' perf-tar-src-pkg - Build $(perf-tar).tar source tarball'
+ @echo ' perf-targz-src-pkg - Build $(perf-tar).tar.gz source tarball'
+ @echo ' perf-tarbz2-src-pkg - Build $(perf-tar).tar.bz2 source tarball'
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index 186344266c35..e1c1d5b8ca70 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Output a simple RPM spec file that uses no fancy features requring
+# Output a simple RPM spec file that uses no fancy features requiring
# RPM v4. This is intended to work with any RPM distro.
#
# The only gothic bit here is redefining install_post to avoid
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
new file mode 100644
index 000000000000..038b3d1e2981
--- /dev/null
+++ b/scripts/recordmcount.c
@@ -0,0 +1,410 @@
+/*
+ * recordmcount.c: construct a table of the locations of calls to 'mcount'
+ * so that ftrace can find them quickly.
+ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
+ * Licensed under the GNU General Public License, version 2 (GPLv2).
+ *
+ * Restructured to fit Linux format, as well as other updates:
+ * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ */
+
+/*
+ * Strategy: alter the .o file in-place.
+ *
+ * Append a new STRTAB that has the new section names, followed by a new array
+ * ElfXX_Shdr[] that has the new section headers, followed by the section
+ * contents for __mcount_loc and its relocations. The old shstrtab strings,
+ * and the old ElfXX_Shdr[] array, remain as "garbage" (commonly, a couple
+ * kilobytes.) Subsequent processing by /bin/ld (or the kernel module loader)
+ * will ignore the garbage regions, because they are not designated by the
+ * new .e_shoff nor the new ElfXX_Shdr[]. [In order to remove the garbage,
+ * then use "ld -r" to create a new file that omits the garbage.]
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <elf.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int fd_map; /* File descriptor for file being modified. */
+static int mmap_failed; /* Boolean flag. */
+static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
+static char gpfx; /* prefix for global symbol name (sometimes '_') */
+static struct stat sb; /* Remember .st_size, etc. */
+static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
+static const char *altmcount; /* alternate mcount symbol name */
+
+/* setjmp() return values */
+enum {
+ SJ_SETJMP = 0, /* hardwired first return */
+ SJ_FAIL,
+ SJ_SUCCEED
+};
+
+/* Per-file resource cleanup when multiple files. */
+static void
+cleanup(void)
+{
+ if (!mmap_failed)
+ munmap(ehdr_curr, sb.st_size);
+ else
+ free(ehdr_curr);
+ close(fd_map);
+}
+
+static void __attribute__((noreturn))
+fail_file(void)
+{
+ cleanup();
+ longjmp(jmpenv, SJ_FAIL);
+}
+
+static void __attribute__((noreturn))
+succeed_file(void)
+{
+ cleanup();
+ longjmp(jmpenv, SJ_SUCCEED);
+}
+
+/* ulseek, uread, ...: Check return value for errors. */
+
+static off_t
+ulseek(int const fd, off_t const offset, int const whence)
+{
+ off_t const w = lseek(fd, offset, whence);
+ if ((off_t)-1 == w) {
+ perror("lseek");
+ fail_file();
+ }
+ return w;
+}
+
+static size_t
+uread(int const fd, void *const buf, size_t const count)
+{
+ size_t const n = read(fd, buf, count);
+ if (n != count) {
+ perror("read");
+ fail_file();
+ }
+ return n;
+}
+
+static size_t
+uwrite(int const fd, void const *const buf, size_t const count)
+{
+ size_t const n = write(fd, buf, count);
+ if (n != count) {
+ perror("write");
+ fail_file();
+ }
+ return n;
+}
+
+static void *
+umalloc(size_t size)
+{
+ void *const addr = malloc(size);
+ if (0 == addr) {
+ fprintf(stderr, "malloc failed: %zu bytes\n", size);
+ fail_file();
+ }
+ return addr;
+}
+
+/*
+ * Get the whole file as a programming convenience in order to avoid
+ * malloc+lseek+read+free of many pieces. If successful, then mmap
+ * avoids copying unused pieces; else just read the whole file.
+ * Open for both read and write; new info will be appended to the file.
+ * Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
+ * do not propagate to the file until an explicit overwrite at the last.
+ * This preserves most aspects of consistency (all except .st_size)
+ * for simultaneous readers of the file while we are appending to it.
+ * However, multiple writers still are bad. We choose not to use
+ * locking because it is expensive and the use case of kernel build
+ * makes multiple writers unlikely.
+ */
+static void *mmap_file(char const *fname)
+{
+ void *addr;
+
+ fd_map = open(fname, O_RDWR);
+ if (0 > fd_map || 0 > fstat(fd_map, &sb)) {
+ perror(fname);
+ fail_file();
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ fprintf(stderr, "not a regular file: %s\n", fname);
+ fail_file();
+ }
+ addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+ fd_map, 0);
+ mmap_failed = 0;
+ if (MAP_FAILED == addr) {
+ mmap_failed = 1;
+ addr = umalloc(sb.st_size);
+ uread(fd_map, addr, sb.st_size);
+ }
+ return addr;
+}
+
+/* w8rev, w8nat, ...: Handle endianness. */
+
+static uint64_t w8rev(uint64_t const x)
+{
+ return ((0xff & (x >> (0 * 8))) << (7 * 8))
+ | ((0xff & (x >> (1 * 8))) << (6 * 8))
+ | ((0xff & (x >> (2 * 8))) << (5 * 8))
+ | ((0xff & (x >> (3 * 8))) << (4 * 8))
+ | ((0xff & (x >> (4 * 8))) << (3 * 8))
+ | ((0xff & (x >> (5 * 8))) << (2 * 8))
+ | ((0xff & (x >> (6 * 8))) << (1 * 8))
+ | ((0xff & (x >> (7 * 8))) << (0 * 8));
+}
+
+static uint32_t w4rev(uint32_t const x)
+{
+ return ((0xff & (x >> (0 * 8))) << (3 * 8))
+ | ((0xff & (x >> (1 * 8))) << (2 * 8))
+ | ((0xff & (x >> (2 * 8))) << (1 * 8))
+ | ((0xff & (x >> (3 * 8))) << (0 * 8));
+}
+
+static uint32_t w2rev(uint16_t const x)
+{
+ return ((0xff & (x >> (0 * 8))) << (1 * 8))
+ | ((0xff & (x >> (1 * 8))) << (0 * 8));
+}
+
+static uint64_t w8nat(uint64_t const x)
+{
+ return x;
+}
+
+static uint32_t w4nat(uint32_t const x)
+{
+ return x;
+}
+
+static uint32_t w2nat(uint16_t const x)
+{
+ return x;
+}
+
+static uint64_t (*w8)(uint64_t);
+static uint32_t (*w)(uint32_t);
+static uint32_t (*w2)(uint16_t);
+
+/* Names of the sections that could contain calls to mcount. */
+static int
+is_mcounted_section_name(char const *const txtname)
+{
+ return 0 == strcmp(".text", txtname) ||
+ 0 == strcmp(".sched.text", txtname) ||
+ 0 == strcmp(".spinlock.text", txtname) ||
+ 0 == strcmp(".irqentry.text", txtname) ||
+ 0 == strcmp(".text.unlikely", txtname);
+}
+
+/* 32 bit and 64 bit are very similar */
+#include "recordmcount.h"
+#define RECORD_MCOUNT_64
+#include "recordmcount.h"
+
+/* 64-bit EM_MIPS has weird ELF64_Rela.r_info.
+ * http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
+ * We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40]
+ * to imply the order of the members; the spec does not say so.
+ * typedef unsigned char Elf64_Byte;
+ * fails on MIPS64 because their <elf.h> already has it!
+ */
+
+typedef uint8_t myElf64_Byte; /* Type for a 8-bit quantity. */
+
+union mips_r_info {
+ Elf64_Xword r_info;
+ struct {
+ Elf64_Word r_sym; /* Symbol index. */
+ myElf64_Byte r_ssym; /* Special symbol. */
+ myElf64_Byte r_type3; /* Third relocation. */
+ myElf64_Byte r_type2; /* Second relocation. */
+ myElf64_Byte r_type; /* First relocation. */
+ } r_mips;
+};
+
+static uint64_t MIPS64_r_sym(Elf64_Rel const *rp)
+{
+ return w(((union mips_r_info){ .r_info = rp->r_info }).r_mips.r_sym);
+}
+
+static void MIPS64_r_info(Elf64_Rel *const rp, unsigned sym, unsigned type)
+{
+ rp->r_info = ((union mips_r_info){
+ .r_mips = { .r_sym = w(sym), .r_type = type }
+ }).r_info;
+}
+
+static void
+do_file(char const *const fname)
+{
+ Elf32_Ehdr *const ehdr = mmap_file(fname);
+ unsigned int reltype = 0;
+
+ ehdr_curr = ehdr;
+ w = w4nat;
+ w2 = w2nat;
+ w8 = w8nat;
+ switch (ehdr->e_ident[EI_DATA]) {
+ static unsigned int const endian = 1;
+ default: {
+ fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
+ ehdr->e_ident[EI_DATA], fname);
+ fail_file();
+ } break;
+ case ELFDATA2LSB: {
+ if (1 != *(unsigned char const *)&endian) {
+ /* main() is big endian, file.o is little endian. */
+ w = w4rev;
+ w2 = w2rev;
+ w8 = w8rev;
+ }
+ } break;
+ case ELFDATA2MSB: {
+ if (0 != *(unsigned char const *)&endian) {
+ /* main() is little endian, file.o is big endian. */
+ w = w4rev;
+ w2 = w2rev;
+ w8 = w8rev;
+ }
+ } break;
+ } /* end switch */
+ if (0 != memcmp(ELFMAG, ehdr->e_ident, SELFMAG)
+ || ET_REL != w2(ehdr->e_type)
+ || EV_CURRENT != ehdr->e_ident[EI_VERSION]) {
+ fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
+ fail_file();
+ }
+
+ gpfx = 0;
+ switch (w2(ehdr->e_machine)) {
+ default: {
+ fprintf(stderr, "unrecognized e_machine %d %s\n",
+ w2(ehdr->e_machine), fname);
+ fail_file();
+ } break;
+ case EM_386: reltype = R_386_32; break;
+ case EM_ARM: reltype = R_ARM_ABS32;
+ altmcount = "__gnu_mcount_nc";
+ break;
+ case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break;
+ case EM_MIPS: /* reltype: e_class */ gpfx = '_'; break;
+ case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break;
+ case EM_PPC64: reltype = R_PPC64_ADDR64; gpfx = '_'; break;
+ case EM_S390: /* reltype: e_class */ gpfx = '_'; break;
+ case EM_SH: reltype = R_SH_DIR32; break;
+ case EM_SPARCV9: reltype = R_SPARC_64; gpfx = '_'; break;
+ case EM_X86_64: reltype = R_X86_64_64; break;
+ } /* end switch */
+
+ switch (ehdr->e_ident[EI_CLASS]) {
+ default: {
+ fprintf(stderr, "unrecognized ELF class %d %s\n",
+ ehdr->e_ident[EI_CLASS], fname);
+ fail_file();
+ } break;
+ case ELFCLASS32: {
+ if (sizeof(Elf32_Ehdr) != w2(ehdr->e_ehsize)
+ || sizeof(Elf32_Shdr) != w2(ehdr->e_shentsize)) {
+ fprintf(stderr,
+ "unrecognized ET_REL file: %s\n", fname);
+ fail_file();
+ }
+ if (EM_S390 == w2(ehdr->e_machine))
+ reltype = R_390_32;
+ if (EM_MIPS == w2(ehdr->e_machine)) {
+ reltype = R_MIPS_32;
+ is_fake_mcount32 = MIPS32_is_fake_mcount;
+ }
+ do32(ehdr, fname, reltype);
+ } break;
+ case ELFCLASS64: {
+ Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
+ if (sizeof(Elf64_Ehdr) != w2(ghdr->e_ehsize)
+ || sizeof(Elf64_Shdr) != w2(ghdr->e_shentsize)) {
+ fprintf(stderr,
+ "unrecognized ET_REL file: %s\n", fname);
+ fail_file();
+ }
+ if (EM_S390 == w2(ghdr->e_machine))
+ reltype = R_390_64;
+ if (EM_MIPS == w2(ghdr->e_machine)) {
+ reltype = R_MIPS_64;
+ Elf64_r_sym = MIPS64_r_sym;
+ Elf64_r_info = MIPS64_r_info;
+ is_fake_mcount64 = MIPS64_is_fake_mcount;
+ }
+ do64(ghdr, fname, reltype);
+ } break;
+ } /* end switch */
+
+ cleanup();
+}
+
+int
+main(int argc, char const *argv[])
+{
+ const char ftrace[] = "/ftrace.o";
+ int ftrace_size = sizeof(ftrace) - 1;
+ int n_error = 0; /* gcc-4.3.0 false positive complaint */
+
+ if (argc <= 1) {
+ fprintf(stderr, "usage: recordmcount file.o...\n");
+ return 0;
+ }
+
+ /* Process each file in turn, allowing deep failure. */
+ for (--argc, ++argv; 0 < argc; --argc, ++argv) {
+ int const sjval = setjmp(jmpenv);
+ int len;
+
+ /*
+ * The file kernel/trace/ftrace.o references the mcount
+ * function but does not call it. Since ftrace.o should
+ * not be traced anyway, we just skip it.
+ */
+ len = strlen(argv[0]);
+ if (len >= ftrace_size &&
+ strcmp(argv[0] + (len - ftrace_size), ftrace) == 0)
+ continue;
+
+ switch (sjval) {
+ default: {
+ fprintf(stderr, "internal error: %s\n", argv[0]);
+ exit(1);
+ } break;
+ case SJ_SETJMP: { /* normal sequence */
+ /* Avoid problems if early cleanup() */
+ fd_map = -1;
+ ehdr_curr = NULL;
+ mmap_failed = 1;
+ do_file(argv[0]);
+ } break;
+ case SJ_FAIL: { /* error in do_file or below */
+ ++n_error;
+ } break;
+ case SJ_SUCCEED: { /* premature success */
+ /* do nothing */
+ } break;
+ } /* end switch */
+ }
+ return !!n_error;
+}
+
+
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
new file mode 100644
index 000000000000..baf187bee983
--- /dev/null
+++ b/scripts/recordmcount.h
@@ -0,0 +1,443 @@
+/*
+ * recordmcount.h
+ *
+ * This code was taken out of recordmcount.c written by
+ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
+ *
+ * The original code had the same algorithms for both 32bit
+ * and 64bit ELF files, but the code was duplicated to support
+ * the difference in structures that were used. This
+ * file creates a macro of everything that is different between
+ * the 64 and 32 bit code, such that by including this header
+ * twice we can create both sets of functions by including this
+ * header once with RECORD_MCOUNT_64 undefined, and again with
+ * it defined.
+ *
+ * This conversion to macros was done by:
+ * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ *
+ * Licensed under the GNU General Public License, version 2 (GPLv2).
+ */
+#undef append_func
+#undef is_fake_mcount
+#undef fn_is_fake_mcount
+#undef MIPS_is_fake_mcount
+#undef sift_rel_mcount
+#undef find_secsym_ndx
+#undef __has_rel_mcount
+#undef has_rel_mcount
+#undef tot_relsize
+#undef do_func
+#undef Elf_Addr
+#undef Elf_Ehdr
+#undef Elf_Shdr
+#undef Elf_Rel
+#undef Elf_Rela
+#undef Elf_Sym
+#undef ELF_R_SYM
+#undef Elf_r_sym
+#undef ELF_R_INFO
+#undef Elf_r_info
+#undef ELF_ST_BIND
+#undef fn_ELF_R_SYM
+#undef fn_ELF_R_INFO
+#undef uint_t
+#undef _w
+#undef _align
+#undef _size
+
+#ifdef RECORD_MCOUNT_64
+# define append_func append64
+# define sift_rel_mcount sift64_rel_mcount
+# define find_secsym_ndx find64_secsym_ndx
+# define __has_rel_mcount __has64_rel_mcount
+# define has_rel_mcount has64_rel_mcount
+# define tot_relsize tot64_relsize
+# define do_func do64
+# define is_fake_mcount is_fake_mcount64
+# define fn_is_fake_mcount fn_is_fake_mcount64
+# define MIPS_is_fake_mcount MIPS64_is_fake_mcount
+# define Elf_Addr Elf64_Addr
+# define Elf_Ehdr Elf64_Ehdr
+# define Elf_Shdr Elf64_Shdr
+# define Elf_Rel Elf64_Rel
+# define Elf_Rela Elf64_Rela
+# define Elf_Sym Elf64_Sym
+# define ELF_R_SYM ELF64_R_SYM
+# define Elf_r_sym Elf64_r_sym
+# define ELF_R_INFO ELF64_R_INFO
+# define Elf_r_info Elf64_r_info
+# define ELF_ST_BIND ELF64_ST_BIND
+# define fn_ELF_R_SYM fn_ELF64_R_SYM
+# define fn_ELF_R_INFO fn_ELF64_R_INFO
+# define uint_t uint64_t
+# define _w w8
+# define _align 7u
+# define _size 8
+#else
+# define append_func append32
+# define sift_rel_mcount sift32_rel_mcount
+# define find_secsym_ndx find32_secsym_ndx
+# define __has_rel_mcount __has32_rel_mcount
+# define has_rel_mcount has32_rel_mcount
+# define tot_relsize tot32_relsize
+# define do_func do32
+# define is_fake_mcount is_fake_mcount32
+# define fn_is_fake_mcount fn_is_fake_mcount32
+# define MIPS_is_fake_mcount MIPS32_is_fake_mcount
+# define Elf_Addr Elf32_Addr
+# define Elf_Ehdr Elf32_Ehdr
+# define Elf_Shdr Elf32_Shdr
+# define Elf_Rel Elf32_Rel
+# define Elf_Rela Elf32_Rela
+# define Elf_Sym Elf32_Sym
+# define ELF_R_SYM ELF32_R_SYM
+# define Elf_r_sym Elf32_r_sym
+# define ELF_R_INFO ELF32_R_INFO
+# define Elf_r_info Elf32_r_info
+# define ELF_ST_BIND ELF32_ST_BIND
+# define fn_ELF_R_SYM fn_ELF32_R_SYM
+# define fn_ELF_R_INFO fn_ELF32_R_INFO
+# define uint_t uint32_t
+# define _w w
+# define _align 3u
+# define _size 4
+#endif
+
+/* Functions and pointers that do_file() may override for specific e_machine. */
+static int fn_is_fake_mcount(Elf_Rel const *rp)
+{
+ return 0;
+}
+static int (*is_fake_mcount)(Elf_Rel const *rp) = fn_is_fake_mcount;
+
+static uint_t fn_ELF_R_SYM(Elf_Rel const *rp)
+{
+ return ELF_R_SYM(_w(rp->r_info));
+}
+static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
+
+static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
+{
+ rp->r_info = _w(ELF_R_INFO(sym, type));
+}
+static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
+
+/*
+ * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st
+ * _mcount symbol is needed for dynamic function tracer, with it, to disable
+ * tracing(ftrace_make_nop), the instruction in the position is replaced with
+ * the "b label" instruction, to enable tracing(ftrace_make_call), replace the
+ * instruction back. So, here, we set the 2nd one as fake and filter it.
+ *
+ * c: 3c030000 lui v1,0x0 <--> b label
+ * c: R_MIPS_HI16 _mcount
+ * c: R_MIPS_NONE *ABS*
+ * c: R_MIPS_NONE *ABS*
+ * 10: 64630000 daddiu v1,v1,0
+ * 10: R_MIPS_LO16 _mcount
+ * 10: R_MIPS_NONE *ABS*
+ * 10: R_MIPS_NONE *ABS*
+ * 14: 03e0082d move at,ra
+ * 18: 0060f809 jalr v1
+ * label:
+ */
+#define MIPS_FAKEMCOUNT_OFFSET 4
+
+static int MIPS_is_fake_mcount(Elf_Rel const *rp)
+{
+ static Elf_Addr old_r_offset;
+ Elf_Addr current_r_offset = _w(rp->r_offset);
+ int is_fake;
+
+ is_fake = old_r_offset &&
+ (current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET);
+ old_r_offset = current_r_offset;
+
+ return is_fake;
+}
+
+/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
+static void append_func(Elf_Ehdr *const ehdr,
+ Elf_Shdr *const shstr,
+ uint_t const *const mloc0,
+ uint_t const *const mlocp,
+ Elf_Rel const *const mrel0,
+ Elf_Rel const *const mrelp,
+ unsigned int const rel_entsize,
+ unsigned int const symsec_sh_link)
+{
+ /* Begin constructing output file */
+ Elf_Shdr mcsec;
+ char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
+ ? ".rela__mcount_loc"
+ : ".rel__mcount_loc";
+ unsigned const old_shnum = w2(ehdr->e_shnum);
+ uint_t const old_shoff = _w(ehdr->e_shoff);
+ uint_t const old_shstr_sh_size = _w(shstr->sh_size);
+ uint_t const old_shstr_sh_offset = _w(shstr->sh_offset);
+ uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size);
+ uint_t new_e_shoff;
+
+ shstr->sh_size = _w(t);
+ shstr->sh_offset = _w(sb.st_size);
+ t += sb.st_size;
+ t += (_align & -t); /* word-byte align */
+ new_e_shoff = t;
+
+ /* body for new shstrtab */
+ ulseek(fd_map, sb.st_size, SEEK_SET);
+ uwrite(fd_map, old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size);
+ uwrite(fd_map, mc_name, 1 + strlen(mc_name));
+
+ /* old(modified) Elf_Shdr table, word-byte aligned */
+ ulseek(fd_map, t, SEEK_SET);
+ t += sizeof(Elf_Shdr) * old_shnum;
+ uwrite(fd_map, old_shoff + (void *)ehdr,
+ sizeof(Elf_Shdr) * old_shnum);
+
+ /* new sections __mcount_loc and .rel__mcount_loc */
+ t += 2*sizeof(mcsec);
+ mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel")
+ + old_shstr_sh_size);
+ mcsec.sh_type = w(SHT_PROGBITS);
+ mcsec.sh_flags = _w(SHF_ALLOC);
+ mcsec.sh_addr = 0;
+ mcsec.sh_offset = _w(t);
+ mcsec.sh_size = _w((void *)mlocp - (void *)mloc0);
+ mcsec.sh_link = 0;
+ mcsec.sh_info = 0;
+ mcsec.sh_addralign = _w(_size);
+ mcsec.sh_entsize = _w(_size);
+ uwrite(fd_map, &mcsec, sizeof(mcsec));
+
+ mcsec.sh_name = w(old_shstr_sh_size);
+ mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize)
+ ? w(SHT_RELA)
+ : w(SHT_REL);
+ mcsec.sh_flags = 0;
+ mcsec.sh_addr = 0;
+ mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t);
+ mcsec.sh_size = _w((void *)mrelp - (void *)mrel0);
+ mcsec.sh_link = w(symsec_sh_link);
+ mcsec.sh_info = w(old_shnum);
+ mcsec.sh_addralign = _w(_size);
+ mcsec.sh_entsize = _w(rel_entsize);
+ uwrite(fd_map, &mcsec, sizeof(mcsec));
+
+ uwrite(fd_map, mloc0, (void *)mlocp - (void *)mloc0);
+ uwrite(fd_map, mrel0, (void *)mrelp - (void *)mrel0);
+
+ ehdr->e_shoff = _w(new_e_shoff);
+ ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum)); /* {.rel,}__mcount_loc */
+ ulseek(fd_map, 0, SEEK_SET);
+ uwrite(fd_map, ehdr, sizeof(*ehdr));
+}
+
+/*
+ * Look at the relocations in order to find the calls to mcount.
+ * Accumulate the section offsets that are found, and their relocation info,
+ * onto the end of the existing arrays.
+ */
+static uint_t *sift_rel_mcount(uint_t *mlocp,
+ unsigned const offbase,
+ Elf_Rel **const mrelpp,
+ Elf_Shdr const *const relhdr,
+ Elf_Ehdr const *const ehdr,
+ unsigned const recsym,
+ uint_t const recval,
+ unsigned const reltype)
+{
+ uint_t *const mloc0 = mlocp;
+ Elf_Rel *mrelp = *mrelpp;
+ Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+ + (void *)ehdr);
+ unsigned const symsec_sh_link = w(relhdr->sh_link);
+ Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
+ Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
+ + (void *)ehdr);
+
+ Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
+ char const *const str0 = (char const *)(_w(strsec->sh_offset)
+ + (void *)ehdr);
+
+ Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
+ + (void *)ehdr);
+ unsigned rel_entsize = _w(relhdr->sh_entsize);
+ unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
+ Elf_Rel const *relp = rel0;
+
+ unsigned mcountsym = 0;
+ unsigned t;
+
+ for (t = nrel; t; --t) {
+ if (!mcountsym) {
+ Elf_Sym const *const symp =
+ &sym0[Elf_r_sym(relp)];
+ char const *symname = &str0[w(symp->st_name)];
+ char const *mcount = '_' == gpfx ? "_mcount" : "mcount";
+
+ if ('.' == symname[0])
+ ++symname; /* ppc64 hack */
+ if (0 == strcmp(mcount, symname) ||
+ (altmcount && 0 == strcmp(altmcount, symname)))
+ mcountsym = Elf_r_sym(relp);
+ }
+
+ if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
+ uint_t const addend = _w(_w(relp->r_offset) - recval);
+
+ mrelp->r_offset = _w(offbase
+ + ((void *)mlocp - (void *)mloc0));
+ Elf_r_info(mrelp, recsym, reltype);
+ if (sizeof(Elf_Rela) == rel_entsize) {
+ ((Elf_Rela *)mrelp)->r_addend = addend;
+ *mlocp++ = 0;
+ } else
+ *mlocp++ = addend;
+
+ mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp);
+ }
+ relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
+ }
+ *mrelpp = mrelp;
+ return mlocp;
+}
+
+
+/*
+ * Find a symbol in the given section, to be used as the base for relocating
+ * the table of offsets of calls to mcount. A local or global symbol suffices,
+ * but avoid a Weak symbol because it may be overridden; the change in value
+ * would invalidate the relocations of the offsets of the calls to mcount.
+ * Often the found symbol will be the unnamed local symbol generated by
+ * GNU 'as' for the start of each section. For example:
+ * Num: Value Size Type Bind Vis Ndx Name
+ * 2: 00000000 0 SECTION LOCAL DEFAULT 1
+ */
+static unsigned find_secsym_ndx(unsigned const txtndx,
+ char const *const txtname,
+ uint_t *const recvalp,
+ Elf_Shdr const *const symhdr,
+ Elf_Ehdr const *const ehdr)
+{
+ Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset)
+ + (void *)ehdr);
+ unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize);
+ Elf_Sym const *symp;
+ unsigned t;
+
+ for (symp = sym0, t = nsym; t; --t, ++symp) {
+ unsigned int const st_bind = ELF_ST_BIND(symp->st_info);
+
+ if (txtndx == w2(symp->st_shndx)
+ /* avoid STB_WEAK */
+ && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
+ *recvalp = _w(symp->st_value);
+ return symp - sym0;
+ }
+ }
+ fprintf(stderr, "Cannot find symbol for section %d: %s.\n",
+ txtndx, txtname);
+ fail_file();
+}
+
+
+/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
+static char const *
+__has_rel_mcount(Elf_Shdr const *const relhdr, /* is SHT_REL or SHT_RELA */
+ Elf_Shdr const *const shdr0,
+ char const *const shstrtab,
+ char const *const fname)
+{
+ /* .sh_info depends on .sh_type == SHT_REL[,A] */
+ Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
+ char const *const txtname = &shstrtab[w(txthdr->sh_name)];
+
+ if (0 == strcmp("__mcount_loc", txtname)) {
+ fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
+ fname);
+ succeed_file();
+ }
+ if (SHT_PROGBITS != w(txthdr->sh_type) ||
+ !is_mcounted_section_name(txtname))
+ return NULL;
+ return txtname;
+}
+
+static char const *has_rel_mcount(Elf_Shdr const *const relhdr,
+ Elf_Shdr const *const shdr0,
+ char const *const shstrtab,
+ char const *const fname)
+{
+ if (SHT_REL != w(relhdr->sh_type) && SHT_RELA != w(relhdr->sh_type))
+ return NULL;
+ return __has_rel_mcount(relhdr, shdr0, shstrtab, fname);
+}
+
+
+static unsigned tot_relsize(Elf_Shdr const *const shdr0,
+ unsigned nhdr,
+ const char *const shstrtab,
+ const char *const fname)
+{
+ unsigned totrelsz = 0;
+ Elf_Shdr const *shdrp = shdr0;
+
+ for (; nhdr; --nhdr, ++shdrp) {
+ if (has_rel_mcount(shdrp, shdr0, shstrtab, fname))
+ totrelsz += _w(shdrp->sh_size);
+ }
+ return totrelsz;
+}
+
+
+/* Overall supervision for Elf32 ET_REL file. */
+static void
+do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
+{
+ Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+ + (void *)ehdr);
+ unsigned const nhdr = w2(ehdr->e_shnum);
+ Elf_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)];
+ char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
+ + (void *)ehdr);
+
+ Elf_Shdr const *relhdr;
+ unsigned k;
+
+ /* Upper bound on space: assume all relevant relocs are for mcount. */
+ unsigned const totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
+ Elf_Rel *const mrel0 = umalloc(totrelsz);
+ Elf_Rel * mrelp = mrel0;
+
+ /* 2*sizeof(address) <= sizeof(Elf_Rel) */
+ uint_t *const mloc0 = umalloc(totrelsz>>1);
+ uint_t * mlocp = mloc0;
+
+ unsigned rel_entsize = 0;
+ unsigned symsec_sh_link = 0;
+
+ for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
+ char const *const txtname = has_rel_mcount(relhdr, shdr0,
+ shstrtab, fname);
+ if (txtname) {
+ uint_t recval = 0;
+ unsigned const recsym = find_secsym_ndx(
+ w(relhdr->sh_info), txtname, &recval,
+ &shdr0[symsec_sh_link = w(relhdr->sh_link)],
+ ehdr);
+
+ rel_entsize = _w(relhdr->sh_entsize);
+ mlocp = sift_rel_mcount(mlocp,
+ (void *)mlocp - (void *)mloc0, &mrelp,
+ relhdr, ehdr, recsym, recval, reltype);
+ }
+ }
+ if (mloc0 != mlocp) {
+ append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
+ rel_entsize, symsec_sh_link);
+ }
+ free(mrel0);
+ free(mloc0);
+}
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index ea6f6e3adaea..1d7963f4ee79 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -136,13 +136,14 @@ my %text_sections = (
".text.unlikely" => 1,
);
-$objdump = "objdump" if ((length $objdump) == 0);
-$objcopy = "objcopy" if ((length $objcopy) == 0);
-$cc = "gcc" if ((length $cc) == 0);
-$ld = "ld" if ((length $ld) == 0);
-$nm = "nm" if ((length $nm) == 0);
-$rm = "rm" if ((length $rm) == 0);
-$mv = "mv" if ((length $mv) == 0);
+# Note: we are nice to C-programmers here, thus we skip the '||='-idiom.
+$objdump = 'objdump' if (!$objdump);
+$objcopy = 'objcopy' if (!$objcopy);
+$cc = 'gcc' if (!$cc);
+$ld = 'ld' if (!$ld);
+$nm = 'nm' if (!$nm);
+$rm = 'rm' if (!$rm);
+$mv = 'mv' if (!$mv);
#print STDERR "running: $P '$arch' '$objdump' '$objcopy' '$cc' '$ld' " .
# "'$nm' '$rm' '$mv' '$inputfile'\n";
@@ -158,6 +159,7 @@ my $section_regex; # Find the start of a section
my $function_regex; # Find the name of a function
# (return offset and func name)
my $mcount_regex; # Find the call site to mcount (return offset)
+my $mcount_adjust; # Address adjustment to mcount offset
my $alignment; # The .align value to use for $mcount_section
my $section_type; # Section header plus possible alignment command
my $can_use_local = 0; # If we can use local function references
@@ -212,6 +214,7 @@ $section_regex = "Disassembly of section\\s+(\\S+):";
$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";
$section_type = '@progbits';
+$mcount_adjust = 0;
$type = ".long";
if ($arch eq "x86_64") {
@@ -267,6 +270,8 @@ if ($arch eq "x86_64") {
} elsif ($arch eq "arm") {
$alignment = 2;
$section_type = '%progbits';
+ $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
+ "\\s+(__gnu_mcount_nc|mcount)\$";
} elsif ($arch eq "ia64") {
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
@@ -325,7 +330,7 @@ if ($arch eq "x86_64") {
# 14: R_MIPS_NONE *ABS*
# 18: 00020021 nop
if ($is_module eq "0") {
- $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
+ $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_26\\s+_mcount\$";
} else {
$mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$";
}
@@ -350,6 +355,9 @@ if ($arch eq "x86_64") {
} elsif ($arch eq "microblaze") {
# Microblaze calls '_mcount' instead of plain 'mcount'.
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
+} elsif ($arch eq "blackfin") {
+ $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
+ $mcount_adjust = -4;
} else {
die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
}
@@ -432,14 +440,14 @@ sub update_funcs
# Loop through all the mcount caller offsets and print a reference
# to the caller based from the ref_func.
- for (my $i=0; $i <= $#offsets; $i++) {
- if (!$opened) {
- open(FILE, ">$mcount_s") || die "can't create $mcount_s\n";
- $opened = 1;
- print FILE "\t.section $mcount_section,\"a\",$section_type\n";
- print FILE "\t.align $alignment\n" if (defined($alignment));
- }
- printf FILE "\t%s %s + %d\n", $type, $ref_func, $offsets[$i] - $offset;
+ if (!$opened) {
+ open(FILE, ">$mcount_s") || die "can't create $mcount_s\n";
+ $opened = 1;
+ print FILE "\t.section $mcount_section,\"a\",$section_type\n";
+ print FILE "\t.align $alignment\n" if (defined($alignment));
+ }
+ foreach my $cur_offset (@offsets) {
+ printf FILE "\t%s %s + %d\n", $type, $ref_func, $cur_offset - $offset;
}
}
@@ -476,11 +484,7 @@ while (<IN>) {
$read_headers = 0;
# Only record text sections that we know are safe
- if (defined($text_sections{$1})) {
- $read_function = 1;
- } else {
- $read_function = 0;
- }
+ $read_function = defined($text_sections{$1});
# print out any recorded offsets
update_funcs();
@@ -514,7 +518,7 @@ while (<IN>) {
}
# is this a call site to mcount? If so, record it to print later
if ($text_found && /$mcount_regex/) {
- $offsets[$#offsets + 1] = hex $1;
+ push(@offsets, (hex $1) + $mcount_adjust);
}
}
diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c
index 24626968055d..58a12c278706 100644
--- a/scripts/selinux/genheaders/genheaders.c
+++ b/scripts/selinux/genheaders/genheaders.c
@@ -81,7 +81,7 @@ int main(int argc, char *argv[])
fprintf(fout, "\n");
for (i = 1; i < isids_len; i++) {
- char *s = initial_sid_to_string[i];
+ const char *s = initial_sid_to_string[i];
fprintf(fout, "#define SECINITSID_%s", s);
for (j = 0; j < max(1, 40 - strlen(s)); j++)
fprintf(fout, " ");
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 46989b88d734..ef8729f48586 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -10,73 +10,164 @@
#
usage() {
- echo "Usage: $0 [srctree]" >&2
+ echo "Usage: $0 [--save-scmversion] [srctree]" >&2
exit 1
}
-cd "${1:-.}" || usage
+scm_only=false
+srctree=.
+if test "$1" = "--save-scmversion"; then
+ scm_only=true
+ shift
+fi
+if test $# -gt 0; then
+ srctree=$1
+ shift
+fi
+if test $# -gt 0 -o ! -d "$srctree"; then
+ usage
+fi
-# Check for git and a git repo.
-if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
+scm_version()
+{
+ local short
+ short=false
- # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore it,
- # because this version is defined in the top level Makefile.
- if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+ cd "$srctree"
+ if test -e .scmversion; then
+ cat .scmversion
+ return
+ fi
+ if test "$1" = "--short"; then
+ short=true
+ fi
- # If we are past a tagged commit (like "v2.6.30-rc5-302-g72357d5"),
- # we pretty print it.
- if atag="`git describe 2>/dev/null`"; then
- echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+ # Check for git and a git repo.
+ if test -d .git && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
+
+ # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
+ # it, because this version is defined in the top level Makefile.
+ if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+
+ # If only the short version is requested, don't bother
+ # running further git commands
+ if $short; then
+ echo "+"
+ return
+ fi
+ # If we are past a tagged commit (like
+ # "v2.6.30-rc5-302-g72357d5"), we pretty print it.
+ if atag="`git describe 2>/dev/null`"; then
+ echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+
+ # If we don't have a tag at all we print -g{commitish}.
+ else
+ printf '%s%s' -g $head
+ fi
+ fi
- # If we don't have a tag at all we print -g{commitish}.
- else
- printf '%s%s' -g $head
+ # Is this git on svn?
+ if git config --get svn-remote.svn.url >/dev/null; then
+ printf -- '-svn%s' "`git svn find-rev $head`"
fi
- fi
- # Is this git on svn?
- if git config --get svn-remote.svn.url >/dev/null; then
- printf -- '-svn%s' "`git svn find-rev $head`"
- fi
+ # Update index only on r/w media
+ [ -w . ] && git update-index --refresh --unmerged > /dev/null
- # Update index only on r/w media
- [ -w . ] && git update-index --refresh --unmerged > /dev/null
+ # Check for uncommitted changes
+ if git diff-index --name-only HEAD | grep -v "^scripts/package" \
+ | read dummy; then
+ printf '%s' -dirty
+ fi
- # Check for uncommitted changes
- if git diff-index --name-only HEAD | grep -v "^scripts/package" \
- | read dummy; then
- printf '%s' -dirty
+ # All done with git
+ return
fi
- # All done with git
- exit
-fi
+ # Check for mercurial and a mercurial repo.
+ if test -d .hg && hgid=`hg id 2>/dev/null`; then
+ tag=`printf '%s' "$hgid" | cut -s -d' ' -f2`
-# Check for mercurial and a mercurial repo.
-if hgid=`hg id 2>/dev/null`; then
- tag=`printf '%s' "$hgid" | cut -d' ' -f2`
+ # Do we have an untagged version?
+ if [ -z "$tag" -o "$tag" = tip ]; then
+ id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
+ printf '%s%s' -hg "$id"
+ fi
+
+ # Are there uncommitted changes?
+ # These are represented by + after the changeset id.
+ case "$hgid" in
+ *+|*+\ *) printf '%s' -dirty ;;
+ esac
- # Do we have an untagged version?
- if [ -z "$tag" -o "$tag" = tip ]; then
- id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
- printf '%s%s' -hg "$id"
+ # All done with mercurial
+ return
fi
- # Are there uncommitted changes?
- # These are represented by + after the changeset id.
- case "$hgid" in
- *+|*+\ *) printf '%s' -dirty ;;
- esac
+ # Check for svn and a svn repo.
+ if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
+ rev=`echo $rev | awk '{print $NF}'`
+ printf -- '-svn%s' "$rev"
- # All done with mercurial
+ # All done with svn
+ return
+ fi
+}
+
+collect_files()
+{
+ local file res
+
+ for file; do
+ case "$file" in
+ *\~*)
+ continue
+ ;;
+ esac
+ if test -e "$file"; then
+ res="$res$(cat "$file")"
+ fi
+ done
+ echo "$res"
+}
+
+if $scm_only; then
+ if test ! -e .scmversion; then
+ res=$(scm_version)
+ echo "$res" >.scmversion
+ fi
exit
fi
-# Check for svn and a svn repo.
-if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
- rev=`echo $rev | awk '{print $NF}'`
- printf -- '-svn%s' "$rev"
+if test -e include/config/auto.conf; then
+ . include/config/auto.conf
+else
+ echo "Error: kernelrelease not valid - run 'make prepare' to update it"
+ exit 1
+fi
- # All done with svn
- exit
+# localversion* files in the build and source directory
+res="$(collect_files localversion*)"
+if test ! "$srctree" -ef .; then
+ res="$res$(collect_files "$srctree"/localversion*)"
+fi
+
+# CONFIG_LOCALVERSION and LOCALVERSION (if set)
+res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"
+
+# scm version string if not at a tagged commit
+if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then
+ # full scm version string
+ res="$res$(scm_version)"
+else
+ # append a plus sign if the repository is not in a clean
+ # annotated or signed tagged state (as git describe only
+ # looks at signed or annotated tags - git tag -a/-s) and
+ # LOCALVERSION= is not specified
+ if test "${LOCALVERSION+set}" != "set"; then
+ scm=$(scm_version --short)
+ res="$res${scm:++}"
+ fi
fi
+
+echo "$res"
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 8509bb512935..bbbe584d4494 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -125,7 +125,9 @@ exuberant()
-I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \
--extra=+f --c-kinds=-px \
--regex-asm='/^ENTRY\(([^)]*)\).*/\1/' \
- --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/'
+ --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \
+ --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \
+ --regex-c++='/^DEFINE_EVENT\(([^,)]*).*/trace_\1/'
all_kconfigs | xargs $1 -a \
--langdef=kconfig --language-force=kconfig \