Newer
Older
Andy Whitcroft
committed
if ($type eq 'V') {
$variant = 'B';
} else {
$variant = 'U';
}
substr($var, length($res), 1, $variant);
$type = 'N';
} elsif ($cur =~ /^($Operators)/o) {
print "OP($1)\n" if ($dbg_values > 1);
if ($1 ne '++' && $1 ne '--') {
$type = 'N';
}
} elsif ($cur =~ /(^.)/o) {
print "C($1)\n" if ($dbg_values > 1);
}
if (defined $1) {
$cur = substr($cur, length($1));
$res .= $type x length($1);
}
return ($res, $var);
my $notPermitted = qr{(?:
^(?:
$Modifier|
$Storage|
$Type|
DEFINE_\S+
)$|
^(?:
goto|
return|
case|
else|
asm|__asm__|
do
)(?:\s|$)|
)}x;
warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
if ($possible !~ $notPermitted) {
# Check for modifiers.
$possible =~ s/\s*$Storage\s*//g;
$possible =~ s/\s*$Sparse\s*//g;
if ($possible =~ /^\s*$/) {
} elsif ($possible =~ /\s/) {
$possible =~ s/\s*$Type\s*//g;
for my $modifier (split(' ', $possible)) {
if ($modifier !~ $notPermitted) {
warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
push(@modifierList, $modifier);
}
}
} else {
warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
push(@typeList, $possible);
}
} else {
warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
if (defined $tst_only && $_[0] !~ /\Q$tst_only\E/) {
return 0;
}
my $line = $prefix . $_[0];
$line = (split('\n', $line))[0] . "\n" if ($terse);
if (report("ERROR: $_[0]\n")) {
our $clean = 0;
our $cnt_error++;
}
if (report("WARNING: $_[0]\n")) {
our $clean = 0;
our $cnt_warn++;
}
if ($check && report("CHECK: $_[0]\n")) {
our $clean = 0;
our $cnt_chk++;
}
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
sub check_absolute_file {
my ($absolute, $herecurr) = @_;
my $file = $absolute;
##print "absolute<$absolute>\n";
# See if any suffix of this path is a path within the tree.
while ($file =~ s@^[^/]*/@@) {
if (-f "$root/$file") {
##print "file<$file>\n";
last;
}
}
if (! -f _) {
return 0;
}
# It is, so see if the prefix is acceptable.
my $prefix = $absolute;
substr($prefix, -length($file)) = '';
##print "prefix<$prefix>\n";
if ($prefix ne ".../") {
WARN("use relative pathname instead of absolute in changelog text\n" . $herecurr);
}
}
sub process {
my $filename = shift;
my $linenr=0;
my $prevline="";
my $indent;
my $previndent=0;
my $stashindent=0;
my $signoff = 0;
my $is_patch = 0;
our $cnt_lines = 0;
our $cnt_error = 0;
our $cnt_warn = 0;
our $cnt_chk = 0;
# Trace the real file/line as we go.
my $realfile = '';
my $realline = 0;
my $realcnt = 0;
my $here = '';
my $in_comment = 0;
my $prev_values = 'E';
# suppression flags
my %suppress_whiletrailers;
# Pre-scan the patch sanitizing the lines.
# Pre-scan the patch looking for any __setup documentation.
my @setup_docs = ();
my $setup_docs = 0;
my $line;
foreach my $rawline (@rawlines) {
$linenr++;
$line = $rawline;
if ($rawline=~/^\+\+\+\s+(\S+)/) {
$setup_docs = 0;
if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
$setup_docs = 1;
}
#next;
}
if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
$realline=$1-1;
if (defined $2) {
$realcnt=$3+1;
} else {
$realcnt=1+1;
}
# Guestimate if this is a continuing comment. Run
# the context looking for a comment "edge". If this
# edge is a close comment then we must be in a comment
# at context start.
my $edge;
my $cnt = $realcnt;
for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
next if (defined $rawlines[$ln - 1] &&
$rawlines[$ln - 1] =~ /^-/);
$cnt--;
#print "RAW<$rawlines[$ln - 1]>\n";
last if (!defined $rawlines[$ln - 1]);
if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
$rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
($edge) = $1;
last;
}
}
if (defined $edge && $edge eq '*/') {
$in_comment = 1;
}
# Guestimate if this is a continuing comment. If this
# is the start of a diff block and this line starts
# ' *' then it is very likely a comment.
if (!defined $edge &&
$rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
{
$in_comment = 1;
}
##print "COMMENT:$in_comment edge<$edge> $rawline\n";
sanitise_line_reset($in_comment);
} elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
# Standardise the strings and chars within the input to
# simplify matching -- only bother with positive lines.
push(@lines, $line);
if ($realcnt > 1) {
$realcnt-- if ($line =~ /^(?:\+| |$)/);
} else {
$realcnt = 0;
}
#print "==>$rawline\n";
#print "-->$line\n";
if ($setup_docs && $line =~ /^\+/) {
push(@setup_docs, $line);
}
}
foreach my $line (@lines) {
$linenr++;
my $rawline = $rawlines[$linenr - 1];
#extract the line range in the file after the patch is applied
if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
$realline=$1-1;
if (defined $2) {
$realcnt=$3+1;
} else {
$realcnt=1+1;
}
%suppress_whiletrailers = ();
# track the line number as we move through the hunk, note that
# new versions of GNU diff omit the leading space on completely
# blank context lines so we need to count that too.
# Measure the line length and indent.
($length, $indent) = line_stats($rawline);
# Track the previous line.
($prevline, $stashline) = ($stashline, $line);
($previndent, $stashindent) = ($stashindent, $indent);
($prevrawline, $stashrawline) = ($stashrawline, $rawline);
} elsif ($realcnt == 1) {
$realcnt--;
my $hunk_line = ($realcnt != 0);
#make up the handle for any error we report on this line
$prefix = "$filename:$realline: " if ($emacs && $file);
$prefix = "$filename:$linenr: " if ($emacs && !$file);
$here = "#$linenr: " if (!$file);
$here = "#$realline: " if ($file);
# extract the filename as it passes
if ($line =~ /^diff --git.*?(\S+)$/) {
$realfile = $1;
$realfile =~ s@^([^/]*)/@@;
} elsif ($line =~ /^\+\+\+\s+(\S+)/) {
$realfile =~ s@^([^/]*)/@@;
$p1_prefix = $1;
if (!$file && $tree && $p1_prefix ne '' &&
-e "$root/$p1_prefix") {
WARN("patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
}
if ($realfile =~ m@^include/asm/@) {
ERROR("do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
}
next;
}
$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
my $hereline = "$here\n$rawline\n";
my $herecurr = "$here\n$rawline\n";
my $hereprev = "$here\n$prevrawline\n$rawline\n";
$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);
}
}
if ($line =~ /^\s*signed-off-by:/i) {
# This is a signoff, if ugly, so do not double report.
$signoff++;
if (!($line =~ /^\s*Signed-off-by:/)) {
WARN("Signed-off-by: is the preferred form\n" .
$herecurr);
}
if ($line =~ /^\s*signed-off-by:\S/i) {
WARN("space required after Signed-off-by:\n" .
# Check for wrappage within a valid hunk of the file
if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
ERROR("patch seems to be corrupt (line wrapped?)\n" .
$herecurr) if (!$emitted_corrupt++);
# Check for absolute kernel paths.
if ($tree) {
while ($line =~ m{(?:^|\s)(/\S*)}g) {
my $file = $1;
if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
check_absolute_file($1, $herecurr)) {
#
} else {
check_absolute_file($file, $herecurr);
}
}
}
# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
if (($realfile =~ /^$/ || $line =~ /^\+/) &&
$rawline !~ m/^$UTF8*$/) {
my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
my $blank = copy_spacing($rawline);
my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
my $hereptr = "$hereline$ptr\n";
ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
# ignore non-hunk lines and lines being removed
next if (!$hunk_line || $line =~ /^-/);
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
ERROR("DOS line endings\n" . $herevet);
} 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(?:---)?$/) {
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 =~ /^$/);
if ($f =~ /^\s*config\s/) {
$is_end = 1;
last;
}
$length++;
}
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
next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
Andy Whitcroft
committed
$rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
!($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ ||
$line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
Andy Whitcroft
committed
$length > 80)
WARN("line over 80 characters\n" . $herecurr);
# check for spaces before a quoted newline
if ($rawline =~ /^.*\".*\s\\n/) {
WARN("unnecessary whitespace before a quoted newline\n" . $herecurr);
}
# check for adding lines without a newline.
if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
WARN("adding a line without newline at end of file\n" . $herecurr);
}
# Blackfin: use hi/lo macros
if ($realfile =~ m@arch/blackfin/.*\.S$@) {
if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) {
my $herevet = "$here\n" . cat_vet($line) . "\n";
ERROR("use the LO() macro, not (... & 0xFFFF)\n" . $herevet);
}
if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) {
my $herevet = "$here\n" . cat_vet($line) . "\n";
ERROR("use the HI() macro, not (... >> 16)\n" . $herevet);
}
}
# check we are in a valid source file C or perl if not then ignore this hunk
next if ($realfile !~ /\.(h|c|pl)$/);
# at the beginning of a line any tabs must come first and anything
# more than 8 must use tabs.
if ($rawline =~ /^\+\s* \t\s*\S/ ||
$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.
if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
WARN("please, no space before tabs\n" . $herevet);
}
# check for spaces at the beginning of a line.
# 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 spaces at the start of a line\n" . $herevet);
# check we are in a valid C source file if not then ignore this hunk
next if ($realfile !~ /\.(h|c)$/);
# check for RCS/CVS revision markers
if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
}
# Blackfin: don't use __builtin_bfin_[cs]sync
if ($line =~ /__builtin_bfin_csync/) {
my $herevet = "$here\n" . cat_vet($line) . "\n";
ERROR("use the CSYNC() macro in asm/blackfin.h\n" . $herevet);
}
if ($line =~ /__builtin_bfin_ssync/) {
my $herevet = "$here\n" . cat_vet($line) . "\n";
ERROR("use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
}
# Check for potential 'bare' types
my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
$realline_next);
if ($realcnt && $line =~ /.\s*\S/) {
($stat, $cond, $line_nr_next, $remain_next, $off_next) =
ctx_statement_block($linenr, $realcnt, 0);
$stat =~ s/\n./\n /g;
$cond =~ s/\n./\n /g;
# Find the real next line.
$realline_next = $line_nr_next;
if (defined $realline_next &&
(!defined $lines[$realline_next - 1] ||
substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) {
$realline_next++;
}
my $s = $stat;
$s =~ s/{.*$//s;
# Ignore functions being called
} elsif ($s =~ /^.\s*$Ident\s*\(/s) {
} elsif ($s =~ /^.\s*else\b/s) {
# declarations always start with types
} elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) {
my $type = $1;
$type =~ s/\s+/ /g;
possible($type, "A:" . $s);
# definitions in global scope can only start with types
} elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) {
# any (foo ... *) is a pointer cast, and foo is a type
while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) {
}
# Check for any sort of function declaration.
# int foo(something bar, other baz);
# void (*store_gdt)(x86_descr_ptr *);
if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
my ($name_len) = length($1);
substr($ctx, 0, $name_len + 1, '');
for my $arg (split(/\s*,\s*/, $ctx)) {
if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) {
#
# Checks which may be anchored in the context.
#
# Check for switch () and associated case and default
# statements should be at the same indent.
if ($line=~/\bswitch\s*\(.*\)/) {
my $err = '';
my $sep = '';
my @ctx = ctx_block_outer($linenr, $realcnt);
shift(@ctx);
for my $ctx (@ctx) {
my ($clen, $cindent) = line_stats($ctx);
if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
$indent != $cindent) {
$err .= "$sep$ctx\n";
$sep = '';
} else {
$sep = "[...]\n";
}
}
if ($err ne '') {
ERROR("switch and case should be at the same indent\n$hereline$err");
}
}
# 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*\#/) {
my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
my $ctx_cnt = $realcnt - $#ctx - 1;
my $ctx = join("\n", @ctx);
my $ctx_ln = $linenr;
my $ctx_skip = $realcnt;
while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt &&
defined $lines[$ctx_ln - 1] &&
$lines[$ctx_ln - 1] =~ /^-/)) {
##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
$ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/);
Andy Whitcroft
committed
#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*{/) {
ERROR("that open brace { should be on the previous line\n" .
"$here\n$ctx\n$lines[$ctx_ln - 1]\n");
if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
$ctx =~ /\)\s*\;\s*$/ &&
defined $lines[$ctx_ln - 1])
{
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");
# Check relative indent for conditionals and blocks.
if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
my ($s, $c) = ($stat, $cond);
substr($s, 0, length($c), '');
# Make sure we remove the line prefixes as we have
# none on the first line, and are going to readd them
# where necessary.
$s =~ s/\n./\n/gs;
# Find out how long the conditional actually is.
my @newlines = ($c =~ /\n/gs);
my $cond_lines = 1 + $#newlines;
# We want to check the first line inside the block
# starting at the end of the conditional, so remove:
# 1) any blank line termination
# 2) any opening brace { on end of the line
# 3) any do (...) {
my $continuation = 0;
my $check = 0;
$s =~ s/^.*\bdo\b//;
$s =~ s/^\s*{//;
if ($s =~ s/^\s*\\//) {
$continuation = 1;
}
Andy Whitcroft
committed
if ($s =~ s/^\s*?\n//) {
$check = 1;
$cond_lines++;
}
# Also ignore a loop construct at the end of a
# preprocessor statement.
if (($prevline =~ /^.\s*#\s*define\s/ ||
$prevline =~ /\\\s*$/) && $continuation == 0) {
$check = 0;
}
Andy Whitcroft
committed
my $cond_ptr = -1;
$continuation = 0;
Andy Whitcroft
committed
while ($cond_ptr != $cond_lines) {
$cond_ptr = $cond_lines;
# If we see an #else/#elif then the code
# is not linear.
if ($s =~ /^\s*\#\s*(?:else|elif)/) {
$check = 0;
}
Andy Whitcroft
committed
# Ignore:
# 1) blank lines, they should be at 0,
# 2) preprocessor lines, and
# 3) labels.
if ($continuation ||
$s =~ /^\s*?\n/ ||
Andy Whitcroft
committed
$s =~ /^\s*#\s*?/ ||
$s =~ /^\s*$Ident\s*:/) {
$continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
if ($s =~ s/^.*?\n//) {
$cond_lines++;
}
Andy Whitcroft
committed
}
}
my (undef, $sindent) = line_stats("+" . $s);
my $stat_real = raw_line($linenr, $cond_lines);
# Check if either of these lines are modified, else
# this is not this patch's fault.
if (!defined($stat_real) ||
$stat !~ /^\+/ && $stat_real !~ /^\+/) {
$check = 0;
}
if (defined($stat_real) && $cond_lines > 1) {
$stat_real = "[...]\n$stat_real";
}
Andy Whitcroft
committed
#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
if ($check && (($sindent % 8) != 0 ||
($sindent <= $indent && $s ne ''))) {
WARN("suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
}
}
# Track the 'values' across context and added lines.
my $opline = $line; $opline =~ s/^./ /;
my ($curr_values, $curr_vars) =
annotate_values($opline . "\n", $prev_values);
$curr_values = $prev_values . $curr_values;
if ($dbg_values) {
my $outline = $opline; $outline =~ s/\t/ /g;
print "$linenr > .$outline\n";
print "$linenr > $curr_values\n";
print "$linenr > $curr_vars\n";
$prev_values = substr($curr_values, -1);
#ignore lines not being added
if ($line=~/^[^\+]/) {next;}
# TEST: allow direct testing of the type matcher.
if ($dbg_type) {
if ($line =~ /^.\s*$Declare\s*$/) {
ERROR("TEST: is type\n" . $herecurr);
} elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
ERROR("TEST: is not type ($1 is)\n". $herecurr);
}
# TEST: allow direct testing of the attribute matcher.
if ($dbg_attr) {
if ($line =~ /^.\s*$Modifier\s*$/) {
ERROR("TEST: is attr\n" . $herecurr);
} elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
ERROR("TEST: is not attr ($1 is)\n". $herecurr);
}
next;
}
# check for initialisation to aggregates open brace on the next line
if ($line =~ /^.\s*{/ &&
$prevline =~ /(?:^|[^=])=\s*$/) {
ERROR("that open brace { should be on the previous line\n" . $hereprev);
#
# Checks which are anchored on the added line.
#
# check for malformed paths in #include statements (uses RAW line)
if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
my $path = $1;
if ($path =~ m{//}) {
ERROR("malformed #include filename\n" .
$herecurr);
ERROR("do not use C99 // comments\n" . $herecurr);
# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
# the whole statement.
#print "APW <$lines[$realline_next - 1]>\n";
if (defined $realline_next &&
exists $lines[$realline_next - 1] &&
!defined $suppress_export{$realline_next} &&
($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
$lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
if ($stat !~ /(?:
\n.}\s*$|
^.DEFINE_$Ident\(\Q$name\E\)|
^.DECLARE_$Ident\(\Q$name\E\)|
^.LIST_HEAD\(\Q$name\E\)|
^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
\b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\()
#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
$suppress_export{$realline_next} = 2;
} else {
$suppress_export{$realline_next} = 1;
if (!defined $suppress_export{$linenr} &&
$prevline =~ /^.\s*$/ &&
($line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
$line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
#print "FOO B <$lines[$linenr - 1]>\n";
$suppress_export{$linenr} = 2;
}
if (defined $suppress_export{$linenr} &&
$suppress_export{$linenr} == 2) {
WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
}
if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
ERROR("do not initialise globals to 0 or NULL\n" .
if ($line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/) {
ERROR("do not initialise statics to 0 or NULL\n" .
$herecurr);
# check for new typedefs, only function parameters and sparse annotations
# make sense.
if ($line =~ /\btypedef\s/ &&
$line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
$line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
$line !~ /\b$typeTypedefs\b/ &&
$line !~ /\b__bitwise(?:__|)\b/) {
WARN("do not add new typedefs\n" . $herecurr);
}
# * goes on variable not on type
# (char*[ const])
if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) {
my ($from, $to) = ($1, $1);
# Should start with a space.
$to =~ s/^(\S)/ $1/;
# Should not end with a space.
$to =~ s/\s+$//;
# '*'s should not have spaces between.
while ($to =~ s/\*\s+\*/\*\*/) {
#print "from<$from> to<$to>\n";
if ($from ne $to) {
ERROR("\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr);
}
} elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) {
my ($from, $to, $ident) = ($1, $1, $2);
# Should start with a space.
$to =~ s/^(\S)/ $1/;
# Should not end with a space.
$to =~ s/\s+$//;
# '*'s should not have spaces between.
while ($to =~ s/\*\s+\*/\*\*/) {
}
# Modifiers should have spaces.
$to =~ s/(\b$Modifier$)/$1 /;
#print "from<$from> to<$to> ident<$ident>\n";
if ($from ne $to && $ident !~ /^$Modifier$/) {
ERROR("\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr);
}
}
# # no BUG() or BUG_ON()
# if ($line =~ /\b(BUG|BUG_ON)\b/) {
# print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
# print "$herecurr";
# $clean = 0;
# }
if ($line =~ /\bLINUX_VERSION_CODE\b/) {
WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\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.
# 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
# with "\n" ignore it, else it is to blame
if ($lines[$ln - 1] =~ m{\bprintk\(}) {
if ($rawlines[$ln - 1] !~ m{\\n"}) {
$ok = 1;
}
last;
}
}
if ($ok == 0) {
WARN("printk() should include KERN_ facility level\n" . $herecurr);
# 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
!($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) {
ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
# 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 '{' 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,
# 3. inside a curly brace -- = { [0...10] = 5 }
while ($line =~ /(.*?\s)\[/g) {
my ($where, $prefix) = ($-[1], $1);
if ($prefix !~ /$Type\s+$/ &&
($where != 0 || $prefix !~ /^.\s+$/) &&
$prefix !~ /{\s+$/) {
ERROR("space prohibited before open square bracket '['\n" . $herecurr);
}
}
# check for spaces between functions and their parentheses.
while ($line =~ /($Ident)\s+\(/g) {
my $ctx_before = substr($line, 0, $-[1]);
my $ctx = "$ctx_before$name";
# Ignore those directives where spaces _are_ permitted.
if ($name =~ /^(?:
if|for|while|switch|return|case|
volatile|__volatile__|
__attribute__|format|__extension__|
asm|__asm__)$/x)
{
# cpp #define statements have non-optional spaces, ie
# if there is a space between the name and the open
# parenthesis it is simply not a parameter group.
} elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
# cpp #elif statement condition may start with a (
} elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
# If this whole things ends with a type its most
# likely a typedef for a function.
WARN("space prohibited between function name and open parenthesis '('\n" . $herecurr);
my $ops = qr{
<<=|>>=|<=|>=|==|!=|
\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
=>|->|<<|>>|<|>|=|!|~|
&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
\?|:
my @elements = split(/($ops|;)/, $opline);