Skip to content
Snippets Groups Projects
checkpatch.pl 121 KiB
Newer Older
  • Learn to ignore specific revisions
  • sub ctx_block_get {
    
    	my ($linenr, $remain, $outer, $open, $close, $off) = @_;
    
    	my $line;
    	my $start = $linenr - 1;
    	my $blk = '';
    	my @o;
    	my @c;
    	my @res = ();
    
    
    	my $level = 0;
    
    	for ($line = $start; $remain > 0; $line++) {
    		next if ($rawlines[$line] =~ /^-/);
    		$remain--;
    
    		$blk .= $rawlines[$line];
    
    		if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
    
    		} elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
    
    			$level = $stack[$#stack - 1];
    
    		} elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
    
    		foreach my $c (split(//, $lines[$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++;
    			}
    		}
    
    		if (!$outer || $level <= 1) {
    
    			push(@res, $rawlines[$line]);
    
    		last if ($level == 0);
    
    	return ($level, @res);
    
    }
    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;
    
    }
    sub ctx_statement {
    
    	my ($linenr, $remain, $off) = @_;
    
    	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
    	return @r;
    }
    sub ctx_block_level {
    
    	my ($linenr, $remain) = @_;
    
    
    	return ctx_block_get($linenr, $remain, 0, '{', '}', 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*(?:\\\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 raw_line {
    	my ($linenr, $cnt) = @_;
    
    	my $offset = $linenr - 1;
    	$cnt++;
    
    	my $line;
    	while ($cnt) {
    		$line = $rawlines[$offset++];
    		next if (defined($line) && $line =~ /^-/);
    		$cnt--;
    	}
    
    	return $line;
    }
    
    
    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;
    
    	$res =~ s/$/\$/;
    
    	return $res;
    
    my $av_preprocessor = 0;
    
    my $av_pending;
    
    my @av_paren_type;
    
    
    sub annotate_reset {
    	$av_preprocessor = 0;
    
    	$av_pending = '_';
    	@av_paren_type = ('E');
    
    sub annotate_values {
    	my ($stream, $type) = @_;
    
    	my $var = '_' x length($stream);
    
    	my $cur = $stream;
    
    
    	print "$stream\n" if ($dbg_values > 1);
    
    
    	while (length($cur)) {
    
    		@av_paren_type = ('E') if ($#av_paren_type < 0);
    
    		print " <" . join('', @av_paren_type) .
    
    				"> <$type> <$av_pending>" if ($dbg_values > 1);
    
    		if ($cur =~ /^(\s+)/o) {
    
    			print "WS($1)\n" if ($dbg_values > 1);
    			if ($1 =~ /\n/ && $av_preprocessor) {
    
    				$type = pop(@av_paren_type);
    
    				$av_preprocessor = 0;
    
    		} elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
    
    			print "CAST($1)\n" if ($dbg_values > 1);
    			push(@av_paren_type, $type);
    
    		} elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
    
    			print "DECLARE($1)\n" if ($dbg_values > 1);
    
    		} elsif ($cur =~ /^($Modifier)\s*/) {
    			print "MODIFIER($1)\n" if ($dbg_values > 1);
    			$type = 'T';
    
    
    		} elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
    
    			print "DEFINE($1,$2)\n" if ($dbg_values > 1);
    
    			$av_preprocessor = 1;
    
    			push(@av_paren_type, $type);
    			if ($2 ne '') {
    				$av_pending = 'N';
    			}
    			$type = 'E';
    
    
    		} elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
    
    			print "UNDEF($1)\n" if ($dbg_values > 1);
    			$av_preprocessor = 1;
    			push(@av_paren_type, $type);
    
    		} elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
    
    			print "PRE_START($1)\n" if ($dbg_values > 1);
    
    			$av_preprocessor = 1;
    
    
    			push(@av_paren_type, $type);
    			push(@av_paren_type, $type);
    
    			$type = 'E';
    
    		} elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
    
    			print "PRE_RESTART($1)\n" if ($dbg_values > 1);
    			$av_preprocessor = 1;
    
    			push(@av_paren_type, $av_paren_type[$#av_paren_type]);
    
    
    			$type = 'E';
    
    		} elsif ($cur =~ /^(\#\s*(?:endif))/o) {
    
    			print "PRE_END($1)\n" if ($dbg_values > 1);
    
    			$av_preprocessor = 1;
    
    			# Assume all arms of the conditional end as this
    			# one does, and continue as if the #endif was not here.
    			pop(@av_paren_type);
    			push(@av_paren_type, $type);
    
    			$type = 'E';
    
    
    		} elsif ($cur =~ /^(\\\n)/o) {
    
    			print "PRECONT($1)\n" if ($dbg_values > 1);
    
    		} elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
    			print "ATTR($1)\n" if ($dbg_values > 1);
    			$av_pending = $type;
    			$type = 'N';
    
    
    		} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
    
    			print "SIZEOF($1)\n" if ($dbg_values > 1);
    
    			if (defined $2) {
    
    				$av_pending = 'V';
    
    		} elsif ($cur =~ /^(if|while|for)\b/o) {
    
    			print "COND($1)\n" if ($dbg_values > 1);
    
    		} elsif ($cur =~/^(case)/o) {
    			print "CASE($1)\n" if ($dbg_values > 1);
    			$av_pend_colon = 'C';
    			$type = 'N';
    
    
    		} elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
    
    			print "KEYWORD($1)\n" if ($dbg_values > 1);
    
    			$type = 'N';
    
    		} elsif ($cur =~ /^(\()/o) {
    
    			print "PAREN('$1')\n" if ($dbg_values > 1);
    
    			push(@av_paren_type, $av_pending);
    			$av_pending = '_';
    
    			$type = 'N';
    
    		} elsif ($cur =~ /^(\))/o) {
    
    			my $new_type = pop(@av_paren_type);
    			if ($new_type ne '_') {
    				$type = $new_type;
    
    				print "PAREN('$1') -> $type\n"
    							if ($dbg_values > 1);
    
    				print "PAREN('$1')\n" if ($dbg_values > 1);
    
    		} elsif ($cur =~ /^($Ident)\s*\(/o) {
    
    			print "FUNC($1)\n" if ($dbg_values > 1);
    
    			$av_pending = 'V';
    
    		} elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
    			if (defined $2 && $type eq 'C' || $type eq 'T') {
    
    			} elsif ($type eq 'E') {
    				$av_pend_colon = 'L';
    
    			}
    			print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
    			$type = '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);
    
    		} elsif ($cur =~/^(;|{|})/) {
    
    			print "END($1)\n" if ($dbg_values > 1);
    
    			$type = 'E';
    
    		} elsif ($cur =~/^(,)/) {
    			print "COMMA($1)\n" if ($dbg_values > 1);
    			$type = 'C';
    
    
    		} elsif ($cur =~ /^(\?)/o) {
    			print "QUESTION($1)\n" if ($dbg_values > 1);
    			$type = 'N';
    
    		} elsif ($cur =~ /^(:)/o) {
    			print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
    
    			substr($var, length($res), 1, $av_pend_colon);
    			if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
    				$type = 'E';
    			} else {
    				$type = 'N';
    			}
    			$av_pend_colon = 'O';
    
    		} elsif ($cur =~ /^(\[)/o) {
    
    			print "CLOSE($1)\n" if ($dbg_values > 1);
    
    		} elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
    
    			my $variant;
    
    			print "OPV($1)\n" if ($dbg_values > 1);
    			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);
    		}
    
    sub possible {
    
    	my ($possible, $line) = @_;
    
    		^(?:
    			$Modifier|
    			$Storage|
    			$Type|
    
    			goto|
    			return|
    			case|
    			else|
    			asm|__asm__|
    
    		^(?:typedef|struct|enum)\b
    
    	    )}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);
    		}
    
    		build_types();
    
    	} else {
    		warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
    
    	return defined $use_type{$_[0]} if (scalar keys %use_type > 0);
    
    	return !defined $ignore_type{$_[0]};
    
    sub report {
    
    	if (!show_type($_[1]) ||
    	    (defined $tst_only && $_[2] !~ /\Q$tst_only\E/)) {
    
    	my $line;
    	if ($show_types) {
    		$line = "$prefix$_[0]:$_[1]: $_[2]\n";
    	} else {
    		$line = "$prefix$_[0]: $_[2]\n";
    	}
    
    	$line = (split('\n', $line))[0] . "\n" if ($terse);
    
    
    	push(our @report, $line);
    
    }
    sub report_dump {
    
    	our @report;
    
    	if (report("ERROR", $_[0], $_[1])) {
    
    		our $clean = 0;
    		our $cnt_error++;
    
    	if (report("WARNING", $_[0], $_[1])) {
    
    		our $clean = 0;
    		our $cnt_warn++;
    
    	if ($check && report("CHECK", $_[0], $_[1])) {
    
    		our $clean = 0;
    		our $cnt_chk++;
    
    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_PATH",
    		     "use relative pathname instead of absolute in changelog text\n" . $herecurr);
    
    	$string =~ s/^\s+|\s+$//g;
    
    	return $string;
    }
    
    sub ltrim {
    	my ($string) = @_;
    
    	$string =~ s/^\s+//;
    
    	return $string;
    }
    
    sub rtrim {
    	my ($string) = @_;
    
    	$string =~ s/\s+$//;
    
    sub string_find_replace {
    	my ($string, $find, $replace) = @_;
    
    	$string =~ s/$find/$replace/g;
    
    	return $string;
    }
    
    
    sub tabify {
    	my ($leading) = @_;
    
    	my $source_indent = 8;
    	my $max_spaces_before_tab = $source_indent - 1;
    	my $spaces_to_tab = " " x $source_indent;
    
    	#convert leading spaces to tabs
    	1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g;
    	#Remove spaces before a tab
    	1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g;
    
    	return "$leading";
    }
    
    
    sub pos_last_openparen {
    	my ($line) = @_;
    
    	my $pos = 0;
    
    	my $opens = $line =~ tr/\(/\(/;
    	my $closes = $line =~ tr/\)/\)/;
    
    	my $last_openparen = 0;
    
    	if (($opens == 0) || ($closes >= $opens)) {
    		return -1;
    	}
    
    	my $len = length($line);
    
    	for ($pos = 0; $pos < $len; $pos++) {
    		my $string = substr($line, $pos);
    		if ($string =~ /^($FuncArg|$balanced_parens)/) {
    			$pos += length($1) - 1;
    		} elsif (substr($line, $pos, 1) eq '(') {
    			$last_openparen = $pos;
    		} elsif (index($string, '(') == -1) {
    			last;
    		}
    	}
    
    	return $last_openparen + 1;
    }
    
    
    sub process {
    	my $filename = shift;
    
    	my $linenr=0;
    	my $prevline="";
    
    	my $prevrawline="";
    
    	my $stashline="";
    
    	my $stashrawline="";
    
    	my $indent;
    	my $previndent=0;
    	my $stashindent=0;
    
    
    	our $clean = 1;
    
    	my $signoff = 0;
    	my $is_patch = 0;
    
    
    	my $in_header_lines = 1;
    	my $in_commit_log = 0;		#Scanning lines before patch
    
    
    	our @report = ();
    
    	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 $comment_edge = 0;
    
    	my $first_line = 0;
    
    	my $p1_prefix = '';
    
    	my $prev_values = 'E';
    
    	# suppression flags
    
    	my %suppress_ifbraces;
    
    	my %suppress_export;
    
    	my $suppress_statement = 0;
    
    	my %signatures = ();
    
    	# Pre-scan the patch sanitizing the lines.
    
    	# Pre-scan the patch looking for any __setup documentation.
    
    	my @setup_docs = ();
    	my $setup_docs = 0;
    
    	sanitise_line_reset();
    
    	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;
    			}
    
    			$in_comment = 0;
    
    
    			# 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.
    
    			$line = sanitise_line($rawline);
    
    		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);
    		}
    	}
    
    
    	$realcnt = 0;
    	$linenr = 0;
    
    	foreach my $line (@lines) {
    		$linenr++;
    
    		my $sline = $line;	#copy of $line
    		$sline =~ s/$;/ /g;	#with comments as spaces
    
    		my $rawline = $rawlines[$linenr - 1];
    
    #extract the line range in the file after the patch is applied
    
    		if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
    
    			$is_patch = 1;
    
    			$first_line = $linenr + 1;
    
    			$realline=$1-1;
    			if (defined $2) {
    				$realcnt=$3+1;
    			} else {
    				$realcnt=1+1;
    			}
    
    			annotate_reset();
    
    			$prev_values = 'E';
    
    
    			%suppress_ifbraces = ();
    
    			%suppress_whiletrailers = ();
    
    			%suppress_export = ();
    
    # 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.
    
    		} elsif ($line =~ /^( |\+|$)/) {
    
    			$realline++;
    
    			$realcnt-- if ($realcnt != 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 "line<$line>\n";
    
    		} 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@^([^/]*)/@@ if (!$file);
    
    		} elsif ($line =~ /^\+\+\+\s+(\S+)/) {
    
    			$realfile = $1;
    
    			$realfile =~ s@^([^/]*)/@@ if (!$file);
    
    			if (!$file && $tree && $p1_prefix ne '' &&
    			    -e "$root/$p1_prefix") {
    
    				WARN("PATCH_PREFIX",
    				     "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
    
    			if ($realfile =~ m@^include/asm/@) {
    
    				ERROR("MODIFIED_INCLUDE_ASM",
    				      "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
    
    		$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 !~ m@scripts/@ &&
    			    $realfile !~ /\.(py|pl|awk|sh)$/) {
    
    				ERROR("EXECUTE_PERMISSIONS",
    				      "do not set execute permissions for source files\n" . $permhere);
    
    # Check the patch for a signoff:
    
    		if ($line =~ /^\s*signed-off-by:/i) {
    
    		if (!$in_header_lines &&
    
    		    $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) {
    
    			my $space_before = $1;
    			my $sign_off = $2;
    			my $space_after = $3;
    			my $email = $4;
    			my $ucfirst_sign_off = ucfirst(lc($sign_off));
    
    
    			if ($sign_off !~ /$signature_tags/) {
    				WARN("BAD_SIGN_OFF",
    				     "Non-standard signature: $sign_off\n" . $herecurr);
    			}
    
    			if (defined $space_before && $space_before ne "") {
    
    				if (WARN("BAD_SIGN_OFF",
    					 "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) &&
    				    $fix) {
    					$fixed[$linenr - 1] =
    					    "$ucfirst_sign_off $email";
    				}
    
    			}
    			if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) {
    
    				if (WARN("BAD_SIGN_OFF",
    					 "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) &&
    				    $fix) {
    					$fixed[$linenr - 1] =
    					    "$ucfirst_sign_off $email";
    				}
    
    
    			}
    			if (!defined $space_after || $space_after ne " ") {
    
    				if (WARN("BAD_SIGN_OFF",
    					 "Use a single space after $ucfirst_sign_off\n" . $herecurr) &&
    				    $fix) {
    					$fixed[$linenr - 1] =
    					    "$ucfirst_sign_off $email";
    				}
    
    
    			my ($email_name, $email_address, $comment) = parse_email($email);
    			my $suggested_email = format_email(($email_name, $email_address));
    			if ($suggested_email eq "") {
    
    				ERROR("BAD_SIGN_OFF",
    				      "Unrecognized email address: '$email'\n" . $herecurr);
    
    			} else {
    				my $dequoted = $suggested_email;
    				$dequoted =~ s/^"//;
    				$dequoted =~ s/" </ </;
    				# Don't force email to have quotes
    				# Allow just an angle bracketed address
    				if ("$dequoted$comment" ne $email &&
    				    "<$email_address>$comment" ne $email &&
    				    "$suggested_email$comment" ne $email) {
    
    					WARN("BAD_SIGN_OFF",
    					     "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
    
    
    # Check for duplicate signatures
    			my $sig_nospace = $line;
    			$sig_nospace =~ s/\s//g;
    			$sig_nospace = lc($sig_nospace);
    			if (defined $signatures{$sig_nospace}) {
    				WARN("BAD_SIGN_OFF",
    				     "Duplicate signature\n" . $herecurr);
    			} else {
    				$signatures{$sig_nospace} = 1;
    			}
    
    # Check for wrappage within a valid hunk of the file
    
    		if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
    
    			ERROR("CORRUPTED_PATCH",
    			      "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";
    
    
    			CHK("INVALID_UTF8",
    			    "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
    
    # Check if it's the start of a commit log
    # (not a header line and we haven't seen the patch filename)
    		if ($in_header_lines && $realfile =~ /^$/ &&
    
    		    $rawline !~ /^(commit\b|from\b|[\w-]+:).+$/i) {
    
    			$in_header_lines = 0;
    			$in_commit_log = 1;
    		}
    
    
    # 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/) {
    
    			    "8-bit UTF-8 used in possible commit log\n" . $herecurr);
    		}
    
    
    # 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 =~ /You should have received a copy/ ||
    		    $rawline =~ /write to the Free Software/ ||
    		    $rawline =~ /59 Temple Place/ ||
    		    $rawline =~ /51 Franklin Street/) {
    			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/ &&
    
    			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;
    				}