|
@@ -9,7 +9,7 @@ use strict;
|
|
|
my $P = $0;
|
|
|
$P =~ s@.*/@@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 =~ m@include/(.*)@) {
|
|
|
+ if (/^Check:\s+(.*\S)/) {
|
|
|
+ for my $entry (split(/[, ]+/, $1)) {
|
|
|
+ if ($entry =~ m@include/(.*)@) {
|
|
|
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 =~ m@\#\s*include\s*\<$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"
|
|
|
}
|