Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f0a594c1c74fedbd838402e7372030311be8cc6e
Commit:     f0a594c1c74fedbd838402e7372030311be8cc6e
Parent:     4b8a8b812edd7067fffcc4a85b8aa3adae081535
Author:     Andy Whitcroft <[EMAIL PROTECTED]>
AuthorDate: Thu Jul 19 01:48:34 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Thu Jul 19 10:04:47 2007 -0700

    update checkpatch.pl to version 0.08
    
    This version brings a number of new checks, and a number of bug
    fixes.  Of note:
    
      - warnings for multiple assignments per line
      - warnings for multiple declarations per line
      - checks for single statement blocks with braces
    
    This patch includes an update for feature-removal-schedule.txt to
    better target checks.
    
    Andy Whitcroft (12):
          Version: 0.08
          only apply printk checks where there is a string literal
          allow suppression of errors for when no patch is found
          warn about multiple assignments
          warn on declaration of multiple variables
          check for kfree() with needless null check
          check for single statement braced blocks
          check for aggregate initialisation on the next line
          handle the => operator
          check for spaces between function name and open parenthesis
          move to explicit Check: entries in feature-removal-schedule.txt
          handle pointer attributes
    
    Signed-off-by: Andy Whitcroft <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 Documentation/feature-removal-schedule.txt |    3 +-
 scripts/checkpatch.pl                      |  175 +++++++++++++++++++++++-----
 2 files changed, 145 insertions(+), 33 deletions(-)

diff --git a/Documentation/feature-removal-schedule.txt 
b/Documentation/feature-removal-schedule.txt
index cff63be..a994154 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -51,6 +51,7 @@ Who:  David Miller <[EMAIL PROTECTED]>
 What:  Video4Linux API 1 ioctls and video_decoder.h from Video devices.
 When:  December 2006
 Files: include/linux/video_decoder.h
+Check: include/linux/video_decoder.h
 Why:   V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
        series. The old API have lots of drawbacks and don't provide enough
        means to work with all video and audio standards. The newer API is
@@ -84,7 +85,7 @@ Who:  Dominik Brodowski <[EMAIL PROTECTED]>
 What:  remove EXPORT_SYMBOL(kernel_thread)
 When:  August 2006
 Files: arch/*/kernel/*_ksyms.c
-Funcs: kernel_thread
+Check: kernel_thread
 Why:   kernel_thread is a low-level implementation detail.  Drivers should
         use the <linux/kthread.h> API instead which shields them from
        implementation details and provides a higherlevel interface that
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 25e20a2..73751ab 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -9,7 +9,7 @@ use strict;
 my $P = $0;
 $P =~ [EMAIL PROTECTED]/@@g;
 
-my $V = '0.07';
+my $V = '0.08';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -47,16 +47,14 @@ my $removal = 'Documentation/feature-removal-schedule.txt';
 if ($tree && -f $removal) {
        open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n";
        while (<REMOVE>) {
-               if (/^Files:\s+(.*\S)/) {
-                       for my $file (split(/[, ]+/, $1)) {
-                               if ($file =~ [EMAIL PROTECTED]/(.*)@) {
+               if (/^Check:\s+(.*\S)/) {
+                       for my $entry (split(/[, ]+/, $1)) {
+                               if ($entry =~ [EMAIL PROTECTED]/(.*)@) {
                                        push(@dep_includes, $1);
-                               }
-                       }
 
-               } elsif (/^Funcs:\s+(.*\S)/) {
-                       for my $func (split(/[, ]+/, $1)) {
-                               push(@dep_functions, $func);
+                               } elsif ($entry !~ m@/@) {
+                                       push(@dep_functions, $entry);
+                               }
                        }
                }
        }
@@ -153,7 +151,7 @@ sub sanitise_line {
 }
 
 sub ctx_block_get {
-       my ($linenr, $remain, $outer, $open, $close) = @_;
+       my ($linenr, $remain, $outer, $open, $close, $off) = @_;
        my $line;
        my $start = $linenr - 1;
        my $blk = '';
@@ -161,38 +159,58 @@ sub ctx_block_get {
        my @c;
        my @res = ();
 
+       my $level = 0;
        for ($line = $start; $remain > 0; $line++) {
                next if ($rawlines[$line] =~ /^-/);
                $remain--;
 
                $blk .= $rawlines[$line];
+               foreach my $c (split(//, $rawlines[$line])) {
+                       ##print "C<$c>L<$level><$open$close>O<$off>\n";
+                       if ($off > 0) {
+                               $off--;
+                               next;
+                       }
 
-               @o = ($blk =~ /$open/g);
-               @c = ($blk =~ /$close/g);
+                       if ($c eq $close && $level > 0) {
+                               $level--;
+                               last if ($level == 0);
+                       } elsif ($c eq $open) {
+                               $level++;
+                       }
+               }
 
-               if (!$outer || (scalar(@o) - scalar(@c)) == 1) {
+               if (!$outer || $level <= 1) {
                        push(@res, $rawlines[$line]);
                }
 
-               last if (scalar(@o) == scalar(@c));
+               last if ($level == 0);
        }
 
-       return @res;
+       return ($level, @res);
 }
 sub ctx_block_outer {
        my ($linenr, $remain) = @_;
 
-       return ctx_block_get($linenr, $remain, 1, '\{', '\}');
+       my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
+       return @r;
 }
 sub ctx_block {
        my ($linenr, $remain) = @_;
 
-       return ctx_block_get($linenr, $remain, 0, '\{', '\}');
+       my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
+       return @r;
 }
 sub ctx_statement {
+       my ($linenr, $remain, $off) = @_;
+
+       my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
+       return @r;
+}
+sub ctx_block_level {
        my ($linenr, $remain) = @_;
 
-       return ctx_block_get($linenr, $remain, 0, '\(', '\)');
+       return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
 }
 
 sub ctx_locate_comment {
@@ -246,16 +264,23 @@ sub cat_vet {
        return $vet;
 }
 
+my @report = ();
+sub report {
+       push(@report, $_[0]);
+}
+sub report_dump {
+       @report;
+}
 sub ERROR {
-       print "ERROR: $_[0]\n";
+       report("ERROR: $_[0]\n");
        our $clean = 0;
 }
 sub WARN {
-       print "WARNING: $_[0]\n";
+       report("WARNING: $_[0]\n");
        our $clean = 0;
 }
 sub CHK {
-       print "CHECK: $_[0]\n";
+       report("CHECK: $_[0]\n");
        our $clean = 0;
 }
 
@@ -318,7 +343,10 @@ sub process {
                                (?:\s*\*+\s*const|\s*\*+)?
                          }x;
        my $Declare     = qr{(?:$Storage\s+)?$Type};
-       my $Attribute   = qr{__read_mostly|__init|__initdata};
+       my $Attribute   = qr{const|__read_mostly|__init|__initdata|__meminit};
+
+       my $Member      = qr{->$Ident|\.$Ident|\[[^]]*\]};
+       my $Lval        = qr{$Ident(?:$Member)*};
 
        # Pre-scan the patch looking for any __setup documentation.
        my @setup_docs = ();
@@ -509,7 +537,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 !~ /^.#/) {
-                       my @ctx = ctx_statement($linenr, $realcnt);
+                       my @ctx = ctx_statement($linenr, $realcnt, 0);
                        my $ctx_ln = $linenr + $#ctx + 1;
                        my $ctx_cnt = $realcnt - $#ctx - 1;
                        my $ctx = join("\n", @ctx);
@@ -521,7 +549,7 @@ sub process {
                        ##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 
1]>";
 
                        if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 
1] =~ /^\+\s*{/) {
-                               ERROR("That { should be on the previous line\n" 
.
+                               ERROR("That open brace { should be on the 
previous line\n" .
                                        "$here\n$ctx\n$lines[$ctx_ln - 1]");
                        }
                }
@@ -535,6 +563,12 @@ sub process {
                        next;
                }
 
+# check for initialisation to aggregates open brace on the next line
+               if ($prevline =~ /$Declare\s*$Ident\s*=\s*$/ &&
+                   $line =~ /^.\s*{/) {
+                       ERROR("That open brace { should be on the previous 
line\n" . $hereprev);
+               }
+
 #
 # Checks which are anchored on the added line.
 #
@@ -570,8 +604,13 @@ sub process {
                        }
                }
 
+# check for external initialisers.
+               if ($line =~ /^.$Type\s*$Ident\s*=\s*(0|NULL);/) {
+                       ERROR("do not initialise externals to 0 or NULL\n" .
+                               $herecurr);
+               }
 # check for static initialisers.
-               if ($line=~/\s*static\s.*=\s+(0|NULL);/) {
+               if ($line =~ /\s*static\s.*=\s*(0|NULL);/) {
                        ERROR("do not initialise statics to 0 or NULL\n" .
                                $herecurr);
                }
@@ -593,11 +632,11 @@ sub process {
                        ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
                                $herecurr);
 
-               } elsif ($line =~ 
m{$NonptrType(\*+)(?:\s+const)?\s+[A-Za-z\d_]+}) {
+               } elsif ($line =~ 
m{$NonptrType(\*+)(?:\s+$Attribute)?\s+[A-Za-z\d_]+}) {
                        ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
                                $herecurr);
 
-               } elsif ($line =~ 
m{$NonptrType\s+(\*+)(?!\s+const)\s+[A-Za-z\d_]+}) {
+               } elsif ($line =~ 
m{$NonptrType\s+(\*+)(?!\s+$Attribute)\s+[A-Za-z\d_]+}) {
                        ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
                                $herecurr);
                }
@@ -614,7 +653,7 @@ sub process {
 # 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.
 # we assume the first bad printk is the one to report.
-               if ($line =~ /\bprintk\((?!KERN_)/) {
+               if ($line =~ /\bprintk\((?!KERN_)\s*"/) {
                        my $ok = 0;
                        for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
                                #print "CHECK<$lines[$ln - 1]\n";
@@ -639,6 +678,12 @@ sub process {
                        ERROR("open brace '{' following function declarations 
go on the next line\n" . $herecurr);
                }
 
+# check for spaces between functions and their parentheses.
+               if ($line =~ /($Ident)\s+\(/ &&
+                   $1 !~ /^(?:if|for|while|switch|return|volatile)$/ &&
+                   $line !~ /$Type\s+\(/ && $line !~ /^.\#\s*define\b/) {
+                       ERROR("no space between function name and open 
parenthesis '('\n" . $herecurr);
+               }
 # Check operator spacing.
                # Note we expand the line with the leading + as the real
                # line will be displayed with the leading + and the tabs
@@ -647,7 +692,7 @@ sub process {
                $opline = expand_tabs($opline);
                $opline =~ s/^./ /;
                if (!($line=~/\#\s*include/)) {
-                       my @elements = 
split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/,
 $opline);
+                       my @elements = 
split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|=>|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/,
 $opline);
                        my $off = 0;
                        for (my $n = 0; $n < $#elements; $n += 2) {
                                $off += length($elements[$n]);
@@ -773,6 +818,18 @@ sub process {
                        }
                }
 
+# check for multiple assignments
+               if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
+                       WARN("multiple assignments should be avoided\n" . 
$herecurr);
+               }
+
+# check for multiple declarations, allowing for a function declaration
+# continuation.
+               if ($line =~ 
/^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
+                   $line !~ 
/^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
+                       WARN("declaring multiple variables together should be 
avoided\n" . $herecurr);
+               }
+
 #need space before brace following if, while, etc
                if ($line =~ /\(.*\){/ || $line =~ /do{/) {
                        ERROR("need a space before the open brace '{'\n" . 
$herecurr);
@@ -847,13 +904,18 @@ sub process {
                        # or the one below.
                        my $ln = $linenr;
                        my $cnt = $realcnt;
+                       my $off = 0;
 
-                       # If the macro starts on the define line start there.
-                       if ($prevline !~ 
m{^.#\s*define\s*$Ident(?:\([^\)]*\))?\s*\\\s*$}) {
+                       # If the macro starts on the define line start
+                       # grabbing the statement after the identifier
+                       $prevline =~ 
m{^(.#\s*define\s*$Ident(?:\([^\)]*\))?\s*)(.*)\\\s*$};
+                       ##print "1<$1> 2<$2>\n";
+                       if ($2 ne '') {
+                               $off = length($1);
                                $ln--;
                                $cnt++;
                        }
-                       my @ctx = ctx_statement($ln, $cnt);
+                       my @ctx = ctx_statement($ln, $cnt, $off);
                        my $ctx_ln = $ln + $#ctx + 1;
                        my $ctx = join("\n", @ctx);
 
@@ -873,6 +935,44 @@ sub process {
                        }
                }
 
+# check for redundant bracing round if etc
+               if ($line =~ /\b(if|while|for|else)\b/) {
+                       # Locate the end of the opening statement.
+                       my @control = ctx_statement($linenr, $realcnt, 0);
+                       my $nr = $linenr + (scalar(@control) - 1);
+                       my $cnt = $realcnt - (scalar(@control) - 1);
+
+                       my $off = $realcnt - $cnt;
+                       #print "$off: line<$line>end<" . $lines[$nr - 1] . 
">\n";
+
+                       # If this is is a braced statement group check it
+                       if ($lines[$nr - 1] =~ /{\s*$/) {
+                               my ($lvl, @block) = ctx_block_level($nr, $cnt);
+
+                               my $stmt = join(' ', @block);
+                               $stmt =~ s/^[^{]*{//;
+                               $stmt =~ s/}[^}]*$//;
+
+                               #print "block<" . join(' ', @block) . "><" . 
scalar(@block) . ">\n";
+                               #print "stmt<$stmt>\n\n";
+
+                               # Count the ;'s if there is fewer than two
+                               # then there can only be one statement,
+                               # if there is a brace inside we cannot
+                               # trivially detect if its one statement.
+                               # Also nested if's often require braces to
+                               # disambiguate the else binding so shhh there.
+                               my @semi = ($stmt =~ /;/g);
+                               ##print "semi<" . scalar(@semi) . ">\n";
+                               if ($lvl == 0 && scalar(@semi) < 2 &&
+                                   $stmt !~ /{/ && $stmt !~ /\bif\b/) {
+                                       my $herectx = "$here\n" . join("\n", 
@control, @block[1 .. $#block]) . "\n";
+                                       shift(@block);
+                                       ERROR("braces {} are not necessary for 
single statement blocks\n" . $herectx);
+                               }
+                       }
+               }
+
 # don't include deprecated include files (uses RAW line)
                for my $inc (@dep_includes) {
                        if ($rawline =~ [EMAIL PROTECTED]<$inc>@) {
@@ -898,6 +998,14 @@ sub process {
                                $herecurr);
                }
 
+# check for needless kfree() checks
+               if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
+                       my $expr = $1;
+                       if ($line =~ /\bkfree\(\Q$expr\E\);/) {
+                               WARN("kfree(NULL) is safe this check is 
probabally not required\n" . $hereprev);
+                       }
+               }
+
 # warn about #ifdefs in C files
 #              if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
 #                      print "#ifdef in C files should be avoided\n";
@@ -952,6 +1060,9 @@ sub process {
                ERROR("Missing Signed-off-by: line(s)\n");
        }
 
+       if ($clean == 0 && ($chk_patch || $is_patch)) {
+               print report_dump();
+       }
        if ($clean == 1 && $quiet == 0) {
                print "Your patch has no obvious style problems and is ready 
for submission.\n"
        }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to