Newer
Older
#!/usr/bin/perl -w
# (c) 2001, Dave Jones. <davej@codemonkey.org.uk> (the file handling bit)
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
# (c) 2007, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite, etc)
# Licensed under the terms of the GNU GPL License version 2
use strict;
my $P = $0;
use Getopt::Long qw(:config no_auto_abbrev);
my $quiet = 0;
my $tree = 1;
my $chk_signoff = 1;
my $chk_patch = 1;
my $summary = 1;
my $mailback = 0;
'tree!' => \$tree,
'signoff!' => \$chk_signoff,
'patch!' => \$chk_patch,
'file!' => \$file,
'subjective!' => \$check,
'strict!' => \$check,
'root=s' => \$root,
'summary!' => \$summary,
'mailback!' => \$mailback,
'summary-file!' => \$summary_file,
) or exit;
my $exit = 0;
if ($#ARGV < 0) {
print "usage: $P [options] patchfile\n";
print "options: -q => quiet\n";
print " --no-tree => run without a kernel tree\n";
print " --terse => one line per report\n";
print " --emacs => emacs compile window format\n";
print " --file => check a source file\n";
print " --strict => enable more subjective tests\n";
print " --root => path to the kernel tree root\n";
print " --no-summary => suppress the per-file summary\n";
print " --summary-file => include the filename in summary\n";
my $dbg_values = 0;
my $dbg_possible = 0;
for my $key (keys %debug) {
eval "\${dbg_$key} = '$debug{$key}';"
}
if ($terse) {
$emacs = 1;
$quiet++;
}
if ($tree) {
if (defined $root) {
if (!top_of_kernel_tree($root)) {
die "$P: $root: --root does not point at a valid tree\n";
}
} else {
if (top_of_kernel_tree('.')) {
$root = '.';
} elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
top_of_kernel_tree($1)) {
$root = $1;
}
}
if (!defined $root) {
print "Must be run from the top-level dir. of a kernel tree\n";
exit(2);
}
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
my $emitted_corrupt = 0;
our $Ident = qr{[A-Za-z_][A-Za-z\d_]*};
our $Storage = qr{extern|static|asmlinkage};
our $Sparse = qr{
__user|
__kernel|
__force|
__iomem|
__must_check|
__init_refok|
__kprobes|
fastcall
}x;
our $Attribute = qr{
const|
__read_mostly|
__kprobes|
__(?:mem|cpu|dev|)(?:initdata|init)
}x;
our $Inline = qr{inline|__always_inline|noinline};
our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};
our $Lval = qr{$Ident(?:$Member)*};
our $Constant = qr{(?:[0-9]+|0x[0-9a-fA-F]+)[UL]*};
our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
our $Operators = qr{
<=|>=|==|!=|
=>|->|<<|>>|<|>|!|~|
&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
our $NonptrType;
our $Type;
our $Declare;
our @typeList = (
qr{void},
qr{char},
qr{short},
qr{int},
qr{long},
qr{unsigned},
qr{float},
qr{double},
qr{bool},
qr{long\s+int},
qr{long\s+long},
qr{long\s+long\s+int},
qr{(?:__)?(?:u|s|be|le)(?:8|16|32|64)},
qr{struct\s+$Ident},
qr{union\s+$Ident},
qr{enum\s+$Ident},
qr{${Ident}_t},
qr{${Ident}_handler},
qr{${Ident}_handler_fn},
);
sub build_types {
my $all = "(?: \n" . join("|\n ", @typeList) . "\n)";
$NonptrType = qr{
\b
(?:const\s+)?
(?:unsigned\s+)?
$all
(?:\s+$Sparse|\s+const)*
\b
}x;
$Type = qr{
\b$NonptrType\b
(?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
(?:\s+$Inline|\s+$Sparse|\s+$Attribute)*
}x;
$Declare = qr{(?:$Storage\s+)?$Type};
}
build_types();
$chk_signoff = 0 if ($file);
my @dep_includes = ();
my @dep_functions = ();
my $removal = "Documentation/feature-removal-schedule.txt";
if ($tree && -f "$root/$removal") {
open(REMOVE, "<$root/$removal") ||
die "$P: $removal: open failed - $!\n";
if (/^Check:\s+(.*\S)/) {
for my $entry (split(/[, ]+/, $1)) {
if ($entry =~ m@include/(.*)@) {
} elsif ($entry !~ m@/@) {
push(@dep_functions, $entry);
}
for my $filename (@ARGV) {
if ($file) {
open(FILE, "diff -u /dev/null $filename|") ||
die "$P: $filename: diff failed - $!\n";
} else {
open(FILE, "<$filename") ||
die "$P: $filename: open failed - $!\n";
if ($filename eq '-') {
$vname = 'Your patch';
} else {
$vname = $filename;
}
while (<FILE>) {
chomp;
push(@rawlines, $_);
}
close(FILE);
$exit = 1;
}
@rawlines = ();
}
exit($exit);
sub top_of_kernel_tree {
my ($root) = @_;
my @tree_check = (
"COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
"README", "Documentation", "arch", "include", "drivers",
"fs", "init", "ipc", "kernel", "lib", "scripts",
);
foreach my $check (@tree_check) {
if (! -e $root . '/' . $check) {
return 0;
}
}
sub expand_tabs {
my ($str) = @_;
my $res = '';
my $n = 0;
for my $c (split(//, $str)) {
if ($c eq "\t") {
$res .= ' ';
$n++;
for (; ($n % 8) != 0; $n++) {
$res .= ' ';
}
next;
}
$res .= $c;
$n++;
}
return $res;
}
sub copy_spacing {
my ($str) = @_;
my $res = '';
for my $c (split(//, $str)) {
if ($c eq "\t") {
$res .= $c;
} else {
$res .= ' ';
}
}
return $res;
}
sub line_stats {
my ($line) = @_;
# Drop the diff line leader and expand tabs
$line =~ s/^.//;
$line = expand_tabs($line);
# Pick the indent from the front of the line.
my ($white) = ($line =~ /^(\s*)/);
return (length($line), length($white));
}
sub sanitise_line {
my ($line) = @_;
my $res = '';
my $l = '';
my $quote = '';
foreach my $c (split(//, $line)) {
# The second backslash of a pair is not a "quote".
if ($l eq "\\" && $c eq "\\") {
$c = 'X';
}
if ($l ne "\\" && ($c eq "'" || $c eq '"')) {
if ($quote eq '') {
$quote = $c;
$res .= $c;
$l = $c;
next;
} elsif ($quote eq $c) {
$quote = '';
}
}
if ($quote eq "'" && $qlen > 1) {
$quote = '';
}
if ($quote && $c ne "\t") {
$res .= "X";
} else {
$res .= $c;
}
$l = $c;
}
while ($res =~ m@(/\*.*?\*/)@g) {
substr($res, $-[1], $+[1] - $-[1]) = $; x ($+[1] - $-[1]);
substr($res, $-[1], $+[1] - $-[1]) = $; x ($+[1] - $-[1]);
substr($res, $-[1], $+[1] - $-[1]) = $; x ($+[1] - $-[1]);
}
# The pathname on a #include may be surrounded by '<' and '>'.
if ($res =~ /^.#\s*include\s+\<(.*)\>/) {
my $clean = 'X' x length($1);
$res =~ s@\<.*\>@<$clean>@;
# The whole of a #error is a string.
} elsif ($res =~ /^.#\s*(?:error|warning)\s+(.*)\b/) {
my $clean = 'X' x length($1);
$res =~ s@(#\s*(?:error|warning)\s+).*@$1$clean@;
}
sub ctx_statement_block {
my ($linenr, $remain, $off) = @_;
my $line = $linenr - 1;
my $blk = '';
my $soff = $off;
my $coff = $off - 1;
my $type = '';
my $level = 0;
my $c;
my $len = 0;
while (1) {
#warn "CSB: blk<$blk>\n";
# If we are about to drop off the end, pull in more
# context.
if ($off >= $len) {
for (; $remain > 0; $line++) {
$len = length($blk);
$line++;
last;
}
# Bail if there is no further context.
#warn "CSB: blk<$blk> off<$off> len<$len>\n";
last;
}
}
$c = substr($blk, $off, 1);
#warn "CSB: c<$c> type<$type> level<$level>\n";
# Statement ends at the ';' or a close '}' at the
# outermost level.
if ($level == 0 && $c eq ';') {
last;
}
# An else is really a conditional as long as its not else if
if ($level == 0 && $remainder =~ /(\s+else)(?:\s|{)/ &&
$remainder !~ /\s+else\s+if\b/) {
$coff = $off + length($1);
}
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
if (($type eq '' || $type eq '(') && $c eq '(') {
$level++;
$type = '(';
}
if ($type eq '(' && $c eq ')') {
$level--;
$type = ($level != 0)? '(' : '';
if ($level == 0 && $coff < $soff) {
$coff = $off;
}
}
if (($type eq '' || $type eq '{') && $c eq '{') {
$level++;
$type = '{';
}
if ($type eq '{' && $c eq '}') {
$level--;
$type = ($level != 0)? '{' : '';
if ($level == 0) {
last;
}
}
$off++;
}
if ($off == $len) {
$line++;
$remain--;
}
my $statement = substr($blk, $soff, $off - $soff + 1);
my $condition = substr($blk, $soff, $coff - $soff + 1);
#warn "STATEMENT<$statement>\n";
#warn "CONDITION<$condition>\n";
#print "off<$off> loff<$loff>\n";
return ($statement, $condition,
$line, $remain + 1, $off - $loff + 1, $level);
}
sub ctx_statement_full {
my ($linenr, $remain, $off) = @_;
my ($statement, $condition, $level);
my (@chunks);
($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off);
#print "F: c<$condition> s<$statement>\n";
for (;;) {
push(@chunks, [ $condition, $statement ]);
last if (!($remain > 0 && $condition =~ /^.\s*(?:if|else|do)/));
($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off);
#print "C: c<$condition> s<$statement>\n";
}
return ($level, $linenr, @chunks);
my ($linenr, $remain, $outer, $open, $close, $off) = @_;
my $line;
my $start = $linenr - 1;
my $blk = '';
my @o;
my @c;
my @res = ();
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;
}
if ($c eq $close && $level > 0) {
$level--;
last if ($level == 0);
} elsif ($c eq $open) {
$level++;
}
}
}
sub ctx_block_outer {
my ($linenr, $remain) = @_;
my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
return @r;
}
sub ctx_block {
my ($linenr, $remain) = @_;
my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
return @r;
my ($linenr, $remain, $off) = @_;
my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
return @r;
}
sub ctx_block_level {
return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
sub ctx_statement_level {
my ($linenr, $remain, $off) = @_;
return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
}
sub ctx_locate_comment {
my ($first_line, $end_line) = @_;
# Catch a comment on the end of the line itself.
my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*$@);
return $current_comment if (defined $current_comment);
# Look through the context and try and figure out if there is a
# comment.
my $in_comment = 0;
$current_comment = '';
for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
my $line = $rawlines[$linenr - 1];
#warn " $line\n";
if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
$in_comment = 1;
}
if ($line =~ m@/\*@) {
$in_comment = 1;
}
if (!$in_comment && $current_comment ne '') {
$current_comment = '';
}
$current_comment .= $line . "\n" if ($in_comment);
if ($line =~ m@\*/@) {
$in_comment = 0;
}
}
chomp($current_comment);
return($current_comment);
}
sub ctx_has_comment {
my ($first_line, $end_line) = @_;
my $cmt = ctx_locate_comment($first_line, $end_line);
##print "LINE: $rawlines[$end_line - 1 ]\n";
##print "CMMT: $cmt\n";
return ($cmt ne '');
}
sub cat_vet {
my ($vet) = @_;
my ($res, $coded);
$res = '';
while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
$res .= $1;
if ($2 ne '') {
$coded = sprintf("^%c", unpack('C', $2) + 64);
$res .= $coded;
my $av_preprocessor = 0;
my $av_paren = 0;
my @av_paren_type;
sub annotate_reset {
$av_preprocessor = 0;
$av_paren = 0;
@av_paren_type = ();
}
sub annotate_values {
my ($stream, $type) = @_;
my $res;
my $cur = $stream;
print "$stream\n" if ($dbg_values > 1);
print " <$type> " if ($dbg_values > 1);
print "WS($1)\n" if ($dbg_values > 1);
if ($1 =~ /\n/ && $av_preprocessor) {
$av_preprocessor = 0;
print "DECLARE($1)\n" if ($dbg_values > 1);
$type = 'T';
} elsif ($cur =~ /^(#\s*define\s*$Ident)(\(?)/o) {
print "DEFINE($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1;
$av_paren_type[$av_paren] = 'N';
} elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if|else|elif|endif))/o) {
print "PRE($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1;
$type = 'N';
} elsif ($cur =~ /^(\\\n)/o) {
print "PRECONT($1)\n" if ($dbg_values > 1);
} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
print "SIZEOF($1)\n" if ($dbg_values > 1);
} elsif ($cur =~ /^(if|while|typeof|__typeof__|for)\b/o) {
print "COND($1)\n" if ($dbg_values > 1);
$av_paren_type[$av_paren] = 'N';
$type = 'N';
} elsif ($cur =~/^(return|case|else)/o) {
print "KEYWORD($1)\n" if ($dbg_values > 1);
$type = 'N';
} elsif ($cur =~ /^(\()/o) {
print "PAREN('$1')\n" if ($dbg_values > 1);
$av_paren++;
$type = 'N';
} elsif ($cur =~ /^(\))/o) {
$av_paren-- if ($av_paren > 0);
if (defined $av_paren_type[$av_paren]) {
$type = $av_paren_type[$av_paren];
undef $av_paren_type[$av_paren];
print "PAREN('$1') -> $type\n"
if ($dbg_values > 1);
print "PAREN('$1')\n" if ($dbg_values > 1);
}
} elsif ($cur =~ /^($Ident)\(/o) {
print "FUNC($1)\n" if ($dbg_values > 1);
$av_paren_type[$av_paren] = 'V';
} elsif ($cur =~ /^($Ident|$Constant)/o) {
print "IDENT($1)\n" if ($dbg_values > 1);
$type = 'V';
} elsif ($cur =~ /^($Assignment)/o) {
print "ASSIGN($1)\n" if ($dbg_values > 1);
print "END($1)\n" if ($dbg_values > 1);
$type = 'E';
} elsif ($cur =~ /^(;|{|}|\?|:|\[)/o) {
print "CLOSE($1)\n" if ($dbg_values > 1);
$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);
}
#print "CHECK<$possible>\n";
if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ &&
$possible ne 'goto' && $possible ne 'return' &&
$possible ne 'struct' && $possible ne 'enum' &&
$possible ne 'case' && $possible ne 'else' &&
$possible ne 'typedef') {
warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
push(@typeList, $possible);
build_types();
}
}
my $line = $prefix . $_[0];
$line = (split('\n', $line))[0] . "\n" if ($terse);
if ($check) {
report("CHECK: $_[0]\n");
our $clean = 0;
our $cnt_chk++;
}
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_ifbraces = 0;
# 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) {
# Standardise the strings and chars within the input to
# simplify matching.
$line = sanitise_line($rawline);
push(@lines, $line);
##print "==>$rawline\n";
##print "-->$line\n";
if ($line=~/^\+\+\+\s+(\S+)/) {
$setup_docs = 0;
if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
$setup_docs = 1;
}
next;
}
if ($setup_docs && $line =~ /^\+/) {
push(@setup_docs, $line);
}
}
foreach my $line (@lines) {
$linenr++;
my $rawline = $rawlines[$linenr - 1];
#extract the filename as it passes
if ($line=~/^\+\+\+\s+(\S+)/) {
$realfile=$1;
$in_comment = 0;
next;
}
#extract the line range in the file after the patch is applied
if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
$in_comment = 0;
$realline=$1-1;
if (defined $2) {
$realcnt=$3+1;
} else {
$realcnt=1+1;
}
$prev_values = 'E';
$suppress_ifbraces = $linenr - 1;
# 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.
if ($line =~ /^( |\+|$)/) {
# 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.
if ($linenr == $first_line) {
my $edge;
for (my $ln = $first_line; $ln < ($linenr + $realcnt); $ln++) {
($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
last if (defined $edge);
}
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 ($linenr == $first_line and $rawline =~ m@^.\s* \*(?:\s|$)@) {
# Find the last comment edge on _this_ line.
$comment_edge = 0;
while (($rawline =~ m@(/\*|\*/)@g)) {
if ($1 eq '/*') {
$in_comment = 1;
} else {
$in_comment = 0;
}
# 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);
#warn "ic<$in_comment> ce<$comment_edge> line<$line>\n";
} elsif ($realcnt == 1) {
$realcnt--;
}
#make up the handle for any error we report on this line
$here = "#$linenr: " if (!$file);
$here = "#$realline: " if ($file);
$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";
$prefix = "$filename:$realline: " if ($emacs && $file);
$prefix = "$filename:$linenr: " if ($emacs && !$file);
$cnt_lines++ if ($realcnt != 0);
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("need space after Signed-off-by:\n" .
$herecurr);
# 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++);
}
# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
if (($realfile =~ /^$/ || $line =~ /^\+/) &&
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*$/x )) {
ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $herecurr);
}
#ignore lines being removed
if ($line=~/^-/) {next;}
# check we are in a valid source file if not then ignore this hunk
next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
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);
if ($line =~ /^\+/ && !($prevrawline=~/\/\*\*/) && $length > 80) {
WARN("line over 80 characters\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);
}
# check we are in a valid source file *.[hc] if not then ignore this hunk
next if ($realfile !~ /\.[hc]$/);
# 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("use tabs not spaces\n" . $herevet);
# check for RCS/CVS revision markers
if ($rawline =~ /\$(Revision|Log|Id)(?:\$|)/) {
WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
}
# The rest of our checks refer specifically to C style
# only apply those _outside_ comments. Only skip
# lines in the middle of comments.
next if (!$comment_edge && $in_comment);
# Check for potential 'bare' types