Skip to content
Snippets Groups Projects
checkpatch.pl 129 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
    # Check if there is UTF-8 in a commit log when a mail header has explicitly
    # declined it, i.e defined some charset where it is missing.
    		if ($in_header_lines &&
    		    $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
    		    $1 !~ /utf-8/i) {
    			$non_utf8_charset = 1;
    		}
    
    		if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
    		    $rawline =~ /$NON_ASCII_UTF8/) {
    			WARN("UTF8_BEFORE_PATCH",
    			    "8-bit UTF-8 used in possible commit log\n" . $herecurr);
    		}
    
    
    # Check for various typo / spelling mistakes
    		if (defined($misspellings) &&
    		    ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
    			while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) {
    				my $typo = $1;
    				my $typo_fix = $spelling_fix{lc($typo)};
    				$typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
    				$typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
    				my $msg_type = \&WARN;
    				$msg_type = \&CHK if ($file);
    				if (&{$msg_type}("TYPO_SPELLING",
    						 "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
    				    $fix) {
    					$fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
    				}
    			}
    		}
    
    
    # ignore non-hunk lines and lines being removed
    		next if (!$hunk_line || $line =~ /^-/);
    
    #trailing whitespace
    		if ($line =~ /^\+.*\015/) {
    			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
    
    			if (ERROR("DOS_LINE_ENDINGS",
    				  "DOS line endings\n" . $herevet) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/[\s\015]+$//;
    			}
    
    		} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
    			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
    
    			if (ERROR("TRAILING_WHITESPACE",
    				  "trailing whitespace\n" . $herevet) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/\s+$//;
    			}
    
    
    # Check for FSF mailing addresses.
    		if ($rawline =~ /\bwrite to the Free/i ||
    		    $rawline =~ /\b59\s+Temple\s+Pl/i ||
    		    $rawline =~ /\b51\s+Franklin\s+St/i) {
    			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
    			my $msg_type = \&ERROR;
    			$msg_type = \&CHK if ($file);
    			&{$msg_type}("FSF_MAILING_ADDRESS",
    				     "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
    		}
    
    
    # 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*config\s+/) {
    
    			my $length = 0;
    			my $cnt = $realcnt;
    			my $ln = $linenr + 1;
    			my $f;
    
    			for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) {
    
    				$f = $lines[$ln - 1];
    				$cnt-- if ($lines[$ln - 1] !~ /^-/);
    				$is_end = $lines[$ln - 1] =~ /^\+/;
    
    				next if ($f =~ /^-/);
    
    
    				if ($lines[$ln - 1] =~ /.\s*(?:bool|tristate)\s*\"/) {
    					$is_start = 1;
    				} elsif ($lines[$ln - 1] =~ /.\s*(?:---)?help(?:---)?$/) {
    					$length = -1;
    				}
    
    
    				$f =~ s/^.//;
    				$f =~ s/#.*//;
    				$f =~ s/^\s+//;
    				next if ($f =~ /^$/);
    				if ($f =~ /^\s*config\s/) {
    					$is_end = 1;
    					last;
    				}
    				$length++;
    			}
    			WARN("CONFIG_DESCRIPTION",
    
    			     "please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_start && $is_end && $length < 4);
    			#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
    		}
    
    # discourage the addition of CONFIG_EXPERIMENTAL in Kconfig.
    		if ($realfile =~ /Kconfig/ &&
    		    $line =~ /.\s*depends on\s+.*\bEXPERIMENTAL\b/) {
    			WARN("CONFIG_EXPERIMENTAL",
    			     "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n");
    		}
    
    		if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) &&
    		    ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) {
    			my $flag = $1;
    			my $replacement = {
    				'EXTRA_AFLAGS' =>   'asflags-y',
    				'EXTRA_CFLAGS' =>   'ccflags-y',
    				'EXTRA_CPPFLAGS' => 'cppflags-y',
    				'EXTRA_LDFLAGS' =>  'ldflags-y',
    			};
    
    			WARN("DEPRECATED_VARIABLE",
    			     "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag});
    
    # check for DT compatible documentation
    		if (defined $root && $realfile =~ /\.dts/ &&
    		    $rawline =~ /^\+\s*compatible\s*=/) {
    			my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
    
    			foreach my $compat (@compats) {
    				my $compat2 = $compat;
    				my $dt_path =  $root . "/Documentation/devicetree/bindings/";
    				$compat2 =~ s/\,[a-z]*\-/\,<\.\*>\-/;
    				`grep -Erq "$compat|$compat2" $dt_path`;
    				if ( $? >> 8 ) {
    					WARN("UNDOCUMENTED_DT_STRING",
    					     "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr);
    				}
    
    				my $vendor = $compat;
    				my $vendor_path = $dt_path . "vendor-prefixes.txt";
    				next if (! -f $vendor_path);
    				$vendor =~ s/^([a-zA-Z0-9]+)\,.*/$1/;
    				`grep -Eq "$vendor" $vendor_path`;
    				if ( $? >> 8 ) {
    					WARN("UNDOCUMENTED_DT_STRING",
    					     "DT compatible string vendor \"$vendor\" appears un-documented -- check $vendor_path\n" . $herecurr);
    				}
    			}
    		}
    
    
    # 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 !~ /\/\*\*/ &&
    		    $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
    		    !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:|,|\)\s*;)\s*$/ ||
    		    $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
    
    		    $length > $max_line_length)
    
    			     "line over $max_line_length characters\n" . $herecurr);
    		}
    
    # Check for user-visible strings broken across lines, which breaks the ability
    
    # to grep for the string.  Make exceptions when the previous string ends in a
    # newline (multiple lines in one string constant) or '\t', '\r', ';', or '{'
    # (common in inline assembly) or is a octal \123 or hexadecimal \xaf value
    
    		if ($line =~ /^\+\s*"/ &&
    		    $prevline =~ /"\s*$/ &&
    
    		    $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) {
    
    			WARN("SPLIT_STRING",
    			     "quoted string split across lines\n" . $hereprev);
    
    		}
    
    # check for spaces before a quoted newline
    		if ($rawline =~ /^.*\".*\s\\n/) {
    
    			if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
    				 "unnecessary whitespace before a quoted newline\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/^(\+.*\".*)\s+\\n/$1\\n/;
    			}
    
    
    		}
    
    # check for adding lines without a newline.
    		if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
    			WARN("MISSING_EOF_NEWLINE",
    			     "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("LO_MACRO",
    				      "use the LO() macro, not (... & 0xFFFF)\n" . $herevet);
    			}
    			if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) {
    				my $herevet = "$here\n" . cat_vet($line) . "\n";
    				ERROR("HI_MACRO",
    				      "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";
    			$rpt_cleaners = 1;
    
    			if (ERROR("CODE_INDENT",
    				  "code indent should use tabs where possible\n" . $herevet) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
    			}
    
    		}
    
    # check for space before tabs.
    		if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
    			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
    
    			if (WARN("SPACE_BEFORE_TAB",
    				"please, no space before tabs\n" . $herevet) &&
    			    $fix) {
    				while ($fixed[$linenr - 1] =~
    
    					   s/(^\+.*) {8,8}\t/$1\t\t/) {}
    
    				while ($fixed[$linenr - 1] =~
    					   s/(^\+.*) +\t/$1\t/) {}
    			}
    
    # check for && or || at the start of a line
    		if ($rawline =~ /^\+\s*(&&|\|\|)/) {
    			CHK("LOGICAL_CONTINUATIONS",
    			    "Logical continuations should be on the previous line\n" . $hereprev);
    		}
    
    # check multi-line statement indentation matches previous line
    		if ($^V && $^V ge 5.10.0 &&
    		    $prevline =~ /^\+(\t*)(if \(|$Ident\().*(\&\&|\|\||,)\s*$/) {
    			$prevline =~ /^\+(\t*)(.*)$/;
    			my $oldindent = $1;
    			my $rest = $2;
    
    			my $pos = pos_last_openparen($rest);
    			if ($pos >= 0) {
    				$line =~ /^(\+| )([ \t]*)/;
    				my $newindent = $2;
    
    				my $goodtabindent = $oldindent .
    					"\t" x ($pos / 8) .
    					" "  x ($pos % 8);
    				my $goodspaceindent = $oldindent . " "  x $pos;
    
    				if ($newindent ne $goodtabindent &&
    				    $newindent ne $goodspaceindent) {
    
    
    					if (CHK("PARENTHESIS_ALIGNMENT",
    						"Alignment should match open parenthesis\n" . $hereprev) &&
    					    $fix && $line =~ /^\+/) {
    						$fixed[$linenr - 1] =~
    						    s/^\+[ \t]*/\+$goodtabindent/;
    					}
    
    		if ($line =~ /^\+.*\*[ \t]*\)[ \t]+(?!$Assignment|$Arithmetic)/) {
    			if (CHK("SPACING",
    				"No space is necessary after a cast\n" . $hereprev) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/^(\+.*\*[ \t]*\))[ \t]+/$1/;
    			}
    
    		}
    
    		if ($realfile =~ m@^(drivers/net/|net/)@ &&
    
    		    $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
    		    $rawline =~ /^\+[ \t]*\*/) {
    
    			WARN("NETWORKING_BLOCK_COMMENT_STYLE",
    			     "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
    		}
    
    
    		if ($realfile =~ m@^(drivers/net/|net/)@ &&
    		    $prevrawline =~ /^\+[ \t]*\/\*/ &&		#starting /*
    		    $prevrawline !~ /\*\/[ \t]*$/ &&		#no trailing */
    		    $rawline =~ /^\+/ &&			#line is new
    		    $rawline !~ /^\+[ \t]*\*/) {		#no leading *
    			WARN("NETWORKING_BLOCK_COMMENT_STYLE",
    			     "networking block comments start with * on subsequent lines\n" . $hereprev);
    		}
    
    
    		if ($realfile =~ m@^(drivers/net/|net/)@ &&
    		    $rawline !~ m@^\+[ \t]*\*/[ \t]*$@ &&	#trailing */
    		    $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ &&	#inline /*...*/
    		    $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ &&	#trailing **/
    		    $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {	#non blank */
    			WARN("NETWORKING_BLOCK_COMMENT_STYLE",
    			     "networking block comments put the trailing */ on a separate line\n" . $herecurr);
    		}
    
    
    # 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";
    
    			if (WARN("LEADING_SPACE",
    				 "please, no spaces at the start of a line\n" . $herevet) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
    			}
    
    		}
    
    # check we are in a valid C source file if not then ignore this hunk
    		next if ($realfile !~ /\.(h|c)$/);
    
    
    # discourage the addition of CONFIG_EXPERIMENTAL in #if(def).
    		if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) {
    			WARN("CONFIG_EXPERIMENTAL",
    			     "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n");
    		}
    
    
    # check for RCS/CVS revision markers
    		if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
    			WARN("CVS_KEYWORD",
    			     "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("CSYNC",
    			      "use the CSYNC() macro in asm/blackfin.h\n" . $herevet);
    		}
    		if ($line =~ /__builtin_bfin_ssync/) {
    			my $herevet = "$here\n" . cat_vet($line) . "\n";
    			ERROR("SSYNC",
    			      "use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
    		}
    
    
    # check for old HOTPLUG __dev<foo> section markings
    		if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) {
    			WARN("HOTPLUG_SECTION",
    			     "Using $1 is unnecessary\n" . $herecurr);
    		}
    
    
    # Check for potential 'bare' types
    		my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
    		    $realline_next);
    
    #print "LINE<$line>\n";
    		if ($linenr >= $suppress_statement &&
    
    		    $realcnt && $sline =~ /.\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;
    
    
    #print "linenr<$linenr> <$stat>\n";
    			# If this statement has no statement boundaries within
    			# it there is no point in retrying a statement scan
    			# until we hit end of it.
    			my $frag = $stat; $frag =~ s/;+\s*$//;
    			if ($frag !~ /(?:{|;)/) {
    #print "skip<$line_nr_next>\n";
    				$suppress_statement = $line_nr_next;
    			}
    
    
    			# 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 goto labels.
    			if ($s =~ /$Ident:\*$/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) {
    				possible($1, "B:" . $s);
    			}
    
    			# any (foo ... *) is a pointer cast, and foo is a type
    			while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) {
    				possible($1, "C:" . $s);
    			}
    
    			# 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);
    
    				my $ctx = $s;
    				substr($ctx, 0, $name_len + 1, '');
    				$ctx =~ s/\)[^\)]*$//;
    
    				for my $arg (split(/\s*,\s*/, $ctx)) {
    					if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) {
    
    						possible($1, "D:" . $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_CASE_INDENT_LEVEL",
    				      "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 $pre_ctx = "$1$2";
    
    			my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
    
    
    			if ($line =~ /^\+\t{6,}/) {
    				WARN("DEEP_INDENTATION",
    				     "Too many leading tabs - consider code refactoring\n" . $herecurr);
    			}
    
    
    			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] !~ /^-/);
    				$ctx_ln++;
    			}
    
    			#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("OPEN_BRACE",
    				      "that open brace { should be on the previous line\n" .
    					"$here\n$ctx\n$rawlines[$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",
    					     "trailing semicolon indicates no statements, indent implies otherwise\n" .
    						"$here\n$ctx\n$rawlines[$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*/) {
    
    			($stat, $cond, $line_nr_next, $remain_next, $off_next) =
    				ctx_statement_block($linenr, $realcnt, 0)
    					if (!defined $stat);
    
    			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;
    			}
    			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;
    			}
    
    			my $cond_ptr = -1;
    			$continuation = 0;
    			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;
    				}
    
    				# Ignore:
    				#  1) blank lines, they should be at 0,
    				#  2) preprocessor lines, and
    				#  3) labels.
    				if ($continuation ||
    				    $s =~ /^\s*?\n/ ||
    				    $s =~ /^\s*#\s*?/ ||
    				    $s =~ /^\s*$Ident\s*:/) {
    					$continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
    					if ($s =~ s/^.*?\n//) {
    						$cond_lines++;
    					}
    				}
    			}
    
    			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";
    			}
    
    			#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",
    				     "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
    
    		next if ($line =~ /^[^\+]/);
    
    
    # TEST: allow direct testing of the type matcher.
    		if ($dbg_type) {
    			if ($line =~ /^.\s*$Declare\s*$/) {
    				ERROR("TEST_TYPE",
    				      "TEST: is type\n" . $herecurr);
    			} elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
    				ERROR("TEST_NOT_TYPE",
    				      "TEST: is not type ($1 is)\n". $herecurr);
    			}
    			next;
    		}
    # TEST: allow direct testing of the attribute matcher.
    		if ($dbg_attr) {
    			if ($line =~ /^.\s*$Modifier\s*$/) {
    				ERROR("TEST_ATTR",
    				      "TEST: is attr\n" . $herecurr);
    			} elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
    				ERROR("TEST_NOT_ATTR",
    				      "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("OPEN_BRACE",
    			      "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",
    
    				      "malformed #include filename\n" . $herecurr);
    			}
    			if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) {
    				ERROR("UAPI_INCLUDE",
    				      "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr);
    
    			}
    		}
    
    # no C99 // comments
    		if ($line =~ m{//}) {
    
    			if (ERROR("C99_COMMENTS",
    				  "do not use C99 // comments\n" . $herecurr) &&
    			    $fix) {
    				my $line = $fixed[$linenr - 1];
    				if ($line =~ /\/\/(.*)$/) {
    					my $comment = trim($1);
    					$fixed[$linenr - 1] =~ s@\/\/(.*)$@/\* $comment \*/@;
    				}
    			}
    
    		}
    		# Remove C99 comments.
    		$line =~ s@//.*@@;
    		$opline =~ s@//.*@@;
    
    # 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.*\((.*)\)/)) {
    			# Handle definitions which produce identifiers with
    			# a prefix:
    			#   XXX(foo);
    			#   EXPORT_SYMBOL(something_foo);
    			my $name = $1;
    
    			if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ &&
    
    			    $name =~ /^${Ident}_$2/) {
    #print "FOO C name<$name>\n";
    				$suppress_export{$realline_next} = 1;
    
    			} elsif ($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*(?:;|=|\[|\()
    			    )/x) {
    #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",
    			     "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
    		}
    
    # check for global initialisers.
    
    		if ($line =~ /^\+(\s*$Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/) {
    			if (ERROR("GLOBAL_INITIALISERS",
    				  "do not initialise globals to 0 or NULL\n" .
    				      $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/($Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/$1;/;
    			}
    
    		}
    # check for static initialisers.
    
    		if ($line =~ /^\+.*\bstatic\s.*=\s*(0|NULL|false)\s*;/) {
    			if (ERROR("INITIALISED_STATIC",
    				  "do not initialise statics to 0 or NULL\n" .
    				      $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/(\bstatic\s.*?)\s*=\s*(0|NULL|false)\s*;/$1;/;
    			}
    
    		}
    
    # check for static const char * arrays.
    		if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
    			WARN("STATIC_CONST_CHAR_ARRAY",
    			     "static const char * array should probably be static const char * const\n" .
    				$herecurr);
                   }
    
    # check for static char foo[] = "bar" declarations.
    		if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
    			WARN("STATIC_CONST_CHAR_ARRAY",
    			     "static char array declaration should probably be static const char\n" .
    				$herecurr);
                   }
    
    
    # check for function declarations without arguments like "int foo()"
    		if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) {
    			if (ERROR("FUNCTION_WITHOUT_ARGS",
    				  "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
    			}
    		}
    
    # check for uses of DEFINE_PCI_DEVICE_TABLE
    		if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) {
    			if (WARN("DEFINE_PCI_DEVICE_TABLE",
    				 "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /;
    			}
    
    		}
    
    # 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("NEW_TYPEDEFS",
    			     "do not add new typedefs\n" . $herecurr);
    		}
    
    # * goes on variable not on type
    		# (char*[ const])
    
    		while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) {
    			#print "AA<$1>\n";
    
    			my ($ident, $from, $to) = ($1, $2, $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+\*/\*\*/) {
    			}
    
    
    ##			print "1: from<$from> to<$to> ident<$ident>\n";
    
    			if ($from ne $to) {
    
    				if (ERROR("POINTER_LOCATION",
    					  "\"(foo$from)\" should be \"(foo$to)\"\n" .  $herecurr) &&
    				    $fix) {
    					my $sub_from = $ident;
    					my $sub_to = $ident;
    					$sub_to =~ s/\Q$from\E/$to/;
    					$fixed[$linenr - 1] =~
    					    s@\Q$sub_from\E@$sub_to@;
    				}
    
    		}
    		while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) {
    			#print "BB<$1>\n";
    
    			my ($match, $from, $to, $ident) = ($1, $2, $2, $3);
    
    
    			# 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 "2: from<$from> to<$to> ident<$ident>\n";
    
    			if ($from ne $to && $ident !~ /^$Modifier$/) {
    
    				if (ERROR("POINTER_LOCATION",
    					  "\"foo${from}bar\" should be \"foo${to}bar\"\n" .  $herecurr) &&
    				    $fix) {
    
    					my $sub_from = $match;
    					my $sub_to = $match;
    					$sub_to =~ s/\Q$from\E/$to/;
    					$fixed[$linenr - 1] =~
    					    s@\Q$sub_from\E@$sub_to@;
    				}
    
    			}
    		}
    
    # # 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",
    			     "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
    		}
    
    # check for uses of printk_ratelimit
    		if ($line =~ /\bprintk_ratelimit\s*\(/) {
    			WARN("PRINTK_RATELIMITED",
    "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\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 preceding 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 preceding 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_WITHOUT_KERN_LEVEL",
    				     "printk() should include KERN_ facility level\n" . $herecurr);
    			}
    		}
    
    
    		if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) {
    			my $orig = $1;
    			my $level = lc($orig);
    			$level = "warn" if ($level eq "warning");
    			my $level2 = $level;
    			$level2 = "dbg" if ($level eq "debug");
    			WARN("PREFER_PR_LEVEL",
    			     "Prefer netdev_$level2(netdev, ... then dev_$level2(dev, ... then pr_$level(...  to printk(KERN_$orig ...\n" . $herecurr);
    		}
    
    		if ($line =~ /\bpr_warning\s*\(/) {
    
    			if (WARN("PREFER_PR_LEVEL",
    				 "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/\bpr_warning\b/pr_warn/;
    			}
    
    		}
    
    		if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
    			my $orig = $1;
    			my $level = lc($orig);
    			$level = "warn" if ($level eq "warning");
    			$level = "dbg" if ($level eq "debug");
    			WARN("PREFER_DEV_LEVEL",
    			     "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\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",
    			      "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",
    			      "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){1,2}[=\{]/) {
    			if (WARN("SPACING",
    				 "missing space after $1 definition\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/;
    			}
    		}
    
    # Function pointer declarations
    # check spacing between type, funcptr, and args
    # canonical declaration is "type (*funcptr)(args...)"
    #
    # the $Declare variable will capture all spaces after the type
    # so check it for trailing missing spaces or multiple spaces
    		if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)$Ident(\s*)\)(\s*)\(/) {
    			my $declare = $1;
    			my $pre_pointer_space = $2;
    			my $post_pointer_space = $3;
    			my $funcname = $4;
    			my $post_funcname_space = $5;
    			my $pre_args_space = $6;
    
    			if ($declare !~ /\s$/) {
    				WARN("SPACING",
    				     "missing space after return type\n" . $herecurr);
    			}
    
    # unnecessary space "type  (*funcptr)(args...)"
    			elsif ($declare =~ /\s{2,}$/) {
    				WARN("SPACING",
    				     "Multiple spaces after return type\n" . $herecurr);
    			}
    
    # unnecessary space "type ( *funcptr)(args...)"
    			if (defined $pre_pointer_space &&
    			    $pre_pointer_space =~ /^\s/) {
    				WARN("SPACING",
    				     "Unnecessary space after function pointer open parenthesis\n" . $herecurr);
    			}
    
    # unnecessary space "type (* funcptr)(args...)"
    			if (defined $post_pointer_space &&
    			    $post_pointer_space =~ /^\s/) {
    				WARN("SPACING",
    				     "Unnecessary space before function pointer name\n" . $herecurr);
    			}
    
    # unnecessary space "type (*funcptr )(args...)"
    			if (defined $post_funcname_space &&
    			    $post_funcname_space =~ /^\s/) {
    				WARN("SPACING",
    				     "Unnecessary space after function pointer name\n" . $herecurr);
    			}
    
    # unnecessary space "type (*funcptr) (args...)"
    			if (defined $pre_args_space &&
    			    $pre_args_space =~ /^\s/) {
    				WARN("SPACING",
    				     "Unnecessary space before function pointer arguments\n" . $herecurr);
    			}
    
    			if (show_type("SPACING") && $fix) {
    				$fixed[$linenr - 1] =~
    				    s/^(.\s*$Declare)\(\s*\*\s*($Ident)\s*\)\s*\(/rtrim($1) . " " . "\(\*$2\)\("/ex;
    			}
    
    		}
    
    # 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+$/) {
    
    				if (ERROR("BRACKET_SPACE",