#!/usr/bin/perl -w # (c) 2001, Dave Jones. (the file handling bit) # (c) 2005, Joel Scohpp (the ugly bit) # Licensed under the terms of the GNU GPL License version 2 use strict; my @lines = (); while (<>) { chomp; push(@lines, $_); if (eof(ARGV)) { process($ARGV, @lines); @lines = (); } } sub process { my $filename = shift; my @lines = @_; my $linenr=0; my $prevline=""; my $clean = 1; # Trace the real file/line as we go. my $realfile = ''; my $realline = 0; my $realcnt = 0; my $here = ''; foreach my $line (@lines) { $linenr++; #extract the filename as it passes if($line=~/^\+\+\+\s+(\S+)/) { $realfile=$1; next; } #extract the line range in the file after the patch is applied if($line=~/^@@ -\d+,\d+ \+(\d+),(\d+) @@/) { $realline=$1-1; $realcnt=$2+1; next; } #track the line number as we move thorugh the hunk if($line=~/^( |\+)/) { $realline++; $realcnt-- if ($realcnt); } #ignore lines not being added if($line=~/^[^\+]/) {next;} #make up the handle for any error we report on this line $here = "PATCH: $ARGV:$linenr:"; $here .= "\nFILE: $realfile:$realline:" if ($realcnt); # * goes on variable not on type if($line=~/[A-Za-z\d_]+\* [A-Za-z\d_]+/) { print ("\"foo* bar\" should be \"foo *bar\"\n"); print "$linenr:\n$line\n\n"; $clean = 0; } #trailing whitespace if($line=~/\S\s+$/) { print ("trailing whitespace\n"); print "$here\n$line\n\n"; $clean = 0; } #80 column limit my $lineforcounting; $lineforcounting = $line; $lineforcounting =~ s/^\+//; $lineforcounting =~ s/\t/ /; if(length($lineforcounting) > 80){ print "line over 80 characters\n"; print "$here\n$line\n\n"; $clean = 0; } #function brace can't be on same line, except for #defines of do while, or if closed on same line if(($line=~/[A-Za-z\d_]+\**\s+\**[A-Za-z\d_]+\(.*\).* {/) and !($line=~/\#define.*do.*while/) and !($line=~/}/)){ print "braces following function declarations go on the next line\n"; print "$here\n$line\n\n"; $clean = 0; } #need spaces around = in assignments unless they are in quotes if((($line=~/[A-Za-z\d_]+=/) or ($line=~/=[A-Za-z\d_]+/)) and !($line=~/\".*=.*\"/)) { print ("need spaces around that =\n"); print "$here\n$line\n\n"; } #need space before brace following if, while, etc if($line=~/\(.*\){/) { print ("need a space before the brace\n"); print "$here\n$line\n\n"; $clean = 0; } #gotos aren't indented if($line=~/^\+[ \t]+[A-Za-z\d_]+\s*:/){ print "Gotos should not be indented\n"; print "$here\n$line\n\n"; $clean = 0; } #spaces vs tabs elsif($line=~/^\+ +[A-Za-z\d_]/) { print ("use tabs not spaces\n"); print "$here\n$line\n\n"; $clean = 0; } #studly caps, commented out until figure out how to distinguish between use of existing and adding new # if(($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) { # print ("No studly caps, use _\n"); # print "$here\n$line\n\n"; # $clean = 0; # } #no spaces allowed after \ in define if($line=~/\#define.*\\\s$/){ print("Whitepspace after \\ makes next lines useless\n"); print "$here\n$line\n\n"; $clean = 0; } #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 ($prevline=~/(if|while|for)\s*\(/) { my @opened = $prevline=~/\(/g; my @closed = $prevline=~/\)/g; my $nr_line = $linenr; my $next_line = $line; my $extra_lines = 0; while (scalar @opened > scalar @closed) { $prevline .= $next_line; $next_line = $lines[$nr_line]; $nr_line++; #This test is here to take into account the contextual lines # i.e. lines not added to the file # Normally there are 3 contextual lines before/after the modified lines if (!$next_line=~/^\+/) { if ($extra_lines < 3) { $extra_lines++; } else { last; } } @opened = $prevline=~/\(/g; @closed = $prevline=~/\)/g; } if(($prevline=~/(if|while|for)\s*\(.*\)\s*$/) and ($next_line=~/{/) and !($next_line=~/(if|while|for)/) and !($next_line=~/\#define.*do.*while/)) { print "test: $lines[$linenr-1]\n"; print "\'$prevline\' \'$line\'"; print "That { should be on the previous line\n"; print "$here\n$line\n\n"; $clean = 0; } } #multiline macros should be enclosed in a do while loop if(($prevline=~/\#define.*\\/) and ($line=~/\\/) and !($line=~/do.*{/)){ print "Macros with multiple statements should be enclosed in a do - while loop\n"; print "$here\n$line\n\n"; $clean = 0; } #assignment in an if or while statement not soo good if($line=~/(if|while)\(.*\s=\s.*\)/){ print "Assignment inside of if statements is generally frowned upon\n"; print "$here\n$line\n\n"; $clean = 0; } #prevline $prevline = $line; } if($clean == 1){ print "Your patch is now worthy to be reviewed by a real person\n"; print "This small program couldn't find anything wrong\n"; print "Not to say there isn't anything wrong, but you are off to a good start\n"; print "If you find any style errors that this program missed please send them to \n"; print "Joel Schopp so he can try to incorporate them\n" } if($clean == 0){ print "If any of these errors are false positives please send them to\n"; print "Joel Schopp so he can fix things."; } return 1; }