From 9d5db8949f1ecf4019785b04d8986835d3c0e99e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 6 Jun 2014 10:43:55 +0900 Subject: scripts/Makefile.clean: clean also $(extra-m) and $(extra-) Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- scripts/Makefile.clean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index 686cb0d31c7c..a651cee84f2a 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -40,8 +40,8 @@ subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn)) # build a list of files to remove, usually relative to the current # directory -__clean-files := $(extra-y) $(always) \ - $(targets) $(clean-files) \ +__clean-files := $(extra-y) $(extra-m) $(extra-) \ + $(always) $(targets) $(clean-files) \ $(host-progs) \ $(hostprogs-y) $(hostprogs-m) $(hostprogs-) -- cgit v1.2.3 From d8d9efe22709b62eb29fa9f4eb61fd882fc2b2c4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 16 Jul 2014 16:12:19 +0900 Subject: kbuild: fix a typo in scripts/Makefile.host Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- scripts/Makefile.host | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.host b/scripts/Makefile.host index 66893643fd7d..395a2403593f 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host @@ -44,7 +44,7 @@ host-cmulti := $(foreach m,$(__hostprogs),\ host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs))) # C++ code -# C++ executables compiled from at least on .cc file +# C++ executables compiled from at least one .cc file # and zero or more .c files host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) -- cgit v1.2.3 From edb950c17de09ed04be1ed2c451ba207e3b0a29b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 16 Jul 2014 16:12:20 +0900 Subject: kbuild: fix a bug of C++ host program handling The comment claims: C++ executables compiled from at least one .cc file and zero or more .c files But C++ executables with zero .c file fail in build. For example, assume we have a Makefile like this: hostprogs-y := foo foo-cxxobjs := bar.o In this case, foo is treated as host-csingle and Kbuild tries to search non-existing foo.c source. Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- scripts/Makefile.host | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.host b/scripts/Makefile.host index 395a2403593f..bf44e7988bf4 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host @@ -34,7 +34,8 @@ __hostprogs := $(sort $(hostprogs-y) $(hostprogs-m)) # C code # Executables compiled from a single .c file -host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m))) +host-csingle := $(foreach m,$(__hostprogs), \ + $(if $($(m)-objs)$($(m)-cxxobjs),,$(m))) # C executables linked based on several .o files host-cmulti := $(foreach m,$(__hostprogs),\ -- cgit v1.2.3 From 62e2210798ed38928ab24841e8b4878a2c170af8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 16 Jul 2014 16:12:21 +0900 Subject: kbuild: drop shared library support from Makefile.host The shared library feature in Makefile.host is no longer used. Rip it off to keep the build infrastucture simple. Update Documentation/kbuild/makefiles.txt too. The section "4.3 Definition shared libraries" should be removed and the following sections should be re-numbered. Signed-off-by: Masahiro Yamada Suggested-by: Sam Ravnborg Signed-off-by: Michal Marek --- scripts/Makefile.host | 43 +++---------------------------------------- 1 file changed, 3 insertions(+), 40 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.host b/scripts/Makefile.host index bf44e7988bf4..1c2e57000f5a 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host @@ -20,16 +20,6 @@ # Will compile qconf as a C++ program, and menu as a C program. # They are linked as C++ code to the executable qconf -# hostprogs-y := conf -# conf-objs := conf.o libkconfig.so -# libkconfig-objs := expr.o type.o -# Will create a shared library named libkconfig.so that consists of -# expr.o and type.o (they are both compiled as C code and the object files -# are made as position independent code). -# conf.c is compiled as a C program, and conf.o is linked together with -# libkconfig.so as the executable conf. -# Note: Shared libraries consisting of C++ files are not supported - __hostprogs := $(sort $(hostprogs-y) $(hostprogs-m)) # C code @@ -52,15 +42,6 @@ host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) # C++ Object (.o) files compiled from .cc files host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) -# Shared libaries (only .c supported) -# Shared libraries (.so) - all .so files referenced in "xxx-objs" -host-cshlib := $(sort $(filter %.so, $(host-cobjs))) -# Remove .so files from "xxx-objs" -host-cobjs := $(filter-out %.so,$(host-cobjs)) - -#Object (.o) files used by the shared libaries -host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs)))) - # output directory for programs/.o files # hostprogs-y := tools/build may have been specified. Retrieve directory host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) @@ -82,8 +63,6 @@ host-cmulti := $(addprefix $(obj)/,$(host-cmulti)) host-cobjs := $(addprefix $(obj)/,$(host-cobjs)) host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti)) host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs)) -host-cshlib := $(addprefix $(obj)/,$(host-cshlib)) -host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs)) host-objdirs := $(addprefix $(obj)/,$(host-objdirs)) obj-dirs += $(host-objdirs) @@ -124,7 +103,7 @@ quiet_cmd_host-cmulti = HOSTLD $@ cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \ $(addprefix $(obj)/,$($(@F)-objs)) \ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) -$(host-cmulti): $(obj)/%: $(host-cobjs) $(host-cshlib) FORCE +$(host-cmulti): $(obj)/%: $(host-cobjs) FORCE $(call if_changed,host-cmulti) # Create .o file from a single .c file @@ -141,7 +120,7 @@ quiet_cmd_host-cxxmulti = HOSTLD $@ $(foreach o,objs cxxobjs,\ $(addprefix $(obj)/,$($(@F)-$(o)))) \ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) -$(host-cxxmulti): $(obj)/%: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE +$(host-cxxmulti): $(obj)/%: $(host-cobjs) $(host-cxxobjs) FORCE $(call if_changed,host-cxxmulti) # Create .o file from a single .cc (C++) file @@ -150,21 +129,5 @@ quiet_cmd_host-cxxobjs = HOSTCXX $@ $(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE $(call if_changed_dep,host-cxxobjs) -# Compile .c file, create position independent .o file -# host-cshobjs -> .o -quiet_cmd_host-cshobjs = HOSTCC -fPIC $@ - cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $< -$(host-cshobjs): $(obj)/%.o: $(src)/%.c FORCE - $(call if_changed_dep,host-cshobjs) - -# Link a shared library, based on position independent .o files -# *.o -> .so shared library (host-cshlib) -quiet_cmd_host-cshlib = HOSTLLD -shared $@ - cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \ - $(addprefix $(obj)/,$($(@F:.so=-objs))) \ - $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) -$(host-cshlib): $(obj)/%: $(host-cshobjs) FORCE - $(call if_changed,host-cshlib) - targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\ - $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) + $(host-cxxmulti) $(host-cxxobjs) -- cgit v1.2.3 From 663935593915ad8dc43d10f58ef5eeefc77ef8c4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 16 Jul 2014 16:12:22 +0900 Subject: kbuild: clean up scripts/Makefile.host The directory creation can be more simplified by two levels. [1] Drop $(dir ...) $(dir $(f)) always returns non-empty string. So, $(if $(dir $(f)),$(dir $(f)) is equivalent to $(dir $(f)). [2] Unroll $(foreach ...) loop $(dir ...) can take one or more arguments and returns a list of directories of them. $(foreach f, $(progs), $(dir $(f))) can be unrolled as $(dir $(progs)). Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- scripts/Makefile.host | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.host b/scripts/Makefile.host index 1c2e57000f5a..bb6a11f4f193 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host @@ -44,15 +44,11 @@ host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) # output directory for programs/.o files # hostprogs-y := tools/build may have been specified. Retrieve directory -host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) +host-objdirs := $(dir $(__hostprogs)) # directory of .o files from prog-objs notation -host-objdirs += $(foreach f,$(host-cmulti), \ - $(foreach m,$($(f)-objs), \ - $(if $(dir $(m)),$(dir $(m))))) +host-objdirs += $(dir $(foreach f,$(host-cmulti), $($(f)-objs))) # directory of .o files from prog-cxxobjs notation -host-objdirs += $(foreach f,$(host-cxxmulti), \ - $(foreach m,$($(f)-cxxobjs), \ - $(if $(dir $(m)),$(dir $(m))))) +host-objdirs += $(dir $(foreach f,$(host-cxxmulti), $($(f)-cxxobjs))) host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs)))) -- cgit v1.2.3 From 1791ff7179f689cb54182a1215686f8138850412 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 16 Jul 2014 16:12:23 +0900 Subject: kbuild: clean-up and bug fix of scripts/Makefile.host Assume we have a Makefile like this: hostprogs-y := foo foo-cxxobjs := bar/baz.o foo-objs := qux/quux.o In this case, Kbuild creates bar/ directory, but fails to create qux/ directory. This commit re-writes directory creation more simply, fixing that bug. Signed-off-by: Masahiro Yamada Signed-off-by: Michal Marek --- scripts/Makefile.host | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.host b/scripts/Makefile.host index bb6a11f4f193..ab5980f91714 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host @@ -43,12 +43,9 @@ host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) # output directory for programs/.o files -# hostprogs-y := tools/build may have been specified. Retrieve directory -host-objdirs := $(dir $(__hostprogs)) -# directory of .o files from prog-objs notation -host-objdirs += $(dir $(foreach f,$(host-cmulti), $($(f)-objs))) -# directory of .o files from prog-cxxobjs notation -host-objdirs += $(dir $(foreach f,$(host-cxxmulti), $($(f)-cxxobjs))) +# hostprogs-y := tools/build may have been specified. +# Retrieve also directory of .o files from prog-objs or prog-cxxobjs notation +host-objdirs := $(dir $(__hostprogs) $(host-cobjs) $(host-cxxobjs)) host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs)))) -- cgit v1.2.3 From fcd38ed0ff263156c3917c70c2fb0b7e91bfeab1 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 27 Jul 2014 07:27:01 +0930 Subject: scripts: modpost: fix compilation warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scripts/mod/modpost.c triggers the following warning: scripts/mod/modpost.c: In function ‘remove_dot’: scripts/mod/modpost.c:1710:10: warning: ignoring return value of ‘strtoul’, declared with attribute warn_unused_result [-Wunused-result] The remove_dot function that calls strtoul does not care about the numeric value of the string that is parsed but only looks for the end of the numeric sequence. As such, it's equivalent to just skip over all digits. Signed-off-by: Michal Nazarewicz Signed-off-by: Rusty Russell --- scripts/mod/modpost.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 9d9c5b905b35..5ba203b9eddf 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1703,12 +1703,11 @@ static void check_sec_ref(struct module *mod, const char *modname, static char *remove_dot(char *s) { - char *end; - int n = strcspn(s, "."); + size_t n = strcspn(s, "."); - if (n > 0 && s[n] != 0) { - strtoul(s + n + 1, &end, 10); - if (end > s + n + 1 && (*end == '.' || *end == 0)) + if (n && s[n]) { + size_t m = strspn(s + n + 1, "0123456789"); + if (m && (s[n + m] == '.' || s[n + m] == 0)) s[n] = 0; } return s; -- cgit v1.2.3 From a0d8f8037468a3b5f964417f71853ccf301b9f39 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Sun, 27 Jul 2014 07:28:01 +0930 Subject: scripts: modpost: Remove numeric suffix pattern matching For several years, the pattern "foo$" has effectively been treated as equivalent to "foo" due to a bug in the (misnamed) helper number_prefix(). This hasn't been observed to cause any problems, so remove the broken $ functionality and change all foo$ patterns to foo. Signed-off-by: Rasmus Villemoes Signed-off-by: Rusty Russell --- scripts/mod/modpost.c | 49 ++++++++++--------------------------------------- 1 file changed, 10 insertions(+), 39 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 5ba203b9eddf..091d90573b63 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -772,32 +772,10 @@ static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr) sechdr->sh_name; } -/* if sym is empty or point to a string - * like ".[0-9]+" then return 1. - * This is the optional prefix added by ld to some sections - */ -static int number_prefix(const char *sym) -{ - if (*sym++ == '\0') - return 1; - if (*sym != '.') - return 0; - do { - char c = *sym++; - if (c < '0' || c > '9') - return 0; - } while (*sym); - return 1; -} - /* The pattern is an array of simple patterns. * "foo" will match an exact string equal to "foo" * "*foo" will match a string that ends with "foo" * "foo*" will match a string that begins with "foo" - * "foo$" will match a string equal to "foo" or "foo.1" - * where the '1' can be any number including several digits. - * The $ syntax is for sections where ld append a dot number - * to make section name unique. */ static int match(const char *sym, const char * const pat[]) { @@ -816,13 +794,6 @@ static int match(const char *sym, const char * const pat[]) if (strncmp(sym, p, strlen(p) - 1) == 0) return 1; } - /* "foo$" */ - else if (*endp == '$') { - if (strncmp(sym, p, strlen(p) - 1) == 0) { - if (number_prefix(sym + strlen(p) - 1)) - return 1; - } - } /* no wildcards */ else { if (strcmp(p, sym) == 0) @@ -880,20 +851,20 @@ static void check_section(const char *modname, struct elf_info *elf, #define ALL_INIT_DATA_SECTIONS \ - ".init.setup$", ".init.rodata$", ".meminit.rodata$", \ - ".init.data$", ".meminit.data$" + ".init.setup", ".init.rodata", ".meminit.rodata", \ + ".init.data", ".meminit.data" #define ALL_EXIT_DATA_SECTIONS \ - ".exit.data$", ".memexit.data$" + ".exit.data", ".memexit.data" #define ALL_INIT_TEXT_SECTIONS \ - ".init.text$", ".meminit.text$" + ".init.text", ".meminit.text" #define ALL_EXIT_TEXT_SECTIONS \ - ".exit.text$", ".memexit.text$" + ".exit.text", ".memexit.text" #define ALL_PCI_INIT_SECTIONS \ - ".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \ - ".pci_fixup_enable$", ".pci_fixup_resume$", \ - ".pci_fixup_resume_early$", ".pci_fixup_suspend$" + ".pci_fixup_early", ".pci_fixup_header", ".pci_fixup_final", \ + ".pci_fixup_enable", ".pci_fixup_resume", \ + ".pci_fixup_resume_early", ".pci_fixup_suspend" #define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS #define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS @@ -901,8 +872,8 @@ static void check_section(const char *modname, struct elf_info *elf, #define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS -#define DATA_SECTIONS ".data$", ".data.rel$" -#define TEXT_SECTIONS ".text$", ".text.unlikely$" +#define DATA_SECTIONS ".data", ".data.rel" +#define TEXT_SECTIONS ".text", ".text.unlikely" #define INIT_SECTIONS ".init.*" #define MEM_INIT_SECTIONS ".meminit.*" -- cgit v1.2.3 From 26ea6bb1fef06c686be771903ecab0518af5c2de Mon Sep 17 00:00:00 2001 From: Behan Webster Date: Thu, 31 Jul 2014 21:08:25 -0700 Subject: kbuild, LLVMLinux: Supress warnings unless W=1-3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clang has more warnings enabled by default. Turn them off unless W is set. This patch fixes a logic bug where warnings in clang were disabled when W was set. Signed-off-by: Behan Webster Signed-off-by: Jan-Simon Möller Signed-off-by: Mark Charlebois Cc: bp@alien8.de Signed-off-by: Michal Marek --- scripts/Makefile.extrawarn | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index 65643506c71c..f734033af219 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -26,16 +26,6 @@ warning-1 += $(call cc-option, -Wmissing-include-dirs) warning-1 += $(call cc-option, -Wunused-but-set-variable) warning-1 += $(call cc-disable-warning, missing-field-initializers) -# Clang -warning-1 += $(call cc-disable-warning, initializer-overrides) -warning-1 += $(call cc-disable-warning, unused-value) -warning-1 += $(call cc-disable-warning, format) -warning-1 += $(call cc-disable-warning, unknown-warning-option) -warning-1 += $(call cc-disable-warning, sign-compare) -warning-1 += $(call cc-disable-warning, format-zero-length) -warning-1 += $(call cc-disable-warning, uninitialized) -warning-1 += $(call cc-option, -fcatch-undefined-behavior) - warning-2 := -Waggregate-return warning-2 += -Wcast-align warning-2 += -Wdisabled-optimization @@ -64,4 +54,15 @@ ifeq ("$(strip $(warning))","") endif KBUILD_CFLAGS += $(warning) +else + +ifeq ($(COMPILER),clang) +KBUILD_CFLAGS += $(call cc-disable-warning, initializer-overrides) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-value) +KBUILD_CFLAGS += $(call cc-disable-warning, format) +KBUILD_CFLAGS += $(call cc-disable-warning, unknown-warning-option) +KBUILD_CFLAGS += $(call cc-disable-warning, sign-compare) +KBUILD_CFLAGS += $(call cc-disable-warning, format-zero-length) +KBUILD_CFLAGS += $(call cc-disable-warning, uninitialized) +endif endif -- cgit v1.2.3 From b5889ab7d4e6ff194ff1ef8ad2eb9266a23e376b Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Wed, 28 May 2014 19:40:47 +0530 Subject: coccinelle/null: solve parse error This patch solves the parse-error by adding @@ . This is necessary since Coccinelle version 1.0.0-rc20. Also, the comment is added to use a recent version of Coccinelle. Signed-off-by: Himangi Saraogi Acked-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/null/badzero.cocci | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/coccinelle/null/badzero.cocci b/scripts/coccinelle/null/badzero.cocci index d79baf7220e7..5551da2b4fe3 100644 --- a/scripts/coccinelle/null/badzero.cocci +++ b/scripts/coccinelle/null/badzero.cocci @@ -10,7 +10,7 @@ // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ -// Comments: +// Comments: Requires Coccinelle version 1.0.0-rc20 or later // Options: virtual patch @@ -19,6 +19,7 @@ virtual org virtual report @initialize:ocaml@ +@@ let negtable = Hashtbl.create 101 @depends on patch@ -- cgit v1.2.3 From 99fcec30e882ec214b689889b3599cf98f5c9843 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sat, 14 Jun 2014 21:15:41 +0530 Subject: Coccinelle: Script to detect cast after memory allocation This script detects cases of use of cast for the value returned by kmalloc, kzalloc, kcalloc, kmem_cache_alloc, kmem_cache_zalloc, kmem_cache_alloc_node, kmalloc_node and kzalloc_node and removes the cast as it is not useful. This Coccinelle script replaces drop_kmalloc_cast.cocci as it removes the casting in more limited cases of kmalloc, kzalloc and kcalloc. Signed-off-by: Himangi Saraogi Acked-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/api/alloc/alloc_cast.cocci | 72 ++++++++++++++++++++++ .../coccinelle/api/alloc/drop_kmalloc_cast.cocci | 67 -------------------- 2 files changed, 72 insertions(+), 67 deletions(-) create mode 100644 scripts/coccinelle/api/alloc/alloc_cast.cocci delete mode 100644 scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/api/alloc/alloc_cast.cocci b/scripts/coccinelle/api/alloc/alloc_cast.cocci new file mode 100644 index 000000000000..6c308ee19b32 --- /dev/null +++ b/scripts/coccinelle/api/alloc/alloc_cast.cocci @@ -0,0 +1,72 @@ +/// Remove casting the values returned by memory allocation functions +/// like kmalloc, kzalloc, kmem_cache_alloc, kmem_cache_zalloc etc. +/// +//# This makes an effort to find cases of casting of values returned by +//# kmalloc, kzalloc, kcalloc, kmem_cache_alloc, kmem_cache_zalloc, +//# kmem_cache_alloc_node, kmalloc_node and kzalloc_node and removes +//# the casting as it is not required. The result in the patch case may +//#need some reformatting. +// +// Confidence: High +// Copyright: 2014, Himangi Saraogi GPLv2. +// Comments: +// Options: --no-includes --include-headers +// + +virtual context +virtual patch +virtual org +virtual report + +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- + +@depends on context@ +type T; +@@ + +* (T *) + \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| + kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...) + +//---------------------------------------------------------- +// For patch mode +//---------------------------------------------------------- + +@depends on patch@ +type T; +@@ + +- (T *) + (\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| + kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...)) + +//---------------------------------------------------------- +// For org and report mode +//---------------------------------------------------------- + +@r depends on org || report@ +type T; +position p; +@@ + + (T@p *)\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| + kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...) + +@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 memory allocation function to (%s *) is useless." % (t) +coccilib.report.print_report(p[0], msg) + + diff --git a/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci b/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci deleted file mode 100644 index bd5d08b882ee..000000000000 --- a/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci +++ /dev/null @@ -1,67 +0,0 @@ -/// -/// 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) -- cgit v1.2.3 From 7ab04ea0e32cf8cabcbc33cefac36e5f9258734e Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sun, 29 Jun 2014 12:46:04 +0530 Subject: Coccinelle: Script to use ARRAY_SIZE instead of division of two sizeofs This script detects cases where ARRAY_SIZE can be used such as where there is a division of sizeof the array by the sizeof its first element or by any indexed element or the element type. It replaces the division of the two sizeofs by ARRAY_SIZE. Signed-off-by: Himangi Saraogi Acked-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/misc/array_size.cocci | 87 ++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 scripts/coccinelle/misc/array_size.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/misc/array_size.cocci b/scripts/coccinelle/misc/array_size.cocci new file mode 100644 index 000000000000..81e279cd347b --- /dev/null +++ b/scripts/coccinelle/misc/array_size.cocci @@ -0,0 +1,87 @@ +/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element +/// +//# This makes an effort to find cases where ARRAY_SIZE can be used such as +//# where there is a division of sizeof the array by the sizeof its first +//# element or by any indexed element or the element type. It replaces the +//# division of the two sizeofs by ARRAY_SIZE. +// +// Confidence: High +// Copyright: (C) 2014 Himangi Saraogi. GPLv2. +// Comments: +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@i@ +@@ + +#include + +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- + +@depends on i&&context@ +type T; +T[] E; +@@ +( +* (sizeof(E)/sizeof(*E)) +| +* (sizeof(E)/sizeof(E[...])) +| +* (sizeof(E)/sizeof(T)) +) + +//---------------------------------------------------------- +// For patch mode +//---------------------------------------------------------- + +@depends on i&&patch@ +type T; +T[] E; +@@ +( +- (sizeof(E)/sizeof(*E)) ++ ARRAY_SIZE(E) +| +- (sizeof(E)/sizeof(E[...])) ++ ARRAY_SIZE(E) +| +- (sizeof(E)/sizeof(T)) ++ ARRAY_SIZE(E) +) + +//---------------------------------------------------------- +// For org and report mode +//---------------------------------------------------------- + +@r@ +type T; +T[] E; +position p; +@@ +( + (sizeof(E)@p /sizeof(*E)) +| + (sizeof(E)@p /sizeof(E[...])) +| + (sizeof(E)@p /sizeof(T)) +) + +@script:python depends on i&&org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_SIZE") + +@script:python depends on i&&report@ +p << r.p; +@@ + +msg="WARNING: Use ARRAY_SIZE" +coccilib.report.print_report(p[0], msg) + -- cgit v1.2.3 From e52320c3b20cbe209e98f2443866209120595636 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Mon, 14 Jul 2014 23:04:10 +0530 Subject: Coccinelle: Script to detect incorrect argument to sizeof This makes an effort to find cases where the argument to sizeof is wrong in memory allocation functions by checking the type of the allocated memory when it is a double pointer and ensuring the sizeof argument takes a pointer to the the memory being allocated. There are false positives in cases the sizeof argument is not used in constructing the return value. Signed-off-by: Himangi Saraogi Acked-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/misc/badty.cocci | 76 +++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 scripts/coccinelle/misc/badty.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/misc/badty.cocci b/scripts/coccinelle/misc/badty.cocci new file mode 100644 index 000000000000..2fc06fc71927 --- /dev/null +++ b/scripts/coccinelle/misc/badty.cocci @@ -0,0 +1,76 @@ +/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element +/// +//# This makes an effort to find cases where the argument to sizeof is wrong +//# in memory allocation functions by checking the type of the allocated memory +//# when it is a double pointer and ensuring the sizeof argument takes a pointer +//# to the the memory being allocated. There are false positives in cases the +//# sizeof argument is not used in constructing the return value. The result +//# may need some reformatting. +// +// Confidence: Moderate +// Copyright: (C) 2014 Himangi Saraogi. GPLv2. +// Comments: +// Options: + +virtual patch +virtual context +virtual org +virtual report + +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- + +@depends on context disable sizeof_type_expr@ +type T; +T **x; +@@ + + x = + <+...sizeof( +* T + )...+> + +//---------------------------------------------------------- +// For patch mode +//---------------------------------------------------------- + +@depends on patch disable sizeof_type_expr@ +type T; +T **x; +@@ + + x = + <+...sizeof( +- T ++ *x + )...+> + +//---------------------------------------------------------- +// For org and report mode +//---------------------------------------------------------- + +@r disable sizeof_type_expr@ +type T; +T **x; +position p; +@@ + + x = + <+...sizeof( + T@p + )...+> + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING sizeof argument should be pointer type, not structure type") + +@script:python depends on report@ +p << r.p; +@@ + +msg="WARNING: Use correct pointer type argument for sizeof" +coccilib.report.print_report(p[0], msg) + -- cgit v1.2.3 From 5be1df668a40cc0a49bc26023fffc537fae1778e Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Mon, 21 Jul 2014 03:06:35 +0530 Subject: Coccinelle: Script to replace if and BUG with BUG_ON This script detects cases where BUG() follows an if condition on an expression and replaces the if condition and BUG() with a BUG_ON having the conditional expression of the if statement as argument. Signed-off-by: Himangi Saraogi Acked-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/misc/bugon.cocci | 62 +++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 scripts/coccinelle/misc/bugon.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/misc/bugon.cocci b/scripts/coccinelle/misc/bugon.cocci new file mode 100644 index 000000000000..556456ca761c --- /dev/null +++ b/scripts/coccinelle/misc/bugon.cocci @@ -0,0 +1,62 @@ +/// Use BUG_ON instead of a if condition followed by BUG. +/// +//# This makes an effort to find cases where BUG() follows an if +//# condition on an expression and replaces the if condition and BUG() +//# with a BUG_ON having the conditional expression of the if statement +//# as argument. +// +// Confidence: High +// Copyright: (C) 2014 Himangi Saraogi. GPLv2. +// Comments: +// Options: --no-includes, --include-headers + +virtual patch +virtual context +virtual org +virtual report + +//---------------------------------------------------------- +// For context mode +//---------------------------------------------------------- + +@depends on context@ +expression e; +@@ + +*if (e) BUG(); + +//---------------------------------------------------------- +// For patch mode +//---------------------------------------------------------- + +@depends on patch@ +expression e; +@@ + +-if (e) BUG(); ++BUG_ON(e); + +//---------------------------------------------------------- +// For org and report mode +//---------------------------------------------------------- + +@r@ +expression e; +position p; +@@ + + if (e) BUG@p (); + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING use BUG_ON") + +@script:python depends on report@ +p << r.p; +@@ + +msg="WARNING: Use BUG_ON" +coccilib.report.print_report(p[0], msg) + -- cgit v1.2.3 From ebfdc40969f24fc0cdd1349835d36e8ebae05374 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:27 -0700 Subject: checkpatch: attempt to find unnecessary 'out of memory' messages Logging messages that show some type of "out of memory" error are generally unnecessary as there is a generic message and a stack dump done by the memory subsystem. These messages generally increase kernel size without much added value. Emit a warning on these types of messages. This test looks for any inserted message function, then looks at the previous line for an "if (!foo)" or "if (foo == NULL)" test and then looks at the preceding statement for an allocation function like "foo = kmalloc()" ie: this code matches: foo = kmalloc(); if (foo == NULL) { printk("Out of memory\n"); return -ENOMEM; } This test is very crude and incomplete. This test can miss quite a lot of of OOM messages that do not have this specific form. ie: this code does not match: foo = kmalloc(); if (!foo) { rtn = -ENOMEM; printk("Out of memory!\n"); goto out; } This test could also be a false positive when the logging message itself does not specify anything about memory, but I did not find any false positives in my limited testing. spatch could be a better solution but correctness seems non-trivial for that tool too. Signed-off-by: Joe Perches Acked-by: Dan Carpenter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 182be0f12407..ac1d6b0a6f09 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4014,6 +4014,23 @@ sub process { } } +# check for unnecessary "Out of Memory" messages + if ($line =~ /^\+.*\b$logFunctions\s*\(/ && + $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ && + (defined $1 || defined $3) && + $linenr > 3) { + my $testval = $2; + my $testline = $lines[$linenr - 3]; + + my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0); +# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n"); + + if ($c =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|(?:dev_)?alloc_skb)/) { + WARN("OOM_MESSAGE", + "Possible unnecessary 'out of memory' message\n" . $hereprev); + } + } + # check for bad placement of section $InitAttribute (e.g.: __initdata) if ($line =~ /(\b$InitAttribute\b)/) { my $attr = $1; -- cgit v1.2.3 From 032a4c0f9a77ce565355c6e191553e853ba66f09 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:29 -0700 Subject: checkpatch: warn on unnecessary else after return or break Using an else following a break or return can unnecessarily indent code blocks. ie: for (i = 0; i < 100; i++) { int foo = bar(); if (foo < 1) break; else usleep(1); } is generally better written as: for (i = 0; i < 100; i++) { int foo = bar(); if (foo < 1) break; usleep(1); } Warn when a bare else statement is preceded by a break or return indented 1 tab more than the else. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index ac1d6b0a6f09..d833b737a295 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2342,6 +2342,16 @@ sub process { # check we are in a valid C source file if not then ignore this hunk next if ($realfile !~ /\.(h|c)$/); +# check indentation of any line with a bare else +# if the previous line is a break or return and is indented 1 tab more... + if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) { + my $tabs = length($1) + 1; + if ($prevline =~ /^\+\t{$tabs,$tabs}(?:break|return)\b/) { + WARN("UNNECESSARY_ELSE", + "else is not generally useful after a break or return\n" . $hereprev); + } + } + # discourage the addition of CONFIG_EXPERIMENTAL in #if(def). if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) { WARN("CONFIG_EXPERIMENTAL", -- cgit v1.2.3 From 356fd398135480363402cd334ac3218be56b7201 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:31 -0700 Subject: checkpatch: fix complex macro false positive for escaped constant char A single escaped constant char is not a complex macro. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index d833b737a295..cadf70f0201a 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3772,7 +3772,7 @@ sub process { $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz - $dstat !~ /^'X'$/ && # character constants + $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants $dstat !~ /$exceptions/ && $dstat !~ /^\.$Ident\s*=/ && # .foo = $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo -- cgit v1.2.3 From 5a4e1fd37d0677755391e2e89e9386e072265157 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:33 -0700 Subject: checkpatch: fix function pointers in blank line needed after declarations test Add a function pointer declaration check to the test for blank line needed after declarations. Signed-off-by: Joe Perches Reported-by: Bruce W Allan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index cadf70f0201a..538105ae88b3 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2295,6 +2295,8 @@ sub process { if ($sline =~ /^\+\s+\S/ && #Not at char 1 # actual declarations ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || + # function pointer declarations + $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || # foo bar; where foo is some local typedef or #define $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || # known declaration macros @@ -2307,6 +2309,8 @@ sub process { $prevline =~ /(?:\{\s*|\\)$/) && # looks like a declaration !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || + # function pointer declarations + $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || # foo bar; where foo is some local typedef or #define $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || # known declaration macros -- cgit v1.2.3 From 29ee1b0c67e0dd7dea8dd718e8326076bce5b6fe Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:35 -0700 Subject: checkpatch: ignore email headers better There are some patches created by git format-patch that when scanned by checkpatch report errors on lines like To: address.tld This is a checkpatch false positive. Improve the logic a bit to ignore folded email headers to avoid emitting these messages. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 538105ae88b3..1ec68083a929 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1637,7 +1637,7 @@ sub process { my $signoff = 0; my $is_patch = 0; - my $in_header_lines = 1; + my $in_header_lines = $file ? 0 : 1; my $in_commit_log = 0; #Scanning lines before patch my $non_utf8_charset = 0; @@ -1993,7 +1993,8 @@ sub process { # Check if it's the start of a commit log # (not a header line and we haven't seen the patch filename) if ($in_header_lines && $realfile =~ /^$/ && - $rawline !~ /^(commit\b|from\b|[\w-]+:).+$/i) { + !($rawline =~ /^\s+\S/ || + $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) { $in_header_lines = 0; $in_commit_log = 1; } -- cgit v1.2.3 From 048b123fad06f33169caa4afd6d56d58c31517e5 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 6 Aug 2014 16:10:37 -0700 Subject: checkpatch.pl: also suggest 'else if' when if follows brace This might help a kernel hacker think twice before blindly adding a newline. Signed-off-by: Rasmus Villemoes Acked-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 1ec68083a929..c40ba40cef43 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3621,7 +3621,7 @@ sub process { # if should not continue a brace if ($line =~ /}\s*if\b/) { ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . + "trailing statements should be on next line (or did you mean 'else if'?)\n" . $herecurr); } # case and default should not have general statements after them -- cgit v1.2.3 From 7f61919144ca69ea29f29c3e60c5b7dbd2070aa6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:39 -0700 Subject: checkpatch: add test for blank lines after function/struct/union/enum Add a --strict test asking for a blank line after function/struct/union/enum declarations. Allow exceptions for several attributes and macro uses. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index c40ba40cef43..9e4ba9fa9bc8 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2292,6 +2292,22 @@ sub process { "networking block comments put the trailing */ on a separate line\n" . $herecurr); } +# check for missing blank lines after struct/union declarations +# with exceptions for various attributes and macros + if ($prevline =~ /^[\+ ]};?\s*$/ && + $line =~ /^\+/ && + !($line =~ /^\+\s*$/ || + $line =~ /^\+\s*EXPORT_SYMBOL/ || + $line =~ /^\+\s*MODULE_/i || + $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || + $line =~ /^\+[a-z_]*init/ || + $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || + $line =~ /^\+\s*DECLARE/ || + $line =~ /^\+\s*__setup/)) { + CHK("LINE_SPACING", + "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev); + } + # check for missing blank lines after declarations if ($sline =~ /^\+\s+\S/ && #Not at char 1 # actual declarations -- cgit v1.2.3 From 365dd4eaafa22d2c79913d5f057d636e8842c470 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:42 -0700 Subject: checkpatch: add a multiple blank lines test Multiple consecutive blank lines waste screen space. Emit a --strict only message with these blank lines. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9e4ba9fa9bc8..fad2116f51a4 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1642,6 +1642,8 @@ sub process { my $non_utf8_charset = 0; + my $last_blank_line = 0; + our @report = (); our $cnt_lines = 0; our $cnt_error = 0; @@ -2308,6 +2310,15 @@ sub process { "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev); } +# check for multiple consecutive blank lines + if ($prevline =~ /^[\+ ]\s*$/ && + $line =~ /^\+\s*$/ && + $last_blank_line != ($linenr - 1)) { + CHK("LINE_SPACING", + "Please don't use multiple blank lines\n" . $hereprev); + $last_blank_line = $linenr; + } + # check for missing blank lines after declarations if ($sline =~ /^\+\s+\S/ && #Not at char 1 # actual declarations -- cgit v1.2.3 From fee0aa83d43ee65648778d48d47975c323fa0490 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:44 -0700 Subject: checkpatch: change blank line after declaration type to "LINE_SPACING" Make it consistent with the other missing or multiple blank line tests. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index fad2116f51a4..146e9f907280 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2353,7 +2353,7 @@ sub process { $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && # indentation of previous and current line are the same (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { - WARN("SPACING", + WARN("LINE_SPACING", "Missing a blank line after declarations\n" . $hereprev); } -- cgit v1.2.3 From 8d73e0e7dc18a39b120cb85ec675d59516e0af1a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:46 -0700 Subject: checkpatch: quiet Kconfig help message checking Editing Kconfig dependencies can emit unnecessary messages about missing or too short help entries. Only emit the message when adding help sections to Kconfig files. Signed-off-by: Joe Perches Reported-by: Jean Delvare Tested-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 146e9f907280..df4250a8ad51 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2052,7 +2052,7 @@ sub process { # 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*config\s+/) { + $line =~ /^\+\s*config\s+/) { my $length = 0; my $cnt = $realcnt; my $ln = $linenr + 1; @@ -2065,10 +2065,11 @@ sub process { $is_end = $lines[$ln - 1] =~ /^\+/; next if ($f =~ /^-/); + last if (!$file && $f =~ /^\@\@/); - if ($lines[$ln - 1] =~ /.\s*(?:bool|tristate)\s*\"/) { + if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) { $is_start = 1; - } elsif ($lines[$ln - 1] =~ /.\s*(?:---)?help(?:---)?$/) { + } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) { $length = -1; } -- cgit v1.2.3 From e2826fd07029e14285c178b41b18f6edc3b15a84 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:48 -0700 Subject: checkpatch: warn on unnecessary parentheses around references of foo->bar Parentheses around &(foo->bar) and *(foo->bar) are unnecessary. Emit a --strict only message on these uses. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index df4250a8ad51..9a89a0609bac 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3491,6 +3491,14 @@ sub process { } } +# check unnecessary parentheses around addressof/dereference single $Lvals +# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar + + while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) { + CHK("UNNECESSARY_PARENTHESES", + "Unnecessary parentheses around $1\n" . $herecurr); + } + #goto labels aren't indented, allow a single space however if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { -- cgit v1.2.3 From 1574a29f8e769998fe3e55eb6030dc61e3d09ccd Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:50 -0700 Subject: checkpatch: allow multiple const * types checkpatch's $Type variable does not match declarations of multiple const * types. This can produce false positives for things like: $ ./scripts/checkpatch.pl -f drivers/staging/comedi/comedidev.h WARNING: Missing a blank line after declarations #60: FILE: drivers/staging/comedi/comedidev.h:60: + const struct comedi_lrange *range_table; + const struct comedi_lrange *const *range_table_list; Fix the $Type variable to support matching multiple "* const" uses. Signed-off-by: Joe Perches Reported-by: Hartley Sweeten Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9a89a0609bac..57a11d7ee841 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -435,7 +435,7 @@ sub build_types { }x; $Type = qr{ $NonptrType - (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)? + (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? (?:\s+$Inline|\s+$Modifier)* }x; $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; -- cgit v1.2.3 From f27c95db1176b41c6c87d9d3480d15efbca8f3ff Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:52 -0700 Subject: checkpatch: improve "no space after cast" test This --strict test previously worked only for what appeared to be cast to pointer types. Make it work for all casts. Also, there's no reason to show the previous line for this type of message, so don't. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 57a11d7ee841..b351805149a5 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2260,12 +2260,12 @@ sub process { } } - if ($line =~ /^\+.*\*[ \t]*\)[ \t]+(?!$Assignment|$Arithmetic)/) { + if ($line =~ /^\+.*\(\s*$Type\s*\)[ \t]+(?!$Assignment|$Arithmetic)/) { if (CHK("SPACING", - "No space is necessary after a cast\n" . $hereprev) && + "No space is necessary after a cast\n" . $herecurr) && $fix) { $fixed[$linenr - 1] =~ - s/^(\+.*\*[ \t]*\))[ \t]+/$1/; + s/(\(\s*$Type\s*\))[ \t]+/$1/; } } -- cgit v1.2.3 From e367455a9f25b11e02b7ea7678a7b146bdd6667e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:55 -0700 Subject: checkpatch: emit fewer kmalloc_array/kcalloc conversion warnings Avoid matching allocs that appear to be known small multiplications of a sizeof with a constant because gcc as of 4.8 cannot optimize the code in a calloc() exactly the same way as an alloc(). Look for numeric constants or what appear to be upper case only macro #defines. Signed-off-by: Joe Perches Reported-by: Theodore Ts'o Original-patch-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index b351805149a5..3661ffc7af23 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4487,22 +4487,23 @@ sub process { # check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc if ($^V && $^V ge 5.10.0 && - $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/) { + $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { my $oldfunc = $3; my $a1 = $4; my $a2 = $10; my $newfunc = "kmalloc_array"; $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); - if ($a1 =~ /^sizeof\s*\S/ || $a2 =~ /^sizeof\s*\S/) { + my $r1 = $a1; + my $r2 = $a2; + if ($a1 =~ /^sizeof\s*\S/) { + $r1 = $a2; + $r2 = $a1; + } + if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ && + !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) { if (WARN("ALLOC_WITH_MULTIPLY", "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) && $fix) { - my $r1 = $a1; - my $r2 = $a2; - if ($a1 =~ /^sizeof\s*\S/) { - $r1 = $a2; - $r2 = $a1; - } $fixed[$linenr - 1] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; } -- cgit v1.2.3 From d311cd44545f2f69749c68d6723360b4cc21cd02 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:57 -0700 Subject: checkpatch: add test for commit id formatting style in commit log Commit logs have various forms of commit id references. Try to standardize on a 12 character long lower case commit id along with a description of parentheses and the quoted subject line. ie: commit 0123456789ab ("commit description") If git and a git tree exists, look up the commit id and emit the appropriate line as part of the message. Signed-off-by: Joe Perches Requested-by: Andrew Morton Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 3661ffc7af23..496f9abdb930 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -550,6 +550,34 @@ sub seed_camelcase_includes { } } +sub git_commit_info { + my ($commit, $id, $desc) = @_; + + return ($id, $desc) if ((which("git") eq "") || !(-e ".git")); + + my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`; + $output =~ s/^\s*//gm; + my @lines = split("\n", $output); + + if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) { +# Maybe one day convert this block of bash into something that returns +# all matching commit ids, but it's very slow... +# +# echo "checking commits $1..." +# git rev-list --remotes | grep -i "^$1" | +# while read line ; do +# git log --format='%H %s' -1 $line | +# echo "commit $(cut -c 1-12,41-)" +# done + } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) { + } else { + $id = substr($lines[0], 0, 12); + $desc = substr($lines[0], 41); + } + + return ($id, $desc); +} + $chk_signoff = 0 if ($file); my @rawlines = (); @@ -674,6 +702,18 @@ sub format_email { return $formatted_email; } +sub which { + my ($bin) = @_; + + foreach my $path (split(/:/, $ENV{PATH})) { + if (-e "$path/$bin") { + return "$path/$bin"; + } + } + + return ""; +} + sub which_conf { my ($conf) = @_; @@ -1958,6 +1998,20 @@ sub process { "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr); } +# Check for improperly formed commit descriptions + if ($in_commit_log && + $line =~ /\bcommit\s+[0-9a-f]{5,}/i && + $line !~ /\b[Cc]ommit [0-9a-f]{12,16} \("/) { + $line =~ /\b(c)ommit\s+([0-9a-f]{5,})/i; + my $init_char = $1; + my $orig_commit = lc($2); + my $id = '01234567890ab'; + my $desc = 'commit description'; + ($id, $desc) = git_commit_info($orig_commit, $id, $desc); + ERROR("GIT_COMMIT_ID", + "Please use 12 to 16 chars for the git commit ID like: '${init_char}ommit $id (\"$desc\")'\n" . $herecurr); + } + # Check for wrappage within a valid hunk of the file if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { ERROR("CORRUPTED_PATCH", -- cgit v1.2.3 From 13f1937ef33950b1112049972249e6191b82e6c9 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:10:59 -0700 Subject: checkpatch: emit a warning on file add/move/delete Whenever files are added, moved, or deleted, the MAINTAINERS file patterns can be out of sync or outdated. To try to keep MAINTAINERS more up-to-date, add a one-time warning whenever a patch does any of those. Signed-off-by: Joe Perches Acked-by: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 496f9abdb930..0cf8b98d8dc9 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1679,7 +1679,7 @@ sub process { my $in_header_lines = $file ? 0 : 1; my $in_commit_log = 0; #Scanning lines before patch - + my $reported_maintainer_file = 0; my $non_utf8_charset = 0; my $last_blank_line = 0; @@ -2012,6 +2012,17 @@ sub process { "Please use 12 to 16 chars for the git commit ID like: '${init_char}ommit $id (\"$desc\")'\n" . $herecurr); } +# Check for added, moved or deleted files + if (!$reported_maintainer_file && !$in_commit_log && + ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || + $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || + ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && + (defined($1) || defined($2))))) { + $reported_maintainer_file = 1; + WARN("FILE_PATH_CHANGES", + "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); + } + # Check for wrappage within a valid hunk of the file if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { ERROR("CORRUPTED_PATCH", -- cgit v1.2.3 From c00df19a5026f2cb08f1770dcc29226512f4d099 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:01 -0700 Subject: checkpatch: warn on break after goto or return with same tab indentation Using break; after a goto or return is unnecessary so emit a warning when the break is at the same indent level. So this emits a warning on: switch (foo) { case 1: goto err; break; } but not on: switch (foo) { case 1: if (bar()) goto err; break; } Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0cf8b98d8dc9..fc72d64cd2d4 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2450,6 +2450,16 @@ sub process { } } +# check indentation of a line with a break; +# if the previous line is a goto or return and is indented the same # of tabs + if ($sline =~ /^\+([\t]+)break\s*;\s*$/) { + my $tabs = $1; + if ($prevline =~ /^\+$tabs(?:goto|return)\b/) { + WARN("UNNECESSARY_BREAK", + "break is not useful after a goto or return\n" . $hereprev); + } + } + # discourage the addition of CONFIG_EXPERIMENTAL in #if(def). if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) { WARN("CONFIG_EXPERIMENTAL", -- cgit v1.2.3 From 194f66fc9567367b3fa2dcbc1b87b091330ef186 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:03 -0700 Subject: checkpatch: add an index variable for fixed lines Make the fix code a bit easier to read. This should also start to allow an easier mechanism to insert/delete lines eventually too. Signed-off-by: Joe Perches Cc: Andy Whitcroft Cc: Dan Carpenter Cc: Josh Triplett Cc: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 114 ++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 54 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index fc72d64cd2d4..f905d7b50530 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -583,6 +583,8 @@ $chk_signoff = 0 if ($file); my @rawlines = (); my @lines = (); my @fixed = (); +my $fixlinenr = -1; + my $vname; for my $filename (@ARGV) { my $FILE; @@ -611,6 +613,7 @@ for my $filename (@ARGV) { @rawlines = (); @lines = (); @fixed = (); + $fixlinenr = -1; } exit($exit); @@ -1801,8 +1804,10 @@ sub process { $realcnt = 0; $linenr = 0; + $fixlinenr = -1; foreach my $line (@lines) { $linenr++; + $fixlinenr++; my $sline = $line; #copy of $line $sline =~ s/$;/ /g; #with comments as spaces @@ -1933,7 +1938,7 @@ sub process { if (WARN("BAD_SIGN_OFF", "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] = + $fixed[$fixlinenr] = "$ucfirst_sign_off $email"; } } @@ -1941,7 +1946,7 @@ sub process { if (WARN("BAD_SIGN_OFF", "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] = + $fixed[$fixlinenr] = "$ucfirst_sign_off $email"; } @@ -1950,7 +1955,7 @@ sub process { if (WARN("BAD_SIGN_OFF", "Use a single space after $ucfirst_sign_off\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] = + $fixed[$fixlinenr] = "$ucfirst_sign_off $email"; } } @@ -2089,14 +2094,14 @@ sub process { if (ERROR("DOS_LINE_ENDINGS", "DOS line endings\n" . $herevet) && $fix) { - $fixed[$linenr - 1] =~ s/[\s\015]+$//; + $fixed[$fixlinenr] =~ s/[\s\015]+$//; } } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { my $herevet = "$here\n" . cat_vet($rawline) . "\n"; if (ERROR("TRAILING_WHITESPACE", "trailing whitespace\n" . $herevet) && $fix) { - $fixed[$linenr - 1] =~ s/\s+$//; + $fixed[$fixlinenr] =~ s/\s+$//; } $rpt_cleaners = 1; @@ -2235,7 +2240,7 @@ sub process { if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", "unnecessary whitespace before a quoted newline\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; + $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; } } @@ -2272,7 +2277,7 @@ sub process { if (ERROR("CODE_INDENT", "code indent should use tabs where possible\n" . $herevet) && $fix) { - $fixed[$linenr - 1] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; + $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; } } @@ -2282,9 +2287,9 @@ sub process { if (WARN("SPACE_BEFORE_TAB", "please, no space before tabs\n" . $herevet) && $fix) { - while ($fixed[$linenr - 1] =~ + while ($fixed[$fixlinenr] =~ s/(^\+.*) {8,8}+\t/$1\t\t/) {} - while ($fixed[$linenr - 1] =~ + while ($fixed[$fixlinenr] =~ s/(^\+.*) +\t/$1\t/) {} } } @@ -2318,7 +2323,7 @@ sub process { if (CHK("PARENTHESIS_ALIGNMENT", "Alignment should match open parenthesis\n" . $hereprev) && $fix && $line =~ /^\+/) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/^\+[ \t]*/\+$goodtabindent/; } } @@ -2329,7 +2334,7 @@ sub process { if (CHK("SPACING", "No space is necessary after a cast\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/(\(\s*$Type\s*\))[ \t]+/$1/; } } @@ -2433,7 +2438,7 @@ sub process { if (WARN("LEADING_SPACE", "please, no spaces at the start of a line\n" . $herevet) && $fix) { - $fixed[$linenr - 1] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; + $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; } } @@ -2798,10 +2803,10 @@ sub process { if (ERROR("C99_COMMENTS", "do not use C99 // comments\n" . $herecurr) && $fix) { - my $line = $fixed[$linenr - 1]; + my $line = $fixed[$fixlinenr]; if ($line =~ /\/\/(.*)$/) { my $comment = trim($1); - $fixed[$linenr - 1] =~ s@\/\/(.*)$@/\* $comment \*/@; + $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@; } } } @@ -2860,7 +2865,7 @@ sub process { "do not initialise globals to 0 or NULL\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/($Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/$1;/; + $fixed[$fixlinenr] =~ s/($Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/$1;/; } } # check for static initialisers. @@ -2869,7 +2874,7 @@ sub process { "do not initialise statics to 0 or NULL\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/(\bstatic\s.*?)\s*=\s*(0|NULL|false)\s*;/$1;/; + $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*(0|NULL|false)\s*;/$1;/; } } @@ -2899,7 +2904,7 @@ sub process { if (ERROR("FUNCTION_WITHOUT_ARGS", "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; + $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; } } @@ -2908,7 +2913,7 @@ sub process { if (WARN("DEFINE_PCI_DEVICE_TABLE", "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /; + $fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /; } } @@ -2945,7 +2950,7 @@ sub process { my $sub_from = $ident; my $sub_to = $ident; $sub_to =~ s/\Q$from\E/$to/; - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s@\Q$sub_from\E@$sub_to@; } } @@ -2973,7 +2978,7 @@ sub process { my $sub_from = $match; my $sub_to = $match; $sub_to =~ s/\Q$from\E/$to/; - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s@\Q$sub_from\E@$sub_to@; } } @@ -3035,7 +3040,7 @@ sub process { if (WARN("PREFER_PR_LEVEL", "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/\bpr_warning\b/pr_warn/; } } @@ -3069,7 +3074,7 @@ sub process { if (WARN("SPACING", "missing space after $1 definition\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/; } } @@ -3139,7 +3144,7 @@ sub process { } if (show_type("SPACING") && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex; } } @@ -3156,7 +3161,7 @@ sub process { if (ERROR("BRACKET_SPACE", "space prohibited before open square bracket '['\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/^(\+.*?)\s+\[/$1\[/; } } @@ -3191,7 +3196,7 @@ sub process { if (WARN("SPACING", "space prohibited between function name and open parenthesis '('\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/\b$name\s+\(/$name\(/; } } @@ -3459,8 +3464,8 @@ sub process { $fixed_line = $fixed_line . $fix_elements[$#elements]; } - if ($fix && $line_fixed && $fixed_line ne $fixed[$linenr - 1]) { - $fixed[$linenr - 1] = $fixed_line; + if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) { + $fixed[$fixlinenr] = $fixed_line; } @@ -3471,7 +3476,7 @@ sub process { if (WARN("SPACING", "space prohibited before semicolon\n" . $herecurr) && $fix) { - 1 while $fixed[$linenr - 1] =~ + 1 while $fixed[$fixlinenr] =~ s/^(\+.*\S)\s+;/$1;/; } } @@ -3504,7 +3509,7 @@ sub process { if (ERROR("SPACING", "space required before the open brace '{'\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/^(\+.*(?:do|\))){/$1 {/; + $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/; } } @@ -3522,7 +3527,7 @@ sub process { if (ERROR("SPACING", "space required after that close brace '}'\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/}((?!(?:,|;|\)))\S)/} $1/; } } @@ -3532,7 +3537,7 @@ sub process { if (ERROR("SPACING", "space prohibited after that open square bracket '['\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/\[\s+/\[/; } } @@ -3540,7 +3545,7 @@ sub process { if (ERROR("SPACING", "space prohibited before that close square bracket ']'\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/\s+\]/\]/; } } @@ -3551,7 +3556,7 @@ sub process { if (ERROR("SPACING", "space prohibited after that open parenthesis '('\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/\(\s+/\(/; } } @@ -3561,7 +3566,8 @@ sub process { if (ERROR("SPACING", "space prohibited before that close parenthesis ')'\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + print("fixlinenr: <$fixlinenr> fixed[fixlinenr]: <$fixed[$fixlinenr]>\n"); + $fixed[$fixlinenr] =~ s/\s+\)/\)/; } } @@ -3580,7 +3586,7 @@ sub process { if (WARN("INDENTED_LABEL", "labels should not be indented\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/^(.)\s+/$1/; } } @@ -3642,7 +3648,7 @@ sub process { if (ERROR("SPACING", "space required before the open parenthesis '('\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/\b(if|while|for|switch)\(/$1 \(/; } } @@ -3779,7 +3785,7 @@ sub process { "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) && $fix) { my $hexval = sprintf("0x%x", oct($var)); - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/\b$var\b/$hexval/; } } @@ -3815,7 +3821,7 @@ sub process { if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", "Whitespace after \\ makes next lines useless\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\s+$//; + $fixed[$fixlinenr] =~ s/\s+$//; } } @@ -4170,7 +4176,7 @@ sub process { WARN("MISPLACED_INIT", "$attr should be placed after $var\n" . $herecurr))) && $fix) { - $fixed[$linenr - 1] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e; + $fixed[$fixlinenr] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e; } } } @@ -4184,7 +4190,7 @@ sub process { if (ERROR("INIT_ATTRIBUTE", "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/$InitAttributeData/${attr_prefix}initconst/; } } @@ -4195,12 +4201,12 @@ sub process { if (ERROR("INIT_ATTRIBUTE", "Use of $attr requires a separate use of const\n" . $herecurr) && $fix) { - my $lead = $fixed[$linenr - 1] =~ + my $lead = $fixed[$fixlinenr] =~ /(^\+\s*(?:static\s+))/; $lead = rtrim($1); $lead = "$lead " if ($lead !~ /^\+$/); $lead = "${lead}const "; - $fixed[$linenr - 1] =~ s/(^\+\s*(?:static\s+))/$lead/; + $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/; } } @@ -4213,7 +4219,7 @@ sub process { if (WARN("CONSTANT_CONVERSION", "$constant_func should be $func\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\b$constant_func\b/$func/g; + $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g; } } @@ -4263,7 +4269,7 @@ sub process { if (ERROR("SPACING", "exactly one space required after that #$1\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ + $fixed[$fixlinenr] =~ s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; } @@ -4311,7 +4317,7 @@ sub process { if (WARN("INLINE", "plain inline is preferred over $1\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\b(__inline__|__inline)\b/inline/; + $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/; } } @@ -4336,7 +4342,7 @@ sub process { if (WARN("PREFER_PRINTF", "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; + $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; } } @@ -4347,7 +4353,7 @@ sub process { if (WARN("PREFER_SCANF", "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; + $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; } } @@ -4362,7 +4368,7 @@ sub process { if (WARN("SIZEOF_PARENTHESIS", "sizeof $1 should be sizeof($1)\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; + $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; } } @@ -4385,7 +4391,7 @@ sub process { if (WARN("PREFER_SEQ_PUTS", "Prefer seq_puts to seq_printf\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\bseq_printf\b/seq_puts/; + $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/; } } } @@ -4414,7 +4420,7 @@ sub process { if (WARN("PREFER_ETHER_ADDR_COPY", "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; + $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; } } @@ -4502,7 +4508,7 @@ sub process { if (CHK("AVOID_EXTERNS", "extern prototypes should be avoided in .h files\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; + $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; } } @@ -4579,7 +4585,7 @@ sub process { if (WARN("ALLOC_WITH_MULTIPLY", "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; + $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; } } @@ -4603,7 +4609,7 @@ sub process { if (WARN("ONE_SEMICOLON", "Statements terminations use 1 semicolon\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/(\s*;\s*){2,}$/;/g; + $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g; } } @@ -4651,7 +4657,7 @@ sub process { if (WARN("USE_FUNC", "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) && $fix) { - $fixed[$linenr - 1] =~ s/\b__FUNCTION__\b/__func__/g; + $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g; } } -- cgit v1.2.3 From d752fcc88b7dddc0bbe6d43b658b306a9d7d1dae Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:05 -0700 Subject: checkpatch: add ability to insert and delete lines to patch/file This can be valuable to insert or delete blank lines as well as fix misplaced brace or else uses. Store indexes of lines to be added/deleted and the new lines. When creating the --fix file, insert or delete the appropriate lines and update the patch range information. Signed-off-by: Joe Perches Cc: Andy Whitcroft Cc: Dan Carpenter Cc: Josh Triplett Cc: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 141 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 130 insertions(+), 11 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index f905d7b50530..f3d9a883f8be 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -583,6 +583,8 @@ $chk_signoff = 0 if ($file); my @rawlines = (); my @lines = (); my @fixed = (); +my @fixed_inserted = (); +my @fixed_deleted = (); my $fixlinenr = -1; my $vname; @@ -613,6 +615,8 @@ for my $filename (@ARGV) { @rawlines = (); @lines = (); @fixed = (); + @fixed_inserted = (); + @fixed_deleted = (); $fixlinenr = -1; } @@ -1526,6 +1530,69 @@ sub report_dump { our @report; } +sub fixup_current_range { + my ($lineRef, $offset, $length) = @_; + + if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) { + my $o = $1; + my $l = $2; + my $no = $o + $offset; + my $nl = $l + $length; + $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/; + } +} + +sub fix_inserted_deleted_lines { + my ($linesRef, $insertedRef, $deletedRef) = @_; + + my $range_last_linenr = 0; + my $delta_offset = 0; + + my $old_linenr = 0; + my $new_linenr = 0; + + my $next_insert = 0; + my $next_delete = 0; + + my @lines = (); + + my $inserted = @{$insertedRef}[$next_insert++]; + my $deleted = @{$deletedRef}[$next_delete++]; + + foreach my $old_line (@{$linesRef}) { + my $save_line = 1; + my $line = $old_line; #don't modify the array + if ($line =~ /^(?:\+\+\+\|\-\-\-)\s+\S+/) { #new filename + $delta_offset = 0; + } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk + $range_last_linenr = $new_linenr; + fixup_current_range(\$line, $delta_offset, 0); + } + + while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) { + $deleted = @{$deletedRef}[$next_delete++]; + $save_line = 0; + fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1); + } + + while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) { + push(@lines, ${$inserted}{'LINE'}); + $inserted = @{$insertedRef}[$next_insert++]; + $new_linenr++; + fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1); + } + + if ($save_line) { + push(@lines, $line); + $new_linenr++; + } + + $old_linenr++; + } + + return @lines; +} + sub ERROR { my ($type, $msg) = @_; @@ -2377,16 +2444,31 @@ sub process { $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || $line =~ /^\+\s*DECLARE/ || $line =~ /^\+\s*__setup/)) { - CHK("LINE_SPACING", - "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev); + if (CHK("LINE_SPACING", + "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) && + $fix) { + my $inserted = { + LINENR => $fixlinenr, + LINE => "\+", + }; + push(@fixed_inserted, $inserted); + } } # check for multiple consecutive blank lines if ($prevline =~ /^[\+ ]\s*$/ && $line =~ /^\+\s*$/ && $last_blank_line != ($linenr - 1)) { - CHK("LINE_SPACING", - "Please don't use multiple blank lines\n" . $hereprev); + if (CHK("LINE_SPACING", + "Please don't use multiple blank lines\n" . $hereprev) && + $fix) { + my $deleted = { + LINENR => $fixlinenr, + LINE => $rawline, + }; + push(@fixed_deleted, $deleted); + } + $last_blank_line = $linenr; } @@ -2424,8 +2506,15 @@ sub process { $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && # indentation of previous and current line are the same (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { - WARN("LINE_SPACING", - "Missing a blank line after declarations\n" . $hereprev); + if (WARN("LINE_SPACING", + "Missing a blank line after declarations\n" . $hereprev) && + $fix) { + my $inserted = { + LINENR => $fixlinenr, + LINE => "\+", + }; + push(@fixed_inserted, $inserted); + } } # check for spaces at the beginning of a line. @@ -2627,7 +2716,7 @@ sub process { #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; - if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { + if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { ERROR("OPEN_BRACE", "that open brace { should be on the previous line\n" . "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); @@ -2777,8 +2866,34 @@ sub process { # check for initialisation to aggregates open brace on the next line if ($line =~ /^.\s*{/ && $prevline =~ /(?:^|[^=])=\s*$/) { - ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . $hereprev); + if (ERROR("OPEN_BRACE", + "that open brace { should be on the previous line\n" . $hereprev) && + $fix && $prevline =~ /^\+/) { + my $deleted = { + LINENR => $fixlinenr - 1, + LINE => $prevrawline, + }; + push(@fixed_deleted, $deleted); + $deleted = { + LINENR => $fixlinenr, + LINE => $rawline, + }; + push(@fixed_deleted, $deleted); + my $fixedline = $prevrawline; + $fixedline =~ s/\s*=\s*$/ = {/; + my $inserted = { + LINENR => $fixlinenr, + LINE => $fixedline, + }; + push(@fixed_inserted, $inserted); + $fixedline = $line; + $fixedline =~ s/^(.\s*){\s*/$1/; + $inserted = { + LINENR => $fixlinenr, + LINE => $fixedline, + }; + push(@fixed_inserted, $inserted); + } } # @@ -4900,12 +5015,16 @@ sub process { hash_show_words(\%use_type, "Used"); hash_show_words(\%ignore_type, "Ignored"); - if ($clean == 0 && $fix && "@rawlines" ne "@fixed") { + if ($clean == 0 && $fix && + ("@rawlines" ne "@fixed" || + $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) { my $newfile = $filename; $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); my $linecount = 0; my $f; + @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted); + open($f, '>', $newfile) or die "$P: Can't open $newfile for write\n"; foreach my $fixed_line (@fixed) { @@ -4913,7 +5032,7 @@ sub process { if ($file) { if ($linecount > 3) { $fixed_line =~ s/^\+//; - print $f $fixed_line. "\n"; + print $f $fixed_line . "\n"; } } else { print $f $fixed_line . "\n"; -- cgit v1.2.3 From f2d7e4d4398092d14fb039cb4d38e502d3f019ee Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:07 -0700 Subject: checkpatch: add fix_insert_line and fix_delete_line helpers Neaten the uses of patch/file line insertions or deletions. Hide the mechanism used. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 65 +++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 36 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index f3d9a883f8be..7c290693b8af 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1593,6 +1593,27 @@ sub fix_inserted_deleted_lines { return @lines; } +sub fix_insert_line { + my ($linenr, $line) = @_; + + my $inserted = { + LINENR => $linenr, + LINE => $line, + }; + push(@fixed_inserted, $inserted); +} + +sub fix_delete_line { + my ($linenr, $line) = @_; + + my $deleted = { + LINENR => $linenr, + LINE => $line, + }; + + push(@fixed_deleted, $deleted); +} + sub ERROR { my ($type, $msg) = @_; @@ -2447,11 +2468,7 @@ sub process { if (CHK("LINE_SPACING", "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) && $fix) { - my $inserted = { - LINENR => $fixlinenr, - LINE => "\+", - }; - push(@fixed_inserted, $inserted); + fix_insert_line($fixlinenr, "\+"); } } @@ -2462,11 +2479,7 @@ sub process { if (CHK("LINE_SPACING", "Please don't use multiple blank lines\n" . $hereprev) && $fix) { - my $deleted = { - LINENR => $fixlinenr, - LINE => $rawline, - }; - push(@fixed_deleted, $deleted); + fix_delete_line($fixlinenr, $rawline); } $last_blank_line = $linenr; @@ -2509,11 +2522,7 @@ sub process { if (WARN("LINE_SPACING", "Missing a blank line after declarations\n" . $hereprev) && $fix) { - my $inserted = { - LINENR => $fixlinenr, - LINE => "\+", - }; - push(@fixed_inserted, $inserted); + fix_insert_line($fixlinenr, "\+"); } } @@ -2868,31 +2877,15 @@ sub process { $prevline =~ /(?:^|[^=])=\s*$/) { if (ERROR("OPEN_BRACE", "that open brace { should be on the previous line\n" . $hereprev) && - $fix && $prevline =~ /^\+/) { - my $deleted = { - LINENR => $fixlinenr - 1, - LINE => $prevrawline, - }; - push(@fixed_deleted, $deleted); - $deleted = { - LINENR => $fixlinenr, - LINE => $rawline, - }; - push(@fixed_deleted, $deleted); + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); my $fixedline = $prevrawline; $fixedline =~ s/\s*=\s*$/ = {/; - my $inserted = { - LINENR => $fixlinenr, - LINE => $fixedline, - }; - push(@fixed_inserted, $inserted); + fix_insert_line($fixlinenr, $fixedline); $fixedline = $line; $fixedline =~ s/^(.\s*){\s*/$1/; - $inserted = { - LINENR => $fixlinenr, - LINE => $fixedline, - }; - push(@fixed_inserted, $inserted); + fix_insert_line($fixlinenr, $fixedline); } } -- cgit v1.2.3 From bd474ca076af8ac6fa8c5f4167f6024b446a08c8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:10 -0700 Subject: checkpatch: use the correct indentation for which() I copied the which subroutine from get_maintainer.pl. Unfortunately, get_maintainer uses a 4 space indentation so use the proper tab indentation instead. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 7c290693b8af..569ba315823e 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -710,15 +710,15 @@ sub format_email { } sub which { - my ($bin) = @_; + my ($bin) = @_; - foreach my $path (split(/:/, $ENV{PATH})) { - if (-e "$path/$bin") { - return "$path/$bin"; + foreach my $path (split(/:/, $ENV{PATH})) { + if (-e "$path/$bin") { + return "$path/$bin"; + } } - } - return ""; + return ""; } sub which_conf { -- cgit v1.2.3 From 8d1824780f2f1786db5e0e7a54bbae75340c655c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:12 -0700 Subject: checkpatch: add --fix option for a couple OPEN_BRACE misuses Style misuses of these types are corrected: typedef struct foo { int bar; }; int foo(int bar) { return bar+1; } int foo(int bar) { return bar+1; } Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 569ba315823e..1e95953b488f 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3164,17 +3164,40 @@ sub process { # function brace can't be on same line, except for #defines of do while, # or if closed on same line - if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and + if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) { - ERROR("OPEN_BRACE", - "open brace '{' following function declarations go on the next line\n" . $herecurr); + if (ERROR("OPEN_BRACE", + "open brace '{' following function declarations go on the next line\n" . $herecurr) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + my $fixed_line = $rawline; + $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/; + my $line1 = $1; + my $line2 = $2; + fix_insert_line($fixlinenr, ltrim($line1)); + fix_insert_line($fixlinenr, "\+{"); + if ($line2 !~ /^\s*$/) { + fix_insert_line($fixlinenr, "\+\t" . trim($line2)); + } + } } # open braces for enum, union and struct go on the same line. if ($line =~ /^.\s*{/ && $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { - ERROR("OPEN_BRACE", - "open brace '{' following $1 go on the same line\n" . $hereprev); + if (ERROR("OPEN_BRACE", + "open brace '{' following $1 go on the same line\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = rtrim($prevrawline) . " {"; + fix_insert_line($fixlinenr, $fixedline); + $fixedline = $rawline; + $fixedline =~ s/^(.\s*){\s*/$1\t/; + if ($fixedline !~ /^\+\s*$/) { + fix_insert_line($fixlinenr, $fixedline); + } + } } # missing space after union, struct or enum definition -- cgit v1.2.3 From 8b8856f4b102ce148611322465f2ff8932664411 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:14 -0700 Subject: checkpatch: fix brace style misuses of else and while Add --fix corrections for ELSE_AFTER_BRACE and WHILE_AFTER_BRACE misuses. if (x) { ... } else { ... } is corrected to if (x) { ... } else { ... } and do { ... } while (x); is corrected to do { ... } while (x); Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 1e95953b488f..404e3d6906aa 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3885,14 +3885,26 @@ sub process { # Check for }else {, these must be at the same # indent level to be relevant to each other. - if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and - $previndent == $indent) { - ERROR("ELSE_AFTER_BRACE", - "else should follow close brace '}'\n" . $hereprev); + if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ && + $previndent == $indent) { + if (ERROR("ELSE_AFTER_BRACE", + "else should follow close brace '}'\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + $fixedline =~ s/}\s*$//; + if ($fixedline !~ /^\+\s*$/) { + fix_insert_line($fixlinenr, $fixedline); + } + $fixedline = $rawline; + $fixedline =~ s/^(.\s*)else/$1} else/; + fix_insert_line($fixlinenr, $fixedline); + } } - if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and - $previndent == $indent) { + if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ && + $previndent == $indent) { my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); # Find out what is on the end of the line after the @@ -3901,8 +3913,18 @@ sub process { $s =~ s/\n.*//g; if ($s =~ /^\s*;/) { - ERROR("WHILE_AFTER_BRACE", - "while should follow close brace '}'\n" . $hereprev); + if (ERROR("WHILE_AFTER_BRACE", + "while should follow close brace '}'\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + my $trailing = $rawline; + $trailing =~ s/^\+//; + $trailing = trim($trailing); + $fixedline =~ s/}\s*$/} $trailing/; + fix_insert_line($fixlinenr, $fixedline); + } } } -- cgit v1.2.3 From 0fe3dc2bc554b849c27c0ebc36daedf032514200 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:16 -0700 Subject: checkpatch: add for_each tests to indentation and brace tests All the various for_each loop macros were not tested for trailing brace on the following lines and for bad indentation. Add them. Signed-off-by: Joe Perches Reported-by: Greg KH Cc: Andy Whitcroft Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 404e3d6906aa..dc72a9b3172d 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2698,7 +2698,7 @@ sub process { # if/while/etc brace do not go on next line, unless defining a do while loop, # or if that brace on the next line is for something else - if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { + if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { my $pre_ctx = "$1$2"; my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); @@ -2744,7 +2744,7 @@ sub process { } # Check relative indent for conditionals and blocks. - if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { + if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { ($stat, $cond, $line_nr_next, $remain_next, $off_next) = ctx_statement_block($linenr, $realcnt, 0) if (!defined $stat); -- cgit v1.2.3 From 3f7bc4e1fcfab05f3e8b49134cfb3e16b8876aae Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:18 -0700 Subject: checkpatch: add short int to c variable types short int is one of the 6.7.2 c90 types. Find it appropriately. This fixes a defect in checkpatch where it suggests that a line break after declaration is required using an input like: int foo; short int bar; Without this change, it warns on the short int line. Signed-off-by: Joe Perches Reported-by: Hartley Sweeten Acked-by: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index dc72a9b3172d..c647caab913c 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -356,6 +356,7 @@ our $signature_tags = qr{(?xi: our @typeList = ( qr{void}, qr{(?:unsigned\s+)?char}, + qr{(?:unsigned\s+)?short\s+int}, qr{(?:unsigned\s+)?short}, qr{(?:unsigned\s+)?int}, qr{(?:unsigned\s+)?long}, -- cgit v1.2.3 From 0c773d9d66684aefd919c4b4550fe16003c54c0e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:20 -0700 Subject: checkpatch: add signed generic types Current generic types are unsigned or unspecified. Add signed to the types. Reorder the types to find the longest match first. Signed-off-by: Joe Perches Acked-by: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index c647caab913c..c10befa118a5 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -355,15 +355,15 @@ our $signature_tags = qr{(?xi: our @typeList = ( qr{void}, - qr{(?:unsigned\s+)?char}, - qr{(?:unsigned\s+)?short\s+int}, - qr{(?:unsigned\s+)?short}, - qr{(?:unsigned\s+)?int}, - qr{(?:unsigned\s+)?long}, - qr{(?:unsigned\s+)?long\s+int}, - qr{(?:unsigned\s+)?long\s+long}, - qr{(?:unsigned\s+)?long\s+long\s+int}, - qr{unsigned}, + qr{(?:(?:un)?signed\s+)?char}, + qr{(?:(?:un)?signed\s+)?short\s+int}, + qr{(?:(?:un)?signed\s+)?short}, + qr{(?:(?:un)?signed\s+)?int}, + qr{(?:(?:un)?signed\s+)?long\s+int}, + qr{(?:(?:un)?signed\s+)?long\s+long\s+int}, + qr{(?:(?:un)?signed\s+)?long\s+long}, + qr{(?:(?:un)?signed\s+)?long}, + qr{(?:un)?signed}, qr{float}, qr{double}, qr{bool}, -- cgit v1.2.3 From 1813087dbc54ff1485bcc84b66d34052eaf23387 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:22 -0700 Subject: checkpatch: add test for native c90 types in unusual order c90 section "6.7.2 Type Specifiers" says: "type specifiers may occur in any order" That means that: short int is the same as int short unsigned short int is the same as int unsigned short etc... checkpatch currently parses only a subset of these allowed types. For instance: "unsigned short" and "signed short" are found by checkpatch as a specific type, but none of the or "int short" or "int signed short" variants are found. Add another table for the "kernel style misordered" variants. Add this misordered table to the findable types. Warn when the misordered style is used. This improves the "Missing a blank line after declarations" test as it depends on the correct parsing of the $Declare variable which looks for "$Type $Ident;" (ie: declarations like "int foo;"). Signed-off-by: Joe Perches Acked-by: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index c10befa118a5..10384cf40691 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -309,9 +309,12 @@ our $Operators = qr{ our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; our $NonptrType; +our $NonptrTypeMisordered; our $NonptrTypeWithAttr; our $Type; +our $TypeMisordered; our $Declare; +our $DeclareMisordered; our $NON_ASCII_UTF8 = qr{ [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte @@ -353,6 +356,25 @@ our $signature_tags = qr{(?xi: Cc: )}; +our @typeListMisordered = ( + qr{char\s+(?:un)?signed}, + qr{int\s+(?:(?:un)?signed\s+)?short\s}, + qr{int\s+short(?:\s+(?:un)?signed)}, + qr{short\s+int(?:\s+(?:un)?signed)}, + qr{(?:un)?signed\s+int\s+short}, + qr{short\s+(?:un)?signed}, + qr{long\s+int\s+(?:un)?signed}, + qr{int\s+long\s+(?:un)?signed}, + qr{long\s+(?:un)?signed\s+int}, + qr{int\s+(?:un)?signed\s+long}, + qr{int\s+(?:un)?signed}, + qr{int\s+long\s+long\s+(?:un)?signed}, + qr{long\s+long\s+int\s+(?:un)?signed}, + qr{long\s+long\s+(?:un)?signed\s+int}, + qr{long\s+long\s+(?:un)?signed}, + qr{long\s+(?:un)?signed}, +); + our @typeList = ( qr{void}, qr{(?:(?:un)?signed\s+)?char}, @@ -373,6 +395,7 @@ our @typeList = ( qr{${Ident}_t}, qr{${Ident}_handler}, qr{${Ident}_handler_fn}, + @typeListMisordered, ); our @typeListWithAttr = ( @typeList, @@ -414,6 +437,7 @@ our $allowed_asm_includes = qr{(?x: sub build_types { my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)"; my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)"; + my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)"; my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; $NonptrType = qr{ @@ -425,6 +449,13 @@ sub build_types { ) (?:\s+$Modifier|\s+const)* }x; + $NonptrTypeMisordered = qr{ + (?:$Modifier\s+|const\s+)* + (?: + (?:${Misordered}\b) + ) + (?:\s+$Modifier|\s+const)* + }x; $NonptrTypeWithAttr = qr{ (?:$Modifier\s+|const\s+)* (?: @@ -439,7 +470,13 @@ sub build_types { (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? (?:\s+$Inline|\s+$Modifier)* }x; + $TypeMisordered = qr{ + $NonptrTypeMisordered + (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? + (?:\s+$Inline|\s+$Modifier)* + }x; $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; + $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered}; } build_types(); @@ -2987,6 +3024,13 @@ sub process { } } +# check for misordered declarations of char/short/int/long with signed/unsigned + while ($sline =~ m{(\b$TypeMisordered\b)}g) { + my $tmp = trim($1); + WARN("MISORDERED_TYPE", + "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $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", -- cgit v1.2.3 From e81f239b4db2ad6c4b029ed92f0222601ce42abe Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:25 -0700 Subject: checkpatch: fix false positive MISSING_BREAK warnings with --file Using --file mode can give false positives with MISSING_BREAK fall-through warnings on simple but long multiple consecutive case statements. Look for all lines before a case statement for a switch or a statement when using --file mode. Fix a misspelling of preceded while there. Signed-off-by: Joe Perches Reported-by: Lee Jones Acked-by: Lee Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 10384cf40691..a0880ede3db9 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4811,13 +4811,13 @@ sub process { } } -# check for case / default statements not preceeded by break/fallthrough/switch +# check for case / default statements not preceded by break/fallthrough/switch if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) { my $has_break = 0; my $has_statement = 0; my $count = 0; my $prevline = $linenr; - while ($prevline > 1 && $count < 3 && !$has_break) { + while ($prevline > 1 && ($file || $count < 3) && !$has_break) { $prevline--; my $rline = $rawlines[$prevline - 1]; my $fline = $lines[$prevline - 1]; -- cgit v1.2.3 From 308cc8d8f0deab2c5a5162316277ced556acc71f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:27 -0700 Subject: checkpatch: fix false positives for --strict "space after cast" test Commit 89da401f6cff ("checkpatch: improve "no space after cast" test") in -next improved the cast test for non pointer types, but also introduced false positives for some types of static inlines. Add a test for an open brace to the exclusions to avoid these false positives. Signed-off-by: Joe Perches Reported-by: Hartley Sweeten Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index a0880ede3db9..9f14bf928cc7 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2456,7 +2456,7 @@ sub process { } } - if ($line =~ /^\+.*\(\s*$Type\s*\)[ \t]+(?!$Assignment|$Arithmetic)/) { + if ($line =~ /^\+.*\(\s*$Type\s*\)[ \t]+(?!$Assignment|$Arithmetic|{)/) { if (CHK("SPACING", "No space is necessary after a cast\n" . $herecurr) && $fix) { -- cgit v1.2.3 From ece9659f16e369d344fe4325d87fab3bb50d1fe2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 6 Aug 2014 16:11:29 -0700 Subject: checkpatch: warn on missing spaces in broken up quoted Checkpatch already complains when people break up quoted strings but it's still pretty common. One mistake that people often make is they leave out the space character between the two strings. This check adds around 450 new warnings and has a low rate of false positives. Signed-off-by: Dan Carpenter Cc: Andy Whitcroft Acked-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9f14bf928cc7..da74e65064d1 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2361,6 +2361,12 @@ sub process { "quoted string split across lines\n" . $hereprev); } +# check for missing a space in a string concatination + if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) { + WARN('MISSING_SPACE', + "break quoted strings at a space character\n" . $hereprev); + } + # check for spaces before a quoted newline if ($rawline =~ /^.*\".*\s\\n/) { if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", -- cgit v1.2.3 From f84223087402c45179be5e7060c5736c17a7b271 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 6 Aug 2014 16:11:31 -0700 Subject: checkpatch: update $declaration_macros, add uninitialized_var Using uninitialized_var reports a false positive for "Missing blank line after declarations". Fix it by adding uninitialized_var to the $declaration_macros exceptions list. Move the macro list after $Type is declared. Add optional prefixes to DECLARE_ and DEFINE_ macro declarations to allow forms like: MLX4_DECLARE_DOORBELL_LOCK Signed-off-by: Joe Perches Reported-by: Dotan Barak Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index da74e65064d1..31a731e06f50 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -423,11 +423,6 @@ foreach my $entry (@mode_permission_funcs) { $mode_perms_search .= $entry->[0]; } -our $declaration_macros = qr{(?x: - (?:$Storage\s+)?(?:DECLARE|DEFINE)_[A-Z]+\s*\(| - (?:$Storage\s+)?LIST_HEAD\s*\( -)}; - our $allowed_asm_includes = qr{(?x: irq| memory @@ -490,6 +485,12 @@ our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/; our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant)}; +our $declaration_macros = qr{(?x: + (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,2}\s*\(| + (?:$Storage\s+)?LIST_HEAD\s*\(| + (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\( +)}; + sub deparenthesize { my ($string) = @_; return "" if (!defined($string)); -- cgit v1.2.3 From 164f0d2efaaef835473e74b162eae750341d6a8c Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 7 Aug 2014 21:39:57 +0200 Subject: kbuild: Fix handling of backslashes in *.cmd files Commit c353acba ("kbuild: make: fix if_changed when command contains backslashes") attempted to handle backslashes in *.cmd files, but it only handled double backslashes for some reason. Changing make-cmd to also handle single backslashes fixes rebuilds with dash, but it breaks bash again. The reason is that the two shells disagree about the interpretation of backslash sequences in the echo builtin. The way out of this is to print the command with printf '%s\n'. While at it, document what the individual parts of make-cmd do and why. Reported-and-tested-by: Konstantin Khlebnikov Reviewed-by: Sam Ravnborg Signed-off-by: Michal Marek --- scripts/Kbuild.include | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 122f95c95869..8a9a4e1c7eab 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -215,11 +215,13 @@ else arg-check = $(if $(strip $(cmd_$@)),,1) endif -# >'< substitution is for echo to work, -# >$< substitution to preserve $ when reloading .cmd file -# note: when using inline perl scripts [perl -e '...$$t=1;...'] -# in $(cmd_xxx) double $$ your perl vars -make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))) +# Replace >$< with >$$< to preserve $ when reloading the .cmd file +# (needed for make) +# Replace >#< with >\#< to avoid starting a comment in the .cmd file +# (needed for make) +# Replace >'< with >'\''< to be able to enclose the whole string in '...' +# (needed for the shell) +make-cmd = $(call escsq,$(subst \#,\\\#,$(subst $$,$$$$,$(cmd_$(1))))) # Find any prerequisites that is newer than target or that does not exist. # PHONY targets skipped in both cases. @@ -230,7 +232,7 @@ any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ @set -e; \ $(echo-cmd) $(cmd_$(1)); \ - echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) + printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) # Execute the command and also postprocess generated .d dependencies file. if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ -- cgit v1.2.3 From 791dfeb49519f18a6efea4619f5678457f1532ff Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Fri, 8 Aug 2014 14:23:29 -0700 Subject: scripts/coccinelle/free: add NULL test before freeing functions Warns or generates patch for NULL check before the following functions: kfree usb_free_urb debugfs_remove debugfs_remove_recursive Signed-off-by: Fabian Frederick Acked-by: Julia Lawall Cc: Gilles Muller Cc: Joe Perches Cc: Markus Elfring Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/coccinelle/free/ifnullfree.cocci | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 scripts/coccinelle/free/ifnullfree.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/free/ifnullfree.cocci b/scripts/coccinelle/free/ifnullfree.cocci new file mode 100644 index 000000000000..77ab43f30b8d --- /dev/null +++ b/scripts/coccinelle/free/ifnullfree.cocci @@ -0,0 +1,52 @@ +/// NULL check before some freeing functions is not needed. +/// +/// Based on checkpatch warning +/// "kfree(NULL) is safe this check is probably not required" +/// and kfreeaddr.cocci by Julia Lawall. +/// +/// Comments: - +/// Options: --no-includes --include-headers + +virtual patch +virtual org +virtual report +virtual context + +@r2 depends on patch@ +expression E; +@@ +- if (E) +( +- kfree(E); ++ kfree(E); +| +- debugfs_remove(E); ++ debugfs_remove(E); +| +- debugfs_remove_recursive(E); ++ debugfs_remove_recursive(E); +| +- usb_free_urb(E); ++ usb_free_urb(E); +) + +@r depends on context || report || org @ +expression E; +position p; +@@ + +* if (E) +* \(kfree@p\|debugfs_remove@p\|debugfs_remove_recursive@p\|usb_free_urb\)(E); + +@script:python depends on org@ +p << r.p; +@@ + +cocci.print_main("NULL check before that freeing function is not needed", p) + +@script:python depends on report@ +p << r.p; +@@ + +msg = "WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values." +coccilib.report.print_report(p[0], msg) -- cgit v1.2.3 From 45715f33d447ba878a3ca81673514785bb4dfe5a Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Fri, 8 Aug 2014 14:23:31 -0700 Subject: scripts/coccinelle/free/ifnullfree.cocci: add copyright information All coccinelle scripts have a copyright in the header. Signed-off-by: Fabian Frederick Suggested-by: Julia Lawall Acked-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/coccinelle/free/ifnullfree.cocci | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/coccinelle/free/ifnullfree.cocci b/scripts/coccinelle/free/ifnullfree.cocci index 77ab43f30b8d..a42d70bf88b3 100644 --- a/scripts/coccinelle/free/ifnullfree.cocci +++ b/scripts/coccinelle/free/ifnullfree.cocci @@ -4,8 +4,9 @@ /// "kfree(NULL) is safe this check is probably not required" /// and kfreeaddr.cocci by Julia Lawall. /// -/// Comments: - -/// Options: --no-includes --include-headers +// Copyright: (C) 2014 Fabian Frederick. GPLv2. +// Comments: - +// Options: --no-includes --include-headers virtual patch virtual org -- cgit v1.2.3 From c965526a82a62a97363ea7f3caae0e4a8a809bb9 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 8 Aug 2014 14:23:33 -0700 Subject: scripts/tags.sh: include compat_sys_* symbols in the generated tags Since the kernel now has a COMPAT_SYSCALL infrastructure via commit 468366138850 ("COMPAT_SYSCALL_DEFINE: infrastructure"), add the corresponding regex for generating compat_sys_* symbols in the tags files (similar to sys_*). Signed-off-by: Catalin Marinas Cc: Alexander Viro Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/tags.sh | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index e6b011fe1d0d..cbfd269a6011 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -168,6 +168,7 @@ exuberant() --extra=+f --c-kinds=+px \ --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ + --regex-c='/^COMPAT_SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/compat_sys_\1/' \ --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ @@ -231,6 +232,7 @@ emacs() all_target_sources | xargs $1 -a \ --regex='/^\(ENTRY\|_GLOBAL\)(\([^)]*\)).*/\2/' \ --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ + --regex='/^COMPAT_SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/compat_sys_\1/' \ --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \ --regex='/PAGEFLAG(\([^,)]*\).*/Page\1/' \ -- cgit v1.2.3 From fda9f9903be6c3b590472c175c514b0834bb3c83 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Fri, 8 Aug 2014 14:23:35 -0700 Subject: scripts/checkstack.pl: automatically handle 32-bit and 64-bit mode for ARCH=x86 This patch adds support for ARCH=x86 into checkstack. Commit ffee0de411fd ("x86: Default to ARCH=x86 to avoid overriding CONFIG_64BIT") had merged ARCH=i386 and ARCH=x86_64 into one ARCH=x86. checkstack.pl searches patterns of machine instructions which are usually used for allocating stack frames. checkstalk.pl needs either i386 or x86_64, x86 isn't enough: $ make checkstack objdump -d vmlinux $(find . -name '*.ko') | \ perl linux/scripts/checkstack.pl x86 wrong or unknown architecture "x86" Signed-off-by: Konstantin Khlebnikov Cc: David Woodhouse Cc: "H. Peter Anvin" Cc: Richard Weinberger Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkstack.pl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index c05d586b1fee..899b4230320e 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl @@ -52,14 +52,12 @@ my (@stack, $re, $dre, $x, $xs, $funcre); #8000008a: 20 1d sub sp,4 #80000ca8: fa cd 05 b0 sub sp,sp,1456 $re = qr/^.*sub.*sp.*,([0-9]{1,8})/o; - } elsif ($arch =~ /^i[3456]86$/) { + } elsif ($arch =~ /^x86(_64)?$/ || $arch =~ /^i[3456]86$/) { #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp - $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%esp$/o; - $dre = qr/^.*[as][du][db] (%.*),\%esp$/o; - } elsif ($arch eq 'x86_64') { - # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp - $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%rsp$/o; - $dre = qr/^.*[as][du][db] (\%.*),\%rsp$/o; + # or + # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp + $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%(e|r)sp$/o; + $dre = qr/^.*[as][du][db] (%.*),\%(e|r)sp$/o; } elsif ($arch eq 'ia64') { #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; -- cgit v1.2.3 From 8370edea81e321b8a976969753d6b2811e6d5ed6 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Fri, 8 Aug 2014 14:25:38 -0700 Subject: bin2c: move bin2c in scripts/basic This patch series does not do kernel signature verification yet. I plan to post another patch series for that. Now distributions are already signing PE/COFF bzImage with PKCS7 signature I plan to parse and verify those signatures. Primary goal of this patchset is to prepare groundwork so that kernel image can be signed and signatures be verified during kexec load. This should help with two things. - It should allow kexec/kdump on secureboot enabled machines. - In general it can help even without secureboot. By being able to verify kernel image signature in kexec, it should help with avoiding module signing restrictions. Matthew Garret showed how to boot into a custom kernel, modify first kernel's memory and then jump back to old kernel and bypass any policy one wants to. This patch (of 15): Kexec wants to use bin2c and it wants to use it really early in the build process. See arch/x86/purgatory/ code in later patches. So move bin2c in scripts/basic so that it can be built very early and be usable by arch/x86/purgatory/ Signed-off-by: Vivek Goyal Cc: Borislav Petkov Cc: Michael Kerrisk Cc: Yinghai Lu Cc: Eric Biederman Cc: H. Peter Anvin Cc: Matthew Garrett Cc: Greg Kroah-Hartman Cc: Dave Young Cc: WANG Chao Cc: Baoquan He Cc: Andy Lutomirski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/.gitignore | 1 - scripts/Makefile | 1 - scripts/basic/.gitignore | 1 + scripts/basic/Makefile | 1 + scripts/basic/bin2c.c | 35 +++++++++++++++++++++++++++++++++++ scripts/bin2c.c | 36 ------------------------------------ 6 files changed, 37 insertions(+), 38 deletions(-) create mode 100644 scripts/basic/bin2c.c delete mode 100644 scripts/bin2c.c (limited to 'scripts') diff --git a/scripts/.gitignore b/scripts/.gitignore index fb070fa1038f..5ecfe93f2028 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -4,7 +4,6 @@ conmakehash kallsyms pnmtologo -bin2c unifdef ihex2fw recordmcount diff --git a/scripts/Makefile b/scripts/Makefile index 890df5c6adfb..72902b5f2721 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -13,7 +13,6 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include hostprogs-$(CONFIG_KALLSYMS) += kallsyms hostprogs-$(CONFIG_LOGO) += pnmtologo hostprogs-$(CONFIG_VT) += conmakehash -hostprogs-$(CONFIG_IKCONFIG) += bin2c hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable hostprogs-$(CONFIG_ASN1) += asn1_compiler diff --git a/scripts/basic/.gitignore b/scripts/basic/.gitignore index a776371a3502..9528ec9e5adc 100644 --- a/scripts/basic/.gitignore +++ b/scripts/basic/.gitignore @@ -1 +1,2 @@ fixdep +bin2c diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile index 4fcef87bb875..afbc1cd69ac5 100644 --- a/scripts/basic/Makefile +++ b/scripts/basic/Makefile @@ -9,6 +9,7 @@ # fixdep: Used to generate dependency information during build process hostprogs-y := fixdep +hostprogs-$(CONFIG_IKCONFIG) += bin2c always := $(hostprogs-y) # fixdep is needed to compile other host programs diff --git a/scripts/basic/bin2c.c b/scripts/basic/bin2c.c new file mode 100644 index 000000000000..af187e695345 --- /dev/null +++ b/scripts/basic/bin2c.c @@ -0,0 +1,35 @@ +/* + * Unloved program to convert a binary on stdin to a C include on stdout + * + * Jan 1999 Matt Mackall + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#include + +int main(int argc, char *argv[]) +{ + int ch, total = 0; + + if (argc > 1) + printf("const char %s[] %s=\n", + argv[1], argc > 2 ? argv[2] : ""); + + do { + printf("\t\""); + while ((ch = getchar()) != EOF) { + total++; + printf("\\x%02x", ch); + if (total % 16 == 0) + break; + } + printf("\"\n"); + } while (ch != EOF); + + if (argc > 1) + printf("\t;\n\nconst int %s_size = %d;\n", argv[1], total); + + return 0; +} diff --git a/scripts/bin2c.c b/scripts/bin2c.c deleted file mode 100644 index 96dd2bcbb407..000000000000 --- a/scripts/bin2c.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Unloved program to convert a binary on stdin to a C include on stdout - * - * Jan 1999 Matt Mackall - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#include - -int main(int argc, char *argv[]) -{ - int ch, total=0; - - if (argc > 1) - printf("const char %s[] %s=\n", - argv[1], argc > 2 ? argv[2] : ""); - - do { - printf("\t\""); - while ((ch = getchar()) != EOF) - { - total++; - printf("\\x%02x",ch); - if (total % 16 == 0) - break; - } - printf("\"\n"); - } while (ch != EOF); - - if (argc > 1) - printf("\t;\n\nconst int %s_size = %d;\n", argv[1], total); - - return 0; -} -- cgit v1.2.3 From de5b56ba51f63973ceb5c184ee0855f0c8a13fc9 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Fri, 8 Aug 2014 14:25:41 -0700 Subject: kernel: build bin2c based on config option CONFIG_BUILD_BIN2C currently bin2c builds only if CONFIG_IKCONFIG=y. But bin2c will now be used by kexec too. So make it compilation dependent on CONFIG_BUILD_BIN2C and this config option can be selected by CONFIG_KEXEC and CONFIG_IKCONFIG. Signed-off-by: Vivek Goyal Cc: Borislav Petkov Cc: Michael Kerrisk Cc: Yinghai Lu Cc: Eric Biederman Cc: H. Peter Anvin Cc: Matthew Garrett Cc: Greg Kroah-Hartman Cc: Dave Young Cc: WANG Chao Cc: Baoquan He Cc: Andy Lutomirski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/basic/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile index afbc1cd69ac5..ec10d9345bc2 100644 --- a/scripts/basic/Makefile +++ b/scripts/basic/Makefile @@ -9,7 +9,7 @@ # fixdep: Used to generate dependency information during build process hostprogs-y := fixdep -hostprogs-$(CONFIG_IKCONFIG) += bin2c +hostprogs-$(CONFIG_BUILD_BIN2C) += bin2c always := $(hostprogs-y) # fixdep is needed to compile other host programs -- cgit v1.2.3 From 3aaefce10351fecab348f5e06857f44cafc61a62 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 6 Aug 2014 15:21:00 -0700 Subject: x86, platform, kconfig: move kvmconfig functionality to a helper The new mergeconfig helper makes it easier to add other partial configurations similar to kvmconfig. Architecture-independent portions of those partial configurations should go in kernel/configs/${name}.config, and architecture-dependent portions should go in arch/${arch}/configs/${name}.config. Based on a patch by Luis R. Rodriguez . Originally-Signed-off-by: Luis R. Rodriguez Modified to make the helper name more general than just virtualization, support architecture-dependent and architecture-independent partial configurations, move the helper and kvmconfig to scripts/kconfig/Makefile, and factor out more of the common file path. Signed-off-by: Josh Triplett --- scripts/kconfig/Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'scripts') diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 9c4d2412fb72..8083b94b45ee 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -104,6 +104,19 @@ endif %_defconfig: $(obj)/conf $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) +configfiles=$(wildcard $(srctree)/kernel/configs/$(1).config $(srctree)/arch/$(SRCARCH)/configs/$(1).config) + +define mergeconfig +$(if $(wildcard $(objtree)/.config),, $(error You need an existing .config for this target)) +$(if $(call configfiles,$(1)),, $(error No configuration exists for this target on this architecture)) +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m -O $(objtree) $(objtree)/.config $(call configfiles,$(1)) +$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig +endef + +PHONY += kvmconfig +kvmconfig: + $(call mergeconfig,kvm_guest) + # Help text used by make help help: @echo ' config - Update current config utilising a line-oriented program' @@ -124,6 +137,7 @@ help: @echo ' randconfig - New config with random answer to all options' @echo ' listnewconfig - List new options' @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value' + @echo ' kvmconfig - Enable additional options for guest kernel support' # lxdialog stuff check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh -- cgit v1.2.3 From 0da1d4a0b9516adb2acc4841e9f6da6618f47f4e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 8 Aug 2014 16:25:47 -0700 Subject: x86: Add "make tinyconfig" to configure the tiniest possible kernel Since commit 5d2acfc7b974bbd3858b4dd3f2cdc6362dd8843a ("kconfig: make allnoconfig disable options behind EMBEDDED and EXPERT") in 3.15-rc1, "make allnoconfig" disables every possible config option. However, a few configuration options (CC_OPTIMIZE_FOR_SIZE, OPTIMIZE_INLINING) produce a smaller kernel when turned on, and a few choices exist (compression, highmem, allocator) for which a non-default option produces a smaller kernel. Add a "tinyconfig" option, which starts from allnoconfig and then sets these options to configure the tiniest possible kernel. This provides a better baseline for embedded systems or efforts to reduce kernel size. Signed-off-by: Josh Triplett --- scripts/kconfig/Makefile | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'scripts') diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 8083b94b45ee..ebf40f6edb4d 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -117,6 +117,10 @@ PHONY += kvmconfig kvmconfig: $(call mergeconfig,kvm_guest) +PHONY += tinyconfig +tinyconfig: allnoconfig + $(call mergeconfig,tiny) + # Help text used by make help help: @echo ' config - Update current config utilising a line-oriented program' @@ -138,6 +142,7 @@ help: @echo ' listnewconfig - List new options' @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value' @echo ' kvmconfig - Enable additional options for guest kernel support' + @echo ' tinyconfig - Configure the tiniest possible kernel' # lxdialog stuff check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh -- cgit v1.2.3 From b8432c6fc12bdf4a6921e1640d3ead23fcd04c10 Mon Sep 17 00:00:00 2001 From: Todd E Brandt Date: Fri, 8 Aug 2014 09:11:59 -0700 Subject: PM / tools: analyze_suspend.py: update to v3.0 Update of analyze_suspend.py to v3.0 New features include back-2-back suspend testing, device filters to reduce the html size, the inclusion of device_prepare and device_complete callbacks, a usb topography list, and the ability to control USB device autosuspend. UI upgrades include a device detail window and mini-timeline, the addition of a suspend_prepare and resume_complete phase to the timeline which includes the associated device callbacks, automatic highlight of related callbacks, and general color and name changes for better reability. The new version relies on two trace point patches that are already in the kernel: enable_trace_events_suspend_resume.patch enable_trace_events_device_pm_callback.patch It has legacy support for older kernels without these trace events, but when available the tool processes the ftrace output alone (dmesg has been deprecated as a tool input, and is only gathered for convenience). Link: https://01.org/suspendresume/downloads/analyzesuspend-v3.0 Signed-off-by: Todd Brandt Signed-off-by: Rafael J. Wysocki --- scripts/analyze_suspend.py | 3817 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 2981 insertions(+), 836 deletions(-) (limited to 'scripts') diff --git a/scripts/analyze_suspend.py b/scripts/analyze_suspend.py index 4f2cc12dc7c7..93e1fd40f430 100755 --- a/scripts/analyze_suspend.py +++ b/scripts/analyze_suspend.py @@ -36,146 +36,392 @@ # CONFIG_FUNCTION_TRACER=y # CONFIG_FUNCTION_GRAPH_TRACER=y # +# For kernel versions older than 3.15: # The following additional kernel parameters are required: # (e.g. in file /etc/default/grub) # GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..." # +# ----------------- LIBRARIES -------------------- + import sys import time import os import string import re -import array import platform -import datetime +from datetime import datetime import struct -# -- classes -- +# ----------------- CLASSES -------------------- +# Class: SystemValues +# Description: +# A global, single-instance container used to +# store system values and test parameters class SystemValues: - testdir = "." - tpath = "/sys/kernel/debug/tracing/" - mempath = "/dev/mem" - powerfile = "/sys/power/state" - suspendmode = "mem" - prefix = "test" - teststamp = "" - dmesgfile = "" - ftracefile = "" - htmlfile = "" + version = 3.0 + verbose = False + testdir = '.' + tpath = '/sys/kernel/debug/tracing/' + fpdtpath = '/sys/firmware/acpi/tables/FPDT' + epath = '/sys/kernel/debug/tracing/events/power/' + traceevents = [ + 'suspend_resume', + 'device_pm_callback_end', + 'device_pm_callback_start' + ] + modename = { + 'freeze': 'Suspend-To-Idle (S0)', + 'standby': 'Power-On Suspend (S1)', + 'mem': 'Suspend-to-RAM (S3)', + 'disk': 'Suspend-to-disk (S4)' + } + mempath = '/dev/mem' + powerfile = '/sys/power/state' + suspendmode = 'mem' + hostname = 'localhost' + prefix = 'test' + teststamp = '' + dmesgfile = '' + ftracefile = '' + htmlfile = '' rtcwake = False + rtcwaketime = 10 + rtcpath = '' + android = False + adb = 'adb' + devicefilter = [] + stamp = 0 + execcount = 1 + x2delay = 0 + usecallgraph = False + usetraceevents = False + usetraceeventsonly = False + notestrun = False + altdevname = dict() + postresumetime = 0 + tracertypefmt = '# tracer: (?P.*)' + firmwarefmt = '# fwsuspend (?P[0-9]*) fwresume (?P[0-9]*)$' + postresumefmt = '# post resume time (?P[0-9]*)$' + stampfmt = '# suspend-(?P[0-9]{2})(?P[0-9]{2})(?P[0-9]{2})-'+\ + '(?P[0-9]{2})(?P[0-9]{2})(?P[0-9]{2})'+\ + ' (?P.*) (?P.*) (?P.*)$' + def __init__(self): + self.hostname = platform.node() + if(self.hostname == ''): + self.hostname = 'localhost' + rtc = "rtc0" + if os.path.exists('/dev/rtc'): + rtc = os.readlink('/dev/rtc') + rtc = '/sys/class/rtc/'+rtc + if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \ + os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'): + self.rtcpath = rtc def setOutputFile(self): - if((self.htmlfile == "") and (self.dmesgfile != "")): - m = re.match(r"(?P.*)_dmesg\.txt$", self.dmesgfile) + if((self.htmlfile == '') and (self.dmesgfile != '')): + m = re.match('(?P.*)_dmesg\.txt$', self.dmesgfile) if(m): - self.htmlfile = m.group("name")+".html" - if((self.htmlfile == "") and (self.ftracefile != "")): - m = re.match(r"(?P.*)_ftrace\.txt$", self.ftracefile) + self.htmlfile = m.group('name')+'.html' + if((self.htmlfile == '') and (self.ftracefile != '')): + m = re.match('(?P.*)_ftrace\.txt$', self.ftracefile) if(m): - self.htmlfile = m.group("name")+".html" - if(self.htmlfile == ""): - self.htmlfile = "output.html" - def initTestOutput(self): - hostname = platform.node() - if(hostname != ""): - self.prefix = hostname - v = os.popen("cat /proc/version").read().strip() - kver = string.split(v)[2] - self.testdir = os.popen("date \"+suspend-%m%d%y-%H%M%S\"").read().strip() - self.teststamp = "# "+self.testdir+" "+self.prefix+" "+self.suspendmode+" "+kver - self.dmesgfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_dmesg.txt" - self.ftracefile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_ftrace.txt" - self.htmlfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+".html" + self.htmlfile = m.group('name')+'.html' + if(self.htmlfile == ''): + self.htmlfile = 'output.html' + def initTestOutput(self, subdir): + if(not self.android): + self.prefix = self.hostname + v = open('/proc/version', 'r').read().strip() + kver = string.split(v)[2] + else: + self.prefix = 'android' + v = os.popen(self.adb+' shell cat /proc/version').read().strip() + kver = string.split(v)[2] + testtime = datetime.now().strftime('suspend-%m%d%y-%H%M%S') + if(subdir != "."): + self.testdir = subdir+"/"+testtime + else: + self.testdir = testtime + self.teststamp = \ + '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver + self.dmesgfile = \ + self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt' + self.ftracefile = \ + self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt' + self.htmlfile = \ + self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html' os.mkdir(self.testdir) + def setDeviceFilter(self, devnames): + self.devicefilter = string.split(devnames) + def rtcWakeAlarm(self): + os.system('echo 0 > '+self.rtcpath+'/wakealarm') + outD = open(self.rtcpath+'/date', 'r').read().strip() + outT = open(self.rtcpath+'/time', 'r').read().strip() + mD = re.match('^(?P[0-9]*)-(?P[0-9]*)-(?P[0-9]*)', outD) + mT = re.match('^(?P[0-9]*):(?P[0-9]*):(?P[0-9]*)', outT) + if(mD and mT): + # get the current time from hardware + utcoffset = int((datetime.now() - datetime.utcnow()).total_seconds()) + dt = datetime(\ + int(mD.group('y')), int(mD.group('m')), int(mD.group('d')), + int(mT.group('h')), int(mT.group('m')), int(mT.group('s'))) + nowtime = int(dt.strftime('%s')) + utcoffset + else: + # if hardware time fails, use the software time + nowtime = int(datetime.now().strftime('%s')) + alarm = nowtime + self.rtcwaketime + os.system('echo %d > %s/wakealarm' % (alarm, self.rtcpath)) +sysvals = SystemValues() + +# Class: DeviceNode +# Description: +# A container used to create a device hierachy, with a single root node +# and a tree of child nodes. Used by Data.deviceTopology() +class DeviceNode: + name = '' + children = 0 + depth = 0 + def __init__(self, nodename, nodedepth): + self.name = nodename + self.children = [] + self.depth = nodedepth + +# Class: Data +# Description: +# The primary container for suspend/resume test data. There is one for +# each test run. The data is organized into a cronological hierarchy: +# Data.dmesg { +# root structure, started as dmesg & ftrace, but now only ftrace +# contents: times for suspend start/end, resume start/end, fwdata +# phases { +# 10 sequential, non-overlapping phases of S/R +# contents: times for phase start/end, order/color data for html +# devlist { +# device callback or action list for this phase +# device { +# a single device callback or generic action +# contents: start/stop times, pid/cpu/driver info +# parents/children, html id for timeline/callgraph +# optionally includes an ftrace callgraph +# optionally includes intradev trace events +# } +# } +# } +# } +# class Data: - altdevname = dict() - usedmesg = False - useftrace = False - notestrun = False - verbose = False - phases = [] - dmesg = {} # root data structure - start = 0.0 - end = 0.0 - stamp = {'time': "", 'host': "", 'mode': ""} - id = 0 - tSuspended = 0.0 - fwValid = False - fwSuspend = 0 - fwResume = 0 - def initialize(self): - self.dmesg = { # dmesg log data - 'suspend_general': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "#CCFFCC", 'order': 0}, - 'suspend_early': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "green", 'order': 1}, + dmesg = {} # root data structure + phases = [] # ordered list of phases + start = 0.0 # test start + end = 0.0 # test end + tSuspended = 0.0 # low-level suspend start + tResumed = 0.0 # low-level resume start + tLow = 0.0 # time spent in low-level suspend (standby/freeze) + fwValid = False # is firmware data available + fwSuspend = 0 # time spent in firmware suspend + fwResume = 0 # time spent in firmware resume + dmesgtext = [] # dmesg text file in memory + testnumber = 0 + idstr = '' + html_device_id = 0 + stamp = 0 + outfile = '' + def __init__(self, num): + idchar = 'abcdefghijklmnopqrstuvwxyz' + self.testnumber = num + self.idstr = idchar[num] + self.dmesgtext = [] + self.phases = [] + self.dmesg = { # fixed list of 10 phases + 'suspend_prepare': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#CCFFCC', 'order': 0}, + 'suspend': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#88FF88', 'order': 1}, + 'suspend_late': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#00AA00', 'order': 2}, 'suspend_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "#00FFFF", 'order': 2}, - 'suspend_cpu': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "blue", 'order': 3}, - 'resume_cpu': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "red", 'order': 4}, + 'row': 0, 'color': '#008888', 'order': 3}, + 'suspend_machine': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#0000FF', 'order': 4}, + 'resume_machine': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#FF0000', 'order': 5}, 'resume_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "orange", 'order': 5}, + 'row': 0, 'color': '#FF9900', 'order': 6}, 'resume_early': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "yellow", 'order': 6}, - 'resume_general': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "#FFFFCC", 'order': 7} + 'row': 0, 'color': '#FFCC00', 'order': 7}, + 'resume': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#FFFF88', 'order': 8}, + 'resume_complete': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#FFFFCC', 'order': 9} } self.phases = self.sortedPhases() - def normalizeTime(self): - tSus = tRes = self.tSuspended - if self.fwValid: - tSus -= -self.fwSuspend / 1000000000.0 - tRes -= self.fwResume / 1000000000.0 - self.tSuspended = 0.0 - self.start -= tSus - self.end -= tRes + def getStart(self): + return self.dmesg[self.phases[0]]['start'] + def setStart(self, time): + self.start = time + self.dmesg[self.phases[0]]['start'] = time + def getEnd(self): + return self.dmesg[self.phases[-1]]['end'] + def setEnd(self, time): + self.end = time + self.dmesg[self.phases[-1]]['end'] = time + def isTraceEventOutsideDeviceCalls(self, pid, time): + for phase in self.phases: + list = self.dmesg[phase]['list'] + for dev in list: + d = list[dev] + if(d['pid'] == pid and time >= d['start'] and + time <= d['end']): + return False + return True + def addIntraDevTraceEvent(self, action, name, pid, time): + if(action == 'mutex_lock_try'): + color = 'red' + elif(action == 'mutex_lock_pass'): + color = 'green' + elif(action == 'mutex_unlock'): + color = 'blue' + else: + # create separate colors based on the name + v1 = len(name)*10 % 256 + v2 = string.count(name, 'e')*100 % 256 + v3 = ord(name[0])*20 % 256 + color = '#%06X' % ((v1*0x10000) + (v2*0x100) + v3) + for phase in self.phases: + list = self.dmesg[phase]['list'] + for dev in list: + d = list[dev] + if(d['pid'] == pid and time >= d['start'] and + time <= d['end']): + e = TraceEvent(action, name, color, time) + if('traceevents' not in d): + d['traceevents'] = [] + d['traceevents'].append(e) + return d + break + return 0 + def capIntraDevTraceEvent(self, action, name, pid, time): + for phase in self.phases: + list = self.dmesg[phase]['list'] + for dev in list: + d = list[dev] + if(d['pid'] == pid and time >= d['start'] and + time <= d['end']): + if('traceevents' not in d): + return + for e in d['traceevents']: + if(e.action == action and + e.name == name and not e.ready): + e.length = time - e.time + e.ready = True + break + return + def trimTimeVal(self, t, t0, dT, left): + if left: + if(t > t0): + if(t - dT < t0): + return t0 + return t - dT + else: + return t + else: + if(t < t0 + dT): + if(t > t0): + return t0 + dT + return t + dT + else: + return t + def trimTime(self, t0, dT, left): + self.tSuspended = self.trimTimeVal(self.tSuspended, t0, dT, left) + self.tResumed = self.trimTimeVal(self.tResumed, t0, dT, left) + self.start = self.trimTimeVal(self.start, t0, dT, left) + self.end = self.trimTimeVal(self.end, t0, dT, left) for phase in self.phases: - zero = tRes - if "suspend" in phase: - zero = tSus p = self.dmesg[phase] - p['start'] -= zero - p['end'] -= zero + p['start'] = self.trimTimeVal(p['start'], t0, dT, left) + p['end'] = self.trimTimeVal(p['end'], t0, dT, left) list = p['list'] for name in list: d = list[name] - d['start'] -= zero - d['end'] -= zero + d['start'] = self.trimTimeVal(d['start'], t0, dT, left) + d['end'] = self.trimTimeVal(d['end'], t0, dT, left) if('ftrace' in d): cg = d['ftrace'] - cg.start -= zero - cg.end -= zero + cg.start = self.trimTimeVal(cg.start, t0, dT, left) + cg.end = self.trimTimeVal(cg.end, t0, dT, left) for line in cg.list: - line.time -= zero - if self.fwValid: - fws = -self.fwSuspend / 1000000000.0 - fwr = self.fwResume / 1000000000.0 - list = dict() - self.id += 1 - devid = "dc%d" % self.id - list["firmware-suspend"] = \ - {'start': fws, 'end': 0, 'pid': 0, 'par': "", - 'length': -fws, 'row': 0, 'id': devid }; - self.id += 1 - devid = "dc%d" % self.id - list["firmware-resume"] = \ - {'start': 0, 'end': fwr, 'pid': 0, 'par': "", - 'length': fwr, 'row': 0, 'id': devid }; - self.dmesg['BIOS'] = \ - {'list': list, 'start': fws, 'end': fwr, - 'row': 0, 'color': "purple", 'order': 4} - self.dmesg['resume_cpu']['order'] += 1 - self.dmesg['resume_noirq']['order'] += 1 - self.dmesg['resume_early']['order'] += 1 - self.dmesg['resume_general']['order'] += 1 - self.phases = self.sortedPhases() - def vprint(self, msg): - if(self.verbose): - print(msg) + line.time = self.trimTimeVal(line.time, t0, dT, left) + if('traceevents' in d): + for e in d['traceevents']: + e.time = self.trimTimeVal(e.time, t0, dT, left) + def normalizeTime(self, tZero): + # first trim out any standby or freeze clock time + if(self.tSuspended != self.tResumed): + if(self.tResumed > tZero): + self.trimTime(self.tSuspended, \ + self.tResumed-self.tSuspended, True) + else: + self.trimTime(self.tSuspended, \ + self.tResumed-self.tSuspended, False) + # shift the timeline so that tZero is the new 0 + self.tSuspended -= tZero + self.tResumed -= tZero + self.start -= tZero + self.end -= tZero + for phase in self.phases: + p = self.dmesg[phase] + p['start'] -= tZero + p['end'] -= tZero + list = p['list'] + for name in list: + d = list[name] + d['start'] -= tZero + d['end'] -= tZero + if('ftrace' in d): + cg = d['ftrace'] + cg.start -= tZero + cg.end -= tZero + for line in cg.list: + line.time -= tZero + if('traceevents' in d): + for e in d['traceevents']: + e.time -= tZero + def newPhaseWithSingleAction(self, phasename, devname, start, end, color): + for phase in self.phases: + self.dmesg[phase]['order'] += 1 + self.html_device_id += 1 + devid = '%s%d' % (self.idstr, self.html_device_id) + list = dict() + list[devname] = \ + {'start': start, 'end': end, 'pid': 0, 'par': '', + 'length': (end-start), 'row': 0, 'id': devid, 'drv': '' }; + self.dmesg[phasename] = \ + {'list': list, 'start': start, 'end': end, + 'row': 0, 'color': color, 'order': 0} + self.phases = self.sortedPhases() + def newPhase(self, phasename, start, end, color, order): + if(order < 0): + order = len(self.phases) + for phase in self.phases[order:]: + self.dmesg[phase]['order'] += 1 + if(order > 0): + p = self.phases[order-1] + self.dmesg[p]['end'] = start + if(order < len(self.phases)): + p = self.phases[order] + self.dmesg[p]['start'] = end + list = dict() + self.dmesg[phasename] = \ + {'list': list, 'start': start, 'end': end, + 'row': 0, 'color': color, 'order': order} + self.phases = self.sortedPhases() + def setPhase(self, phase, ktime, isbegin): + if(isbegin): + self.dmesg[phase]['start'] = ktime + else: + self.dmesg[phase]['end'] = ktime def dmesgSortVal(self, phase): return self.dmesg[phase]['order'] def sortedPhases(self): @@ -197,59 +443,180 @@ class Data: dev = phaselist[devname] if(dev['end'] < 0): dev['end'] = end - self.vprint("%s (%s): callback didn't return" % (devname, phase)) + vprint('%s (%s): callback didnt return' % (devname, phase)) + def deviceFilter(self, devicefilter): + # remove all by the relatives of the filter devnames + filter = [] + for phase in self.phases: + list = self.dmesg[phase]['list'] + for name in devicefilter: + dev = name + while(dev in list): + if(dev not in filter): + filter.append(dev) + dev = list[dev]['par'] + children = self.deviceDescendants(name, phase) + for dev in children: + if(dev not in filter): + filter.append(dev) + for phase in self.phases: + list = self.dmesg[phase]['list'] + rmlist = [] + for name in list: + pid = list[name]['pid'] + if(name not in filter and pid >= 0): + rmlist.append(name) + for name in rmlist: + del list[name] def fixupInitcallsThatDidntReturn(self): # if any calls never returned, clip them at system resume end for phase in self.phases: - self.fixupInitcalls(phase, self.dmesg['resume_general']['end']) - if(phase == "resume_general"): - break - def newAction(self, phase, name, pid, parent, start, end): - self.id += 1 - devid = "dc%d" % self.id + self.fixupInitcalls(phase, self.getEnd()) + def newActionGlobal(self, name, start, end): + # which phase is this device callback or action "in" + targetphase = "none" + overlap = 0.0 + for phase in self.phases: + pstart = self.dmesg[phase]['start'] + pend = self.dmesg[phase]['end'] + o = max(0, min(end, pend) - max(start, pstart)) + if(o > overlap): + targetphase = phase + overlap = o + if targetphase in self.phases: + self.newAction(targetphase, name, -1, '', start, end, '') + return True + return False + def newAction(self, phase, name, pid, parent, start, end, drv): + # new device callback for a specific phase + self.html_device_id += 1 + devid = '%s%d' % (self.idstr, self.html_device_id) list = self.dmesg[phase]['list'] length = -1.0 if(start >= 0 and end >= 0): length = end - start list[name] = {'start': start, 'end': end, 'pid': pid, 'par': parent, - 'length': length, 'row': 0, 'id': devid } + 'length': length, 'row': 0, 'id': devid, 'drv': drv } def deviceIDs(self, devlist, phase): idlist = [] - for p in self.phases: - if(p[0] != phase[0]): - continue - list = data.dmesg[p]['list'] - for devname in list: - if devname in devlist: - idlist.append(list[devname]['id']) + list = self.dmesg[phase]['list'] + for devname in list: + if devname in devlist: + idlist.append(list[devname]['id']) return idlist def deviceParentID(self, devname, phase): - pdev = "" - pdevid = "" - for p in self.phases: - if(p[0] != phase[0]): - continue - list = data.dmesg[p]['list'] - if devname in list: - pdev = list[devname]['par'] - for p in self.phases: - if(p[0] != phase[0]): - continue - list = data.dmesg[p]['list'] - if pdev in list: - return list[pdev]['id'] + pdev = '' + pdevid = '' + list = self.dmesg[phase]['list'] + if devname in list: + pdev = list[devname]['par'] + if pdev in list: + return list[pdev]['id'] return pdev - def deviceChildrenIDs(self, devname, phase): + def deviceChildren(self, devname, phase): devlist = [] - for p in self.phases: - if(p[0] != phase[0]): - continue - list = data.dmesg[p]['list'] - for child in list: - if(list[child]['par'] == devname): - devlist.append(child) + list = self.dmesg[phase]['list'] + for child in list: + if(list[child]['par'] == devname): + devlist.append(child) + return devlist + def deviceDescendants(self, devname, phase): + children = self.deviceChildren(devname, phase) + family = children + for child in children: + family += self.deviceDescendants(child, phase) + return family + def deviceChildrenIDs(self, devname, phase): + devlist = self.deviceChildren(devname, phase) return self.deviceIDs(devlist, phase) - + def printDetails(self): + vprint(' test start: %f' % self.start) + for phase in self.phases: + dc = len(self.dmesg[phase]['list']) + vprint(' %16s: %f - %f (%d devices)' % (phase, \ + self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc)) + vprint(' test end: %f' % self.end) + def masterTopology(self, name, list, depth): + node = DeviceNode(name, depth) + for cname in list: + clist = self.deviceChildren(cname, 'resume') + cnode = self.masterTopology(cname, clist, depth+1) + node.children.append(cnode) + return node + def printTopology(self, node): + html = '' + if node.name: + info = '' + drv = '' + for phase in self.phases: + list = self.dmesg[phase]['list'] + if node.name in list: + s = list[node.name]['start'] + e = list[node.name]['end'] + if list[node.name]['drv']: + drv = ' {'+list[node.name]['drv']+'}' + info += ('
  • %s: %.3fms
  • ' % (phase, (e-s)*1000)) + html += '
  • '+node.name+drv+'' + if info: + html += '
      '+info+'
    ' + html += '
  • ' + if len(node.children) > 0: + html += '
      ' + for cnode in node.children: + html += self.printTopology(cnode) + html += '
    ' + return html + def rootDeviceList(self): + # list of devices graphed + real = [] + for phase in self.dmesg: + list = self.dmesg[phase]['list'] + for dev in list: + if list[dev]['pid'] >= 0 and dev not in real: + real.append(dev) + # list of top-most root devices + rootlist = [] + for phase in self.dmesg: + list = self.dmesg[phase]['list'] + for dev in list: + pdev = list[dev]['par'] + if(re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)): + continue + if pdev and pdev not in real and pdev not in rootlist: + rootlist.append(pdev) + return rootlist + def deviceTopology(self): + rootlist = self.rootDeviceList() + master = self.masterTopology('', rootlist, 0) + return self.printTopology(master) + +# Class: TraceEvent +# Description: +# A container for trace event data found in the ftrace file +class TraceEvent: + ready = False + name = '' + time = 0.0 + color = '#FFFFFF' + length = 0.0 + action = '' + def __init__(self, a, n, c, t): + self.action = a + self.name = n + self.color = c + self.time = t + +# Class: FTraceLine +# Description: +# A container for a single line of ftrace data. There are six basic types: +# callgraph line: +# call: " dpm_run_callback() {" +# return: " }" +# leaf: " dpm_run_callback();" +# trace event: +# tracing_mark_write: SUSPEND START or RESUME COMPLETE +# suspend_resume: phase or custom exec block data +# device_pm_callback: device callback info class FTraceLine: time = 0.0 length = 0.0 @@ -257,20 +624,33 @@ class FTraceLine: freturn = False fevent = False depth = 0 - name = "" + name = '' + type = '' def __init__(self, t, m, d): self.time = float(t) - # check to see if this is a trace event - em = re.match(r"^ *\/\* *(?P.*) \*\/ *$", m) - if(em): - self.name = em.group("msg") + # is this a trace event + if(d == 'traceevent' or re.match('^ *\/\* *(?P.*) \*\/ *$', m)): + if(d == 'traceevent'): + # nop format trace event + msg = m + else: + # function_graph format trace event + em = re.match('^ *\/\* *(?P.*) \*\/ *$', m) + msg = em.group('msg') + + emm = re.match('^(?P.*?): (?P.*)', msg) + if(emm): + self.name = emm.group('msg') + self.type = emm.group('call') + else: + self.name = msg self.fevent = True return # convert the duration to seconds if(d): self.length = float(d)/1000000 # the indentation determines the depth - match = re.match(r"^(?P *)(?P.*)$", m) + match = re.match('^(?P *)(?P.*)$', m) if(not match): return self.depth = self.getDepth(match.group('d')) @@ -280,7 +660,7 @@ class FTraceLine: self.freturn = True if(len(m) > 1): # includes comment with function name - match = re.match(r"^} *\/\* *(?P.*) *\*\/$", m) + match = re.match('^} *\/\* *(?P.*) *\*\/$', m) if(match): self.name = match.group('n') # function call @@ -288,13 +668,13 @@ class FTraceLine: self.fcall = True # function call with children if(m[-1] == '{'): - match = re.match(r"^(?P.*) *\(.*", m) + match = re.match('^(?P.*) *\(.*', m) if(match): self.name = match.group('n') # function call with no children (leaf) elif(m[-1] == ';'): self.freturn = True - match = re.match(r"^(?P.*) *\(.*", m) + match = re.match('^(?P.*) *\(.*', m) if(match): self.name = match.group('n') # something else (possibly a trace marker) @@ -302,7 +682,23 @@ class FTraceLine: self.name = m def getDepth(self, str): return len(str)/2 + def debugPrint(self, dev): + if(self.freturn and self.fcall): + print('%s -- %f (%02d): %s(); (%.3f us)' % (dev, self.time, \ + self.depth, self.name, self.length*1000000)) + elif(self.freturn): + print('%s -- %f (%02d): %s} (%.3f us)' % (dev, self.time, \ + self.depth, self.name, self.length*1000000)) + else: + print('%s -- %f (%02d): %s() { (%.3f us)' % (dev, self.time, \ + self.depth, self.name, self.length*1000000)) +# Class: FTraceCallGraph +# Description: +# A container for the ftrace callgraph of a single recursive function. +# This can be a dpm_run_callback, dpm_prepare, or dpm_complete callgraph +# Each instance is tied to a single device in a single phase, and is +# comprised of an ordered list of FTraceLine objects class FTraceCallGraph: start = -1.0 end = -1.0 @@ -327,24 +723,53 @@ class FTraceCallGraph: if(not self.invalid): self.setDepth(line) if(line.depth == 0 and line.freturn): + if(self.start < 0): + self.start = line.time self.end = line.time self.list.append(line) return True if(self.invalid): return False if(len(self.list) >= 1000000 or self.depth < 0): - first = self.list[0] - self.list = [] - self.list.append(first) - self.invalid = True - id = "task %s cpu %s" % (match.group("pid"), match.group("cpu")) - window = "(%f - %f)" % (self.start, line.time) - data.vprint("Too much data for "+id+" "+window+", ignoring this callback") - return False + if(len(self.list) > 0): + first = self.list[0] + self.list = [] + self.list.append(first) + self.invalid = True + if(not match): + return False + id = 'task %s cpu %s' % (match.group('pid'), match.group('cpu')) + window = '(%f - %f)' % (self.start, line.time) + if(self.depth < 0): + print('Too much data for '+id+\ + ' (buffer overflow), ignoring this callback') + else: + print('Too much data for '+id+\ + ' '+window+', ignoring this callback') + return False self.list.append(line) if(self.start < 0): self.start = line.time return False + def slice(self, t0, tN): + minicg = FTraceCallGraph() + count = -1 + firstdepth = 0 + for l in self.list: + if(l.time < t0 or l.time > tN): + continue + if(count < 0): + if(not l.fcall or l.name == 'dev_driver_string'): + continue + firstdepth = l.depth + count = 0 + l.depth -= firstdepth + minicg.addLine(l, 0) + if((count == 0 and l.freturn and l.fcall) or + (count > 0 and l.depth <= 0)): + break + count += 1 + return minicg def sanityCheck(self): stack = dict() cnt = 0 @@ -353,7 +778,7 @@ class FTraceCallGraph: stack[l.depth] = l cnt += 1 elif(l.freturn and not l.fcall): - if(not stack[l.depth]): + if(l.depth not in stack): return False stack[l.depth].length = l.length stack[l.depth] = 0 @@ -363,40 +788,51 @@ class FTraceCallGraph: return True return False def debugPrint(self, filename): - if(filename == "stdout"): - print("[%f - %f]") % (self.start, self.end) + if(filename == 'stdout'): + print('[%f - %f]') % (self.start, self.end) for l in self.list: if(l.freturn and l.fcall): - print("%f (%02d): %s(); (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000)) + print('%f (%02d): %s(); (%.3f us)' % (l.time, \ + l.depth, l.name, l.length*1000000)) elif(l.freturn): - print("%f (%02d): %s} (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000)) + print('%f (%02d): %s} (%.3f us)' % (l.time, \ + l.depth, l.name, l.length*1000000)) else: - print("%f (%02d): %s() { (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000)) - print(" ") + print('%f (%02d): %s() { (%.3f us)' % (l.time, \ + l.depth, l.name, l.length*1000000)) + print(' ') else: fp = open(filename, 'w') print(filename) for l in self.list: if(l.freturn and l.fcall): - fp.write("%f (%02d): %s(); (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000)) + fp.write('%f (%02d): %s(); (%.3f us)\n' % (l.time, \ + l.depth, l.name, l.length*1000000)) elif(l.freturn): - fp.write("%f (%02d): %s} (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000)) + fp.write('%f (%02d): %s} (%.3f us)\n' % (l.time, \ + l.depth, l.name, l.length*1000000)) else: - fp.write("%f (%02d): %s() { (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000)) + fp.write('%f (%02d): %s() { (%.3f us)\n' % (l.time, \ + l.depth, l.name, l.length*1000000)) fp.close() +# Class: Timeline +# Description: +# A container for a suspend/resume html timeline. In older versions +# of the script there were multiple timelines, but in the latest +# there is only one. class Timeline: html = {} - scaleH = 0.0 # height of the timescale row as a percent of the timeline height + scaleH = 0.0 # height of the row as a percent of the timeline height rowH = 0.0 # height of each row in percent of the timeline height row_height_pixels = 30 maxrows = 0 height = 0 def __init__(self): self.html = { - 'timeline': "", - 'legend': "", - 'scale': "" + 'timeline': '', + 'legend': '', + 'scale': '' } def setRows(self, rows): self.maxrows = int(rows) @@ -407,104 +843,261 @@ class Timeline: r = 1.0 self.rowH = (100.0 - self.scaleH)/r -# -- global objects -- +# Class: TestRun +# Description: +# A container for a suspend/resume test run. This is necessary as +# there could be more than one, and they need to be separate. +class TestRun: + ftrace_line_fmt_fg = \ + '^ *(?P