Skip to content
Snippets Groups Projects
checkpatch.pl 118 KiB
Newer Older
  • Learn to ignore specific revisions
  • 							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
    
    					}
    					if ($ctx =~ /Wx[BE]/ ||
    					    ($ctx =~ /Wx./ && $cc =~ /^;/)) {
    
    						if (ERROR("SPACING",
    							  "space prohibited before that '$op' $at\n" . $hereptr)) {
    
    							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
    
    					if ($ctx =~ /ExW/) {
    
    						if (ERROR("SPACING",
    							  "space prohibited after that '$op' $at\n" . $hereptr)) {
    
    							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
    
    							if (defined $fix_elements[$n + 2]) {
    								$fix_elements[$n + 2] =~ s/^\s+//;
    							}
    
    							$line_fixed = 1;
    
    
    				# << and >> may either have or not have spaces both sides
    
    				} elsif ($op eq '<<' or $op eq '>>' or
    					 $op eq '&' or $op eq '^' or $op eq '|' or
    					 $op eq '+' or $op eq '-' or
    
    					 $op eq '*' or $op eq '/' or
    					 $op eq '%')
    
    					if ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
    
    						if (ERROR("SPACING",
    							  "need consistent spacing around '$op' $at\n" . $hereptr)) {
    
    							$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
    							if (defined $fix_elements[$n + 2]) {
    								$fix_elements[$n + 2] =~ s/^\s+//;
    							}
    
    				# A colon needs no spaces before when it is
    				# terminating a case value or a label.
    				} elsif ($opv eq ':C' || $opv eq ':L') {
    					if ($ctx =~ /Wx./) {
    
    						if (ERROR("SPACING",
    							  "space prohibited before that '$op' $at\n" . $hereptr)) {
    
    							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
    
    				# All the others need spaces both sides.
    
    				} elsif ($ctx !~ /[EWC]x[CWE]/) {
    
    					# Ignore email addresses <foo@bar>
    
    					if (($op eq '<' &&
    					     $cc =~ /^\S+\@\S+>/) ||
    					    ($op eq '>' &&
    					     $ca =~ /<\S+\@\S+$/))
    					{
    					    	$ok = 1;
    					}
    
    
    					# messages are ERROR, but ?: are CHK
    
    						my $msg_type = \&ERROR;
    						$msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
    
    						if (&{$msg_type}("SPACING",
    								 "spaces required around that '$op' $at\n" . $hereptr)) {
    
    							$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
    							if (defined $fix_elements[$n + 2]) {
    								$fix_elements[$n + 2] =~ s/^\s+//;
    							}
    
    				$off += length($elements[$n + 1]);
    
    
    ##				print("n: <$n> GOOD: <$good>\n");
    
    				$fixed_line = $fixed_line . $good;
    			}
    
    			if (($#elements % 2) == 0) {
    				$fixed_line = $fixed_line . $fix_elements[$#elements];
    
    
    			if ($fix && $line_fixed && $fixed_line ne $fixed[$linenr - 1]) {
    				$fixed[$linenr - 1] = $fixed_line;
    			}
    
    
    
    # check for whitespace before a non-naked semicolon
    		if ($line =~ /^\+.*\S\s+;/) {
    			if (WARN("SPACING",
    				 "space prohibited before semicolon\n" . $herecurr) &&
    			    $fix) {
    				1 while $fixed[$linenr - 1] =~
    				    s/^(\+.*\S)\s+;/$1;/;
    			}
    		}
    
    
    # check for multiple assignments
    		if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
    
    			CHK("MULTIPLE_ASSIGNMENTS",
    			    "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.*/) {
    ##
    ## 			# Remove any bracketed sections to ensure we do not
    ## 			# falsly report the parameters of functions.
    ## 			my $ln = $line;
    ## 			while ($ln =~ s/\([^\(\)]*\)//g) {
    ## 			}
    ## 			if ($ln =~ /,/) {
    
    ## 				WARN("MULTIPLE_DECLARATION",
    ##				     "declaring multiple variables together should be avoided\n" . $herecurr);
    
    #need space before brace following if, while, etc
    
    		if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) ||
    		    $line =~ /do{/) {
    
    			if (ERROR("SPACING",
    				  "space required before the open brace '{'\n" . $herecurr) &&
    			    $fix) {
    
    				$fixed[$linenr - 1] =~ s/^(\+.*(?:do|\))){/$1 {/;
    
    ## # check for blank lines before declarations
    ##		if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ &&
    ##		    $prevrawline =~ /^.\s*$/) {
    ##			WARN("SPACING",
    ##			     "No blank lines before declarations\n" . $hereprev);
    ##		}
    ##
    
    
    # closing brace should have a space following it when it has anything
    # on the line
    		if ($line =~ /}(?!(?:,|;|\)))\S/) {
    
    			if (ERROR("SPACING",
    				  "space required after that close brace '}'\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/}((?!(?:,|;|\)))\S)/} $1/;
    			}
    
    # check spacing on square brackets
    		if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
    
    			if (ERROR("SPACING",
    				  "space prohibited after that open square bracket '['\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/\[\s+/\[/;
    			}
    
    		}
    		if ($line =~ /\s\]/) {
    
    			if (ERROR("SPACING",
    				  "space prohibited before that close square bracket ']'\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/\s+\]/\]/;
    			}
    
    # check spacing on parentheses
    
    		if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
    		    $line !~ /for\s*\(\s+;/) {
    
    			if (ERROR("SPACING",
    				  "space prohibited after that open parenthesis '('\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/\(\s+/\(/;
    			}
    
    		if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
    
    		    $line !~ /for\s*\(.*;\s+\)/ &&
    		    $line !~ /:\s+\)/) {
    
    			if (ERROR("SPACING",
    				  "space prohibited before that close parenthesis ')'\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/\s+\)/\)/;
    			}
    
    #goto labels aren't indented, allow a single space however
    
    		if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
    
    		   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
    
    			if (WARN("INDENTED_LABEL",
    				 "labels should not be indented\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/^(.)\s+/$1/;
    			}
    
    # Return is not a function.
    		if (defined($stat) && $stat =~ /^.\s*return(\s*)(\(.*);/s) {
    			my $spacing = $1;
    			my $value = $2;
    
    
    			# Flatten any parentheses
    
    			$value =~ s/\(/ \(/g;
    			$value =~ s/\)/\) /g;
    
    			while ($value =~ s/\[[^\[\]]*\]/1/ ||
    
    			       $value !~ /(?:$Ident|-?$Constant)\s*
    					     $Compare\s*
    					     (?:$Ident|-?$Constant)/x &&
    			       $value =~ s/\([^\(\)]*\)/1/) {
    
    #print "value<$value>\n";
    			if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
    
    				ERROR("RETURN_PARENTHESES",
    				      "return is not a function, parentheses are not required\n" . $herecurr);
    
    
    			} elsif ($spacing !~ /\s+/) {
    
    				ERROR("SPACING",
    				      "space required before the open parenthesis '('\n" . $herecurr);
    
    # Return of what appears to be an errno should normally be -'ve
    		if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
    			my $name = $1;
    			if ($name ne 'EOF' && $name ne 'ERROR') {
    
    				WARN("USE_NEGATIVE_ERRNO",
    				     "return of an errno should typically be -ve (return -$1)\n" . $herecurr);
    
    # Need a space before open parenthesis after if, while etc
    
    		if ($line =~ /\b(if|while|for|switch)\(/) {
    			if (ERROR("SPACING",
    				  "space required before the open parenthesis '('\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/\b(if|while|for|switch)\(/$1 \(/;
    			}
    
    # Check for illegal assignment in if conditional -- and check for trailing
    # statements after the conditional.
    
    			($stat, $cond, $line_nr_next, $remain_next, $off_next) =
    				ctx_statement_block($linenr, $realcnt, 0)
    					if (!defined $stat);
    
    			my ($stat_next) = ctx_statement_block($line_nr_next,
    						$remain_next, $off_next);
    			$stat_next =~ s/\n./\n /g;
    			##print "stat<$stat> stat_next<$stat_next>\n";
    
    			if ($stat_next =~ /^\s*while\b/) {
    				# If the statement carries leading newlines,
    				# then count those as offsets.
    				my ($whitespace) =
    					($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
    				my $offset =
    					statement_rawlines($whitespace) - 1;
    
    				$suppress_whiletrailers{$line_nr_next +
    								$offset} = 1;
    			}
    		}
    		if (!defined $suppress_whiletrailers{$linenr} &&
    		    $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
    
    			my ($s, $c) = ($stat, $cond);
    
    			if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
    
    				ERROR("ASSIGN_IN_IF",
    				      "do not use assignment in if condition\n" . $herecurr);
    
    			}
    
    			# Find out what is on the end of the line after the
    			# conditional.
    
    			substr($s, 0, length($c), '');
    
    			$s =~ s/\n.*//g;
    
    			$s =~ s/$;//g; 	# Remove any comments
    
    			if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
    			    $c !~ /}\s*while\s*/)
    
    				# Find out how long the conditional actually is.
    				my @newlines = ($c =~ /\n/gs);
    				my $cond_lines = 1 + $#newlines;
    
    				$stat_real = raw_line($linenr, $cond_lines)
    							. "\n" if ($cond_lines);
    
    				if (defined($stat_real) && $cond_lines > 1) {
    					$stat_real = "[...]\n$stat_real";
    				}
    
    
    				ERROR("TRAILING_STATEMENTS",
    				      "trailing statements should be on next line\n" . $herecurr . $stat_real);
    
    # Check for bitwise tests written as boolean
    		if ($line =~ /
    			(?:
    				(?:\[|\(|\&\&|\|\|)
    				\s*0[xX][0-9]+\s*
    				(?:\&\&|\|\|)
    			|
    				(?:\&\&|\|\|)
    				\s*0[xX][0-9]+\s*
    				(?:\&\&|\|\||\)|\])
    			)/x)
    		{
    
    			WARN("HEXADECIMAL_BOOLEAN_TEST",
    			     "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
    
    # if and else should not have general statements after it
    
    		if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
    			my $s = $1;
    			$s =~ s/$;//g; 	# Remove any comments
    			if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
    
    				ERROR("TRAILING_STATEMENTS",
    				      "trailing statements should be on next line\n" . $herecurr);
    
    # if should not continue a brace
    		if ($line =~ /}\s*if\b/) {
    
    			ERROR("TRAILING_STATEMENTS",
    			      "trailing statements should be on next line\n" .
    
    # case and default should not have general statements after them
    		if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
    		    $line !~ /\G(?:
    
    			(?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
    
    			ERROR("TRAILING_STATEMENTS",
    			      "trailing statements should be on next line\n" . $herecurr);
    
    
    		# Check for }<nl>else {, these must be at the same
    		# indent level to be relevant to each other.
    		if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
    						$previndent == $indent) {
    
    			ERROR("ELSE_AFTER_BRACE",
    			      "else should follow close brace '}'\n" . $hereprev);
    
    		if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and
    						$previndent == $indent) {
    			my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
    
    			# Find out what is on the end of the line after the
    			# conditional.
    
    			substr($s, 0, length($c), '');
    
    			$s =~ s/\n.*//g;
    
    			if ($s =~ /^\s*;/) {
    
    				ERROR("WHILE_AFTER_BRACE",
    				      "while should follow close brace '}'\n" . $hereprev);
    
    		while ($line =~ m{($Constant|$Lval)}g) {
    			my $var = $1;
    
    
    #gcc binary extension
    			if ($var =~ /^$Binary$/) {
    
    				if (WARN("GCC_BINARY_CONSTANT",
    					 "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) &&
    				    $fix) {
    					my $hexval = sprintf("0x%x", oct($var));
    					$fixed[$linenr - 1] =~
    					    s/\b$var\b/$hexval/;
    				}
    
    			if ($var !~ /^$Constant$/ &&
    
    			    $var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
    
    #Ignore Page<foo> variants
    
    			    $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
    
    #Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show)
    
    			    $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/) {
    
    				while ($var =~ m{($Ident)}g) {
    					my $word = $1;
    					next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
    
    					if ($check) {
    						seed_camelcase_includes();
    						if (!$file && !$camelcase_file_seeded) {
    							seed_camelcase_file($realfile);
    							$camelcase_file_seeded = 1;
    						}
    					}
    
    					if (!defined $camelcase{$word}) {
    						$camelcase{$word} = 1;
    						CHK("CAMELCASE",
    						    "Avoid CamelCase: <$word>\n" . $herecurr);
    					}
    
    
    #no spaces allowed after \ in define
    
    		if ($line =~ /\#\s*define.*\\\s+$/) {
    			if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
    				 "Whitespace after \\ makes next lines useless\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/\s+$//;
    			}
    
    #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
    
    		if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
    
    			my $file = "$1.h";
    			my $checkfile = "include/linux/$file";
    			if (-f "$root/$checkfile" &&
    			    $realfile ne $checkfile &&
    
    			    $1 !~ /$allowed_asm_includes/)
    
    					CHK("ARCH_INCLUDE_LINUX",
    					    "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
    
    					WARN("INCLUDE_LINUX",
    					     "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
    
    # multi-statement macros should be enclosed in a do while loop, grab the
    # first statement and ensure its the whole macro if its not enclosed
    
    # in a known good container
    
    		if ($realfile !~ m@/vmlinux.lds.h$@ &&
    		    $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
    
    			my $ln = $linenr;
    			my $cnt = $realcnt;
    
    			my ($off, $dstat, $dcond, $rest);
    			my $ctx = '';
    			($dstat, $dcond, $ln, $cnt, $off) =
    
    				ctx_statement_block($linenr, $realcnt, 0);
    			$ctx = $dstat;
    
    			#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
    
    			#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
    
    			$dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//;
    
    			$dstat =~ s/\\\n.//g;
    			$dstat =~ s/^\s*//s;
    			$dstat =~ s/\s*$//s;
    
    			# Flatten any parentheses and braces
    
    			while ($dstat =~ s/\([^\(\)]*\)/1/ ||
    			       $dstat =~ s/\{[^\{\}]*\}/1/ ||
    
    			       $dstat =~ s/\[[^\[\]]*\]/1/)
    
    			# Flatten any obvious string concatentation.
    			while ($dstat =~ s/("X*")\s*$Ident/$1/ ||
    			       $dstat =~ s/$Ident\s*("X*")/$1/)
    			{
    			}
    
    
    			my $exceptions = qr{
    				$Declare|
    				module_param_named|
    
    				MODULE_PARM_DESC|
    
    				DECLARE_PER_CPU|
    				DEFINE_PER_CPU|
    
    			#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
    
    			if ($dstat ne '' &&
    			    $dstat !~ /^(?:$Ident|-?$Constant),$/ &&			# 10, // foo(),
    			    $dstat !~ /^(?:$Ident|-?$Constant);$/ &&			# foo();
    
    			    $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ &&		# 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz
    
    			    $dstat !~ /^'X'$/ &&					# character constants
    
    			    $dstat !~ /$exceptions/ &&
    			    $dstat !~ /^\.$Ident\s*=/ &&				# .foo =
    
    			    $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ &&		# stringification #foo
    
    			    $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ &&	# do {...} while (...); // do {...} while (...)
    
    			    $dstat !~ /^for\s*$Constant$/ &&				# for (...)
    			    $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ &&	# for (...) bar()
    			    $dstat !~ /^do\s*{/ &&					# do {...
    
    			    $dstat !~ /^\({/ &&						# ({...
    			    $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
    
    			{
    				$ctx =~ s/\n*$//;
    				my $herectx = $here . "\n";
    				my $cnt = statement_rawlines($ctx);
    
    				for (my $n = 0; $n < $cnt; $n++) {
    					$herectx .= raw_line($linenr, $n) . "\n";
    
    				if ($dstat =~ /;/) {
    					ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
    					      "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
    				} else {
    
    					ERROR("COMPLEX_MACRO",
    
    					      "Macros with complex values should be enclosed in parenthesis\n" . "$herectx");
    
    # check for line continuations outside of #defines, preprocessor #, and asm
    
    
    		} else {
    			if ($prevline !~ /^..*\\$/ &&
    
    			    $line !~ /^\+\s*\#.*\\$/ &&		# preprocessor
    			    $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ &&	# asm
    
    			    $line =~ /^\+.*\\$/) {
    				WARN("LINE_CONTINUATIONS",
    				     "Avoid unnecessary line continuations\n" . $herecurr);
    			}
    
    # do {} while (0) macro tests:
    # single-statement macros do not need to be enclosed in do while (0) loop,
    # macro should not end with a semicolon
    		if ($^V && $^V ge 5.10.0 &&
    		    $realfile !~ m@/vmlinux.lds.h$@ &&
    		    $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {
    			my $ln = $linenr;
    			my $cnt = $realcnt;
    			my ($off, $dstat, $dcond, $rest);
    			my $ctx = '';
    			($dstat, $dcond, $ln, $cnt, $off) =
    				ctx_statement_block($linenr, $realcnt, 0);
    			$ctx = $dstat;
    
    			$dstat =~ s/\\\n.//g;
    
    			if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) {
    				my $stmts = $2;
    				my $semis = $3;
    
    				$ctx =~ s/\n*$//;
    				my $cnt = statement_rawlines($ctx);
    				my $herectx = $here . "\n";
    
    				for (my $n = 0; $n < $cnt; $n++) {
    					$herectx .= raw_line($linenr, $n) . "\n";
    				}
    
    
    				if (($stmts =~ tr/;/;/) == 1 &&
    				    $stmts !~ /^\s*(if|while|for|switch)\b/) {
    
    					WARN("SINGLE_STATEMENT_DO_WHILE_MACRO",
    					     "Single statement macros should not use a do {} while (0) loop\n" . "$herectx");
    				}
    				if (defined $semis && $semis ne "") {
    					WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON",
    					     "do {} while (0) macros should not be semicolon terminated\n" . "$herectx");
    				}
    			}
    		}
    
    
    # make sure symbols are always wrapped with VMLINUX_SYMBOL() ...
    # all assignments may have only one of the following with an assignment:
    #	.
    #	ALIGN(...)
    #	VMLINUX_SYMBOL(...)
    		if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) {
    
    			WARN("MISSING_VMLINUX_SYMBOL",
    			     "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr);
    
    # check for redundant bracing round if etc
    
    		if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
    			my ($level, $endln, @chunks) =
    
    				ctx_statement_full($linenr, $realcnt, 1);
    
    			#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
    
    			#print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
    			if ($#chunks > 0 && $level == 0) {
    
    				my @allowed = ();
    				my $allow = 0;
    
    				my $seen = 0;
    
    				my $herectx = $here . "\n";
    
    				my $ln = $linenr - 1;
    
    				for my $chunk (@chunks) {
    					my ($cond, $block) = @{$chunk};
    
    
    					# If the condition carries leading newlines, then count those as offsets.
    					my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
    					my $offset = statement_rawlines($whitespace) - 1;
    
    
    					#print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
    
    					# We have looked at and allowed this specific line.
    					$suppress_ifbraces{$ln + $offset} = 1;
    
    					$herectx .= "$rawlines[$ln + $offset]\n[...]\n";
    
    					$ln += statement_rawlines($block) - 1;
    
    
    					substr($block, 0, length($cond), '');
    
    
    					$seen++ if ($block =~ /^\s*{/);
    
    
    					#print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n";
    
    					if (statement_lines($cond) > 1) {
    						#print "APW: ALLOWED: cond<$cond>\n";
    
    					}
    					if ($block =~/\b(?:if|for|while)\b/) {
    
    						#print "APW: ALLOWED: block<$block>\n";
    
    					if (statement_block_size($block) > 1) {
    						#print "APW: ALLOWED: lines block<$block>\n";
    
    				if ($seen) {
    					my $sum_allowed = 0;
    					foreach (@allowed) {
    						$sum_allowed += $_;
    					}
    					if ($sum_allowed == 0) {
    						WARN("BRACES",
    						     "braces {} are not necessary for any arm of this statement\n" . $herectx);
    					} elsif ($sum_allowed != $allow &&
    						 $seen != $allow) {
    						CHK("BRACES",
    						    "braces {} should be used on all arms of this statement\n" . $herectx);
    					}
    
    		if (!defined $suppress_ifbraces{$linenr - 1} &&
    
    					$line =~ /\b(if|while|for|else)\b/) {
    
    			my $allowed = 0;
    
    			# Check the pre-context.
    			if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
    				#print "APW: ALLOWED: pre<$1>\n";
    				$allowed = 1;
    			}
    
    
    			my ($level, $endln, @chunks) =
    				ctx_statement_full($linenr, $realcnt, $-[0]);
    
    
    			# Check the condition.
    			my ($cond, $block) = @{$chunks[0]};
    
    			#print "CHECKING<$linenr> cond<$cond> block<$block>\n";
    
    			if (defined $cond) {
    
    				substr($block, 0, length($cond), '');
    
    			}
    			if (statement_lines($cond) > 1) {
    				#print "APW: ALLOWED: cond<$cond>\n";
    				$allowed = 1;
    			}
    			if ($block =~/\b(?:if|for|while)\b/) {
    				#print "APW: ALLOWED: block<$block>\n";
    				$allowed = 1;
    			}
    			if (statement_block_size($block) > 1) {
    				#print "APW: ALLOWED: lines block<$block>\n";
    				$allowed = 1;
    			}
    			# Check the post-context.
    			if (defined $chunks[1]) {
    				my ($cond, $block) = @{$chunks[1]};
    				if (defined $cond) {
    
    					substr($block, 0, length($cond), '');
    
    				}
    				if ($block =~ /^\s*\{/) {
    					#print "APW: ALLOWED: chunk-1 block<$block>\n";
    					$allowed = 1;
    				}
    			}
    			if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
    
    				my $cnt = statement_rawlines($block);
    
    				for (my $n = 0; $n < $cnt; $n++) {
    
    					$herectx .= raw_line($linenr, $n) . "\n";
    
    				WARN("BRACES",
    				     "braces {} are not necessary for single statement blocks\n" . $herectx);
    
    # check for unnecessary blank lines around braces
    
    		if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) {
    
    			CHK("BRACES",
    			    "Blank lines aren't necessary before a close brace '}'\n" . $hereprev);
    		}
    
    		if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) {
    
    			CHK("BRACES",
    			    "Blank lines aren't necessary after an open brace '{'\n" . $hereprev);
    		}
    
    
    # no volatiles please
    
    		my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
    		if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
    
    			WARN("VOLATILE",
    			     "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
    
    # warn about #if 0
    
    		if ($line =~ /^.\s*\#\s*if\s+0\b/) {
    
    			CHK("REDUNDANT_CODE",
    			    "if this code is redundant consider removing it\n" .
    
    # check for needless "if (<foo>) fn(<foo>)" uses
    		if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) {
    			my $expr = '\s*\(\s*' . quotemeta($1) . '\s*\)\s*;';
    			if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?)$expr/) {
    				WARN('NEEDLESS_IF',
    				     "$1(NULL) is safe this check is probably not required\n" . $hereprev);
    
    sub string_find_replace {
    	my ($string, $find, $replace) = @_;
    
    	$string =~ s/$find/$replace/g;
    
    	return $string;
    }
    
    # check for bad placement of section $InitAttribute (e.g.: __initdata)
    		if ($line =~ /(\b$InitAttribute\b)/) {
    			my $attr = $1;
    			if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) {
    				my $ptr = $1;
    				my $var = $2;
    				if ((($ptr =~ /\b(union|struct)\s+$attr\b/ &&
    				      ERROR("MISPLACED_INIT",
    					    "$attr should be placed after $var\n" . $herecurr)) ||
    				     ($ptr !~ /\b(union|struct)\s+$attr\b/ &&
    				      WARN("MISPLACED_INIT",
    					   "$attr should be placed after $var\n" . $herecurr))) &&
    				    $fix) {
    					$fixed[$linenr - 1] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e;
    				}
    			}
    		}
    
    
    # prefer usleep_range over udelay
    
    		if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
    
    			# ignore udelay's < 10, however
    
    			if (! ($1 < 10) ) {
    
    				CHK("USLEEP_RANGE",
    				    "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line);
    
    # warn about unexpectedly long msleep's
    		if ($line =~ /\bmsleep\s*\((\d+)\);/) {
    			if ($1 < 20) {
    
    				WARN("MSLEEP",
    				     "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line);
    
    # check for comparisons of jiffies
    		if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
    			WARN("JIFFIES_COMPARISON",
    			     "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr);
    		}
    
    
    # check for comparisons of get_jiffies_64()
    		if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) {
    			WARN("JIFFIES_COMPARISON",
    			     "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr);
    		}
    
    
    # warn about #ifdefs in C files
    
    #		if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
    
    #			print "#ifdef in C files should be avoided\n";
    #			print "$herecurr";
    #			$clean = 0;
    #		}
    
    
    # warn about spacing in #ifdefs
    
    		if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
    
    			if (ERROR("SPACING",
    				  "exactly one space required after that #$1\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~
    				    s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /;
    			}
    
    
    # check for spinlock_t definitions without a comment.
    
    		if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
    		    $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
    
    			my $which = $1;
    			if (!ctx_has_comment($first_line, $linenr)) {
    
    				CHK("UNCOMMENTED_DEFINITION",
    				    "$1 definition without comment\n" . $herecurr);
    
    			}
    		}
    # check for memory barriers without a comment.
    		if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
    			if (!ctx_has_comment($first_line, $linenr)) {
    
    				CHK("MEMORY_BARRIER",
    				    "memory barrier without comment\n" . $herecurr);
    
    			}
    		}
    # check of hardware specific defines
    
    		if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
    
    			CHK("ARCH_DEFINES",
    			    "architecture specific defines should be avoided\n" .  $herecurr);
    
    # Check that the storage class is at the beginning of a declaration
    		if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) {
    
    			WARN("STORAGE_CLASS",
    			     "storage class should be at the beginning of the declaration\n" . $herecurr)
    
    # check the location of the inline attribute, that it is between
    # storage class and type.
    
    		if ($line =~ /\b$Type\s+$Inline\b/ ||
    		    $line =~ /\b$Inline\s+$Storage\b/) {
    
    			ERROR("INLINE_LOCATION",
    			      "inline keyword should sit between storage class and type\n" . $herecurr);
    
    # Check for __inline__ and __inline, prefer inline
    		if ($line =~ /\b(__inline__|__inline)\b/) {
    
    			if (WARN("INLINE",
    				 "plain inline is preferred over $1\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/\b(__inline__|__inline)\b/inline/;
    
    			}
    
    # Check for __attribute__ packed, prefer __packed
    		if ($line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
    
    			WARN("PREFER_PACKED",
    			     "__packed is preferred over __attribute__((packed))\n" . $herecurr);
    
    # Check for __attribute__ aligned, prefer __aligned
    		if ($line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
    
    			WARN("PREFER_ALIGNED",
    			     "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
    
    # Check for __attribute__ format(printf, prefer __printf
    		if ($line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
    
    			if (WARN("PREFER_PRINTF",
    				 "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
    
    			}
    
    # Check for __attribute__ format(scanf, prefer __scanf
    		if ($line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
    
    			if (WARN("PREFER_SCANF",
    				 "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
    			}
    
    # check for sizeof(&)
    		if ($line =~ /\bsizeof\s*\(\s*\&/) {
    
    			WARN("SIZEOF_ADDRESS",
    			     "sizeof(& should be avoided\n" . $herecurr);
    
    # check for sizeof without parenthesis
    		if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) {
    
    			if (WARN("SIZEOF_PARENTHESIS",
    				 "sizeof $1 should be sizeof($1)\n" . $herecurr) &&
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
    			}
    
    # check for line continuations in quoted strings with odd counts of "
    		if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) {
    
    			WARN("LINE_CONTINUATIONS",
    			     "Avoid line continuations in quoted strings\n" . $herecurr);
    
    # check for struct spinlock declarations
    		if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) {
    			WARN("USE_SPINLOCK_T",
    			     "struct spinlock should be spinlock_t\n" . $herecurr);
    		}
    
    
    # check for seq_printf uses that could be seq_puts
    		if ($line =~ /\bseq_printf\s*\(/) {
    			my $fmt = get_quoted_string($line, $rawline);
    			if ($fmt !~ /[^\\]\%/) {
    
    				if (WARN("PREFER_SEQ_PUTS",
    					 "Prefer seq_puts to seq_printf\n" . $herecurr) &&
    				    $fix) {
    					$fixed[$linenr - 1] =~ s/\bseq_printf\b/seq_puts/;
    				}
    
    		if ($^V && $^V ge 5.10.0 &&
    		    defined $stat &&
    
    		    $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/s) {
    
    			my $ms_addr = $2;
    
    			my $ms_val = $7;
    			my $ms_size = $12;
    
    
    			if ($ms_size =~ /^(0x|)0$/i) {
    				ERROR("MEMSET",
    
    				      "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n");
    
    			} elsif ($ms_size =~ /^(0x|)1$/i) {
    				WARN("MEMSET",
    
    				     "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n");
    			}
    		}
    
    # typecasts on min/max could be min_t/max_t
    
    		if ($^V && $^V ge 5.10.0 &&
    		    defined $stat &&
    
    		    $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
    
    			if (defined $2 || defined $7) {
    
    				my $call = $1;
    				my $cast1 = deparenthesize($2);
    				my $arg1 = $3;
    
    				my $cast2 = deparenthesize($7);
    				my $arg2 = $8;
    
    				if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) {
    
    					$cast = "$cast1 or $cast2";
    				} elsif ($cast1 ne "") {
    					$cast = $cast1;
    				} else {
    					$cast = $cast2;
    				}
    				WARN("MINMAX",
    				     "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n");
    
    # check usleep_range arguments
    		if ($^V && $^V ge 5.10.0 &&
    		    defined $stat &&
    		    $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
    			my $min = $1;
    			my $max = $7;
    			if ($min eq $max) {
    				WARN("USLEEP_RANGE",
    				     "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
    			} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
    				 $min > $max) {
    				WARN("USLEEP_RANGE",
    				     "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
    			}
    		}
    
    
    # check for new externs in .h files.
    		if ($realfile =~ /\.h$/ &&
    		    $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
    
    			if (CHK("AVOID_EXTERNS",
    				"extern prototypes should be avoided in .h files\n" . $herecurr) &&
    
    			    $fix) {
    				$fixed[$linenr - 1] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
    			}
    		}
    
    
    # check for new externs in .c files.
    
    		if ($realfile =~ /\.c$/ && defined $stat &&
    
    		    $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
    
    			my $function_name = $1;
    			my $paren_space = $2;
    
    
    			my $s = $stat;
    			if (defined $cond) {
    				substr($s, 0, length($cond), '');