# (c) 2001, Dave Jones. (the file handling bit)
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
-# (c) 2008,2009, Andy Whitcroft <apw@canonical.com>
+# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
# Licensed under the terms of the GNU GPL License version 2
use strict;
my $P = $0;
$P =~ s@.*/@@g;
-my $V = '0.30';
+my $V = '0.31';
use Getopt::Long qw(:config no_auto_abbrev);
die "$@" if ($@);
}
+my $rpt_cleaners = 0;
+
if ($terse) {
$emacs = 1;
$quiet++;
# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
our $Attribute = qr{
const|
+ __percpu|
+ __nocast|
+ __safe|
+ __bitwise__|
+ __packed__|
+ __packed2__|
+ __naked|
+ __maybe_unused|
+ __always_unused|
+ __noreturn|
+ __used|
+ __cold|
+ __noclone|
+ __deprecated|
__read_mostly|
__kprobes|
__(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
our $logFunctions = qr{(?x:
printk|
- pr_(debug|dbg|vdbg|devel|info|warning|err|notice|alert|crit|emerg|cont)|
- (dev|netdev|netif)_(printk|dbg|vdbg|info|warn|err|notice|alert|crit|emerg|WARN)|
+ [a-z]+_(emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)|
WARN|
- panic
+ panic|
+ MODULE_[A-Z_]+
)};
our @typeList = (
$blk .= $rawlines[$line];
# Handle nested #if/#else.
- if ($rawlines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
+ if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
push(@stack, $level);
- } elsif ($rawlines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
+ } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
$level = $stack[$#stack - 1];
- } elsif ($rawlines[$line] =~ /^.\s*#\s*endif\b/) {
+ } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
$level = pop(@stack);
}
- foreach my $c (split(//, $rawlines[$line])) {
+ foreach my $c (split(//, $lines[$line])) {
##print "C<$c>L<$level><$open$close>O<$off>\n";
if ($off > 0) {
$off--;
$av_preprocessor = 0;
}
- } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) {
+ } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
+ print "CAST($1)\n" if ($dbg_values > 1);
+ push(@av_paren_type, $type);
+ $type = 'C';
+
+ } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
print "DECLARE($1)\n" if ($dbg_values > 1);
$type = 'T';
$here = "#$realline: " if ($file);
# extract the filename as it passes
- if ($line=~/^\+\+\+\s+(\S+)/) {
+ if ($line =~ /^diff --git.*?(\S+)$/) {
+ $realfile = $1;
+ $realfile =~ s@^([^/]*)/@@;
+
+ } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
$realfile = $1;
$realfile =~ s@^([^/]*)/@@;
$cnt_lines++ if ($realcnt != 0);
+# Check for incorrect file permissions
+ if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
+ my $permhere = $here . "FILE: $realfile\n";
+ if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
+ ERROR("do not set execute permissions for source files\n" . $permhere);
+ }
+ }
+
#check the patch for a signoff:
if ($line =~ /^\s*signed-off-by:/i) {
# This is a signoff, if ugly, so do not double report.
} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
ERROR("trailing whitespace\n" . $herevet);
+ $rpt_cleaners = 1;
}
# check for Kconfig help text having a real description
+# Only applies when adding the entry originally, after that we do not have
+# sufficient context to determine whether it is indeed long enough.
if ($realfile =~ /Kconfig/ &&
- $line =~ /\+?\s*(---)?help(---)?$/) {
+ $line =~ /\+\s*(?:---)?help(?:---)?$/) {
my $length = 0;
- for (my $l = $linenr; defined($lines[$l]); $l++) {
- my $f = $lines[$l];
+ my $cnt = $realcnt;
+ my $ln = $linenr + 1;
+ my $f;
+ my $is_end = 0;
+ while ($cnt > 0 && defined $lines[$ln - 1]) {
+ $f = $lines[$ln - 1];
+ $cnt-- if ($lines[$ln - 1] !~ /^-/);
+ $is_end = $lines[$ln - 1] =~ /^\+/;
+ $ln++;
+
+ next if ($f =~ /^-/);
+ $f =~ s/^.//;
$f =~ s/#.*//;
$f =~ s/^\s+//;
next if ($f =~ /^$/);
- last if ($f =~ /^\s*config\s/);
+ if ($f =~ /^\s*config\s/) {
+ $is_end = 1;
+ last;
+ }
$length++;
}
- WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($length < 4);
+ WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
+ #print "is_end<$is_end> length<$length>\n";
}
# check we are in a valid source file if not then ignore this hunk
#80 column limit
if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
$rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
- !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ ||
+ !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:|,|\)\s*;)\s*$/ ||
$line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
$length > 80)
{
$rawline =~ /^\+\s* \s*/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
ERROR("code indent should use tabs where possible\n" . $herevet);
+ $rpt_cleaners = 1;
}
# check for space before tabs.
}
# check for spaces at the beginning of a line.
- if ($rawline =~ /^\+ / && $rawline !~ /\+ +\*/) {
+# Exceptions:
+# 1) within comments
+# 2) indented preprocessor commands
+# 3) hanging labels
+ if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
- WARN("please, no space for starting a line, \
- excluding comments\n" . $herevet);
+ WARN("please, no spaces at the start of a line\n" . $herevet);
}
# check we are in a valid C source file if not then ignore this hunk
if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
ERROR("that open brace { should be on the previous line\n" .
- "$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+ "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
}
if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
$ctx =~ /\)\s*\;\s*$/ &&
my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
if ($nindent > $indent) {
WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
- "$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+ "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
}
}
}
!defined $suppress_export{$realline_next} &&
($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
$lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+ # Handle definitions which produce identifiers with
+ # a prefix:
+ # XXX(foo);
+ # EXPORT_SYMBOL(something_foo);
my $name = $1;
- if ($stat !~ /(?:
+ if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ &&
+ $name =~ /^${Ident}_$2/) {
+#print "FOO C name<$name>\n";
+ $suppress_export{$realline_next} = 1;
+
+ } elsif ($stat !~ /(?:
\n.}\s*$|
^.DEFINE_$Ident\(\Q$name\E\)|
^.DECLARE_$Ident\(\Q$name\E\)|
$herecurr);
}
+# check for static const char * arrays.
+ if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
+ WARN("static const char * array should probably be static const char * const\n" .
+ $herecurr);
+ }
+
+# check for static char foo[] = "bar" declarations.
+ if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
+ WARN("static char array declaration should probably be static const char\n" .
+ $herecurr);
+ }
+
+# check for declarations of struct pci_device_id
+ if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) {
+ WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr);
+ }
+
# check for new typedefs, only function parameters and sparse annotations
# make sense.
if ($line =~ /\btypedef\s/ &&
WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
}
+# check for uses of printk_ratelimit
+ if ($line =~ /\bprintk_ratelimit\s*\(/) {
+ WARN("Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
+ }
+
# printk should use KERN_* levels. Note that follow on printk's on the
# same line do not need a level, so we use the current block context
# to try and find and validate the current printk. In summary the current
-# printk includes all preceeding printk's which have no newline on the end.
+# printk includes all preceding printk's which have no newline on the end.
# we assume the first bad printk is the one to report.
if ($line =~ /\bprintk\((?!KERN_)\s*"/) {
my $ok = 0;
for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
#print "CHECK<$lines[$ln - 1]\n";
- # we have a preceeding printk if it ends
+ # we have a preceding printk if it ends
# with "\n" ignore it, else it is to blame
if ($lines[$ln - 1] =~ m{\bprintk\(}) {
if ($rawlines[$ln - 1] !~ m{\\n"}) {
ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
}
+# missing space after union, struct or enum definition
+ if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
+ WARN("missing space after $1 definition\n" . $herecurr);
+ }
+
# check for spacing round square brackets; allowed:
# 1. with a type on the left -- int [] a;
# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
for (my $n = 0; $n < $#elements; $n += 2) {
$off += length($elements[$n]);
- # Pick up the preceeding and succeeding characters.
+ # Pick up the preceding and succeeding characters.
my $ca = substr($opline, 0, $off);
my $cc = '';
if (length($opline) >= ($off + length($elements[$n + 1]))) {
my $value = $2;
# Flatten any parentheses
- $value =~ s/\)\(/\) \(/g;
+ $value =~ s/\(/ \(/g;
+ $value =~ s/\)/\) /g;
while ($value =~ s/\[[^\{\}]*\]/1/ ||
$value !~ /(?:$Ident|-?$Constant)\s*
$Compare\s*
(?:$Ident|-?$Constant)/x &&
$value =~ s/\([^\(\)]*\)/1/) {
}
-
- if ($value =~ /^(?:$Ident|-?$Constant)$/) {
+#print "value<$value>\n";
+ if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
ERROR("return is not a function, parentheses are not required\n" . $herecurr);
} elsif ($spacing !~ /\s+/) {
ERROR("space required before the open parenthesis '('\n" . $herecurr);
}
}
+# Return of what appears to be an errno should normally be -'ve
+ if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
+ my $name = $1;
+ if ($name ne 'EOF' && $name ne 'ERROR') {
+ WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
+ }
+ }
# Need a space before open parenthesis after if, while etc
if ($line=~/\b(if|while|for|switch)\(/) {
\.$Ident\s*=\s*|
^\"|\"$
}x;
- #print "REST<$rest> dstat<$dstat>\n";
- if ($rest ne '') {
+ #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
+ if ($rest ne '' && $rest ne ',') {
if ($rest !~ /while\s*\(/ &&
$dstat !~ /$exceptions/)
{
WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
}
-# SPIN_LOCK_UNLOCKED & RW_LOCK_UNLOCKED are deprecated
- if ($line =~ /\b(SPIN_LOCK_UNLOCKED|RW_LOCK_UNLOCKED)/) {
- ERROR("Use of $1 is deprecated: see Documentation/spinlocks.txt\n" . $herecurr);
- }
-
# warn about #if 0
if ($line =~ /^.\s*\#\s*if\s+0\b/) {
CHK("if this code is redundant consider removing it\n" .
WARN("plain inline is preferred over $1\n" . $herecurr);
}
+# Check for __attribute__ packed, prefer __packed
+ if ($line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
+ WARN("__packed is preferred over __attribute__((packed))\n" . $herecurr);
+ }
+
# check for sizeof(&)
if ($line =~ /\bsizeof\s*\(\s*\&/) {
WARN("sizeof(& should be avoided\n" . $herecurr);
}
+# check for line continuations in quoted strings with odd counts of "
+ if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) {
+ WARN("Avoid line continuations in quoted strings\n" . $herecurr);
+ }
+
# check for new externs in .c files.
if ($realfile =~ /\.c$/ && defined $stat &&
$stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
}
# check for pointless casting of kmalloc return
- if ($line =~ /\*\s*\)\s*k[czm]alloc\b/) {
+ if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) {
WARN("unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
}
+# check for multiple semicolons
+ if ($line =~ /;\s*;\s*$/) {
+ WARN("Statements terminations use 1 semicolon\n" . $herecurr);
+ }
+
# check for gcc specific __FUNCTION__
if ($line =~ /__FUNCTION__/) {
WARN("__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr);
}
-# check for semaphores used as mutexes
- if ($line =~ /^.\s*(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
- WARN("mutexes are preferred for single holder semaphores\n" . $herecurr);
- }
-# check for semaphores used as mutexes
- if ($line =~ /^.\s*init_MUTEX_LOCKED\s*\(/) {
+# check for semaphores initialized locked
+ if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
WARN("consider using a completion\n" . $herecurr);
}
-# recommend strict_strto* over simple_strto*
+# recommend kstrto* over simple_strto*
if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
- WARN("consider using strict_$1 in preference to simple_$1\n" . $herecurr);
+ WARN("consider using kstrto* in preference to simple_$1\n" . $herecurr);
}
# check for __initcall(), use device_initcall() explicitly please
if ($line =~ /^.\s*__initcall\s*\(/) {
ERROR("lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
}
}
+
+ if ($line =~ /debugfs_create_file.*S_IWUGO/ ||
+ $line =~ /DEVICE_ATTR.*S_IWUGO/ ) {
+ WARN("Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
+ }
+
+ # Check for memset with swapped arguments
+ if ($line =~ /memset.*\,(\ |)(0x|)0(\ |0|)\);/) {
+ ERROR("memset size is 3rd argument, not the second.\n" . $herecurr);
+ }
}
# If we have no input at all, then there is nothing to report on
print "\n" if ($quiet == 0);
}
+ if ($quiet == 0) {
+ # If there were whitespace errors which cleanpatch can fix
+ # then suggest that.
+ if ($rpt_cleaners) {
+ print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
+ print " scripts/cleanfile\n\n";
+ $rpt_cleaners = 0;
+ }
+ }
+
if ($clean == 1 && $quiet == 0) {
print "$vname has no obvious style problems and is ready for submission.\n"
}