1#!/usr/bin/perl 2#*************************************************************************** 3# _ _ ____ _ 4# Project ___| | | | _ \| | 5# / __| | | | |_) | | 6# | (__| |_| | _ <| |___ 7# \___|\___/|_| \_\_____| 8# 9# Copyright (C) 2011, Daniel Stenberg, <daniel@haxx.se>, et al. 10# 11# This software is licensed as described in the file COPYING, which 12# you should have received as part of this distribution. The terms 13# are also available at http://curl.haxx.se/docs/copyright.html. 14# 15# You may opt to use, copy, modify, merge, publish, distribute and/or sell 16# copies of the Software, and permit persons to whom the Software is 17# furnished to do so, under the terms of the COPYING file. 18# 19# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20# KIND, either express or implied. 21# 22########################################################################### 23 24my $max_column = 79; 25my $indent = 2; 26 27my $warnings; 28my $errors; 29my $file; 30my $dir="."; 31my $wlist; 32 33sub checkwarn { 34 my ($num, $col, $file, $line, $msg, $error) = @_; 35 36 my $w=$error?"error":"warning"; 37 38 if($w) { 39 $warnings++; 40 } 41 else { 42 $errors++; 43 } 44 45 $col++; 46 print "$file:$num:$col: $w: $msg\n"; 47 print " $line\n"; 48 49 if($col < 80) { 50 my $pref = (' ' x $col); 51 print "${pref}^\n"; 52 } 53} 54 55$file = shift @ARGV; 56 57while(1) { 58 59 if($file =~ /-D(.*)/) { 60 $dir = $1; 61 $file = shift @ARGV; 62 next; 63 } 64 elsif($file =~ /-W(.*)/) { 65 $wlist .= " $1 "; 66 $file = shift @ARGV; 67 next; 68 } 69 70 last; 71} 72 73if(!$file) { 74 print "checksrc.pl [option] <file1> [file2] ...\n"; 75 print " Options:\n"; 76 print " -D[DIR] Directory to prepend file names\n"; 77 print " -W[file] Whitelist the given file - ignore all its flaws\n"; 78 exit; 79} 80 81do { 82 if("$wlist" !~ / $file /) { 83 my $fullname = $file; 84 $fullname = "$dir/$file" if ($fullname !~ '^\.?\.?/'); 85 scanfile($fullname); 86 } 87 $file = shift @ARGV; 88 89} while($file); 90 91 92sub scanfile { 93 my ($file) = @_; 94 95 my $line = 1; 96 my $prevl; 97 my $l; 98 open(R, "<$file") || die "failed to open $file"; 99 100 my $copyright=0; 101 102 while(<R>) { 103 chomp; 104 my $l = $_; 105 my $column = 0; 106 107 # check for a copyright statement 108 if(!$copyright && ($l =~ /copyright .* \d\d\d\d/i)) { 109 $copyright=1; 110 } 111 112 # detect long lines 113 if(length($l) > $max_column) { 114 checkwarn($line, length($l), $file, $l, "Longer than $max_column columns"); 115 } 116 # detect TAB characters 117 if($l =~ /^(.*)\t/) { 118 checkwarn($line, length($1), $file, $l, "Contains TAB character", 1); 119 } 120 # detect trailing white space 121 if($l =~ /^(.*)[ \t]+\z/) { 122 checkwarn($line, length($1), $file, $l, "Trailing whitespace"); 123 } 124 125 # check spaces after for/if/while 126 if($l =~ /^(.*)(for|if|while) \(/) { 127 if($1 =~ / *\#/) { 128 # this is a #if, treat it differently 129 } 130 else { 131 checkwarn($line, length($1)+length($2), $file, $l, 132 "$2 with space"); 133 } 134 } 135 136 # check spaces after open paren after for/if/while 137 if($l =~ /^(.*)(for|if|while)\( /) { 138 if($1 =~ / *\#/) { 139 # this is a #if, treat it differently 140 } 141 else { 142 checkwarn($line, length($1)+length($2)+1, $file, $l, 143 "$2 with space first in condition"); 144 } 145 } 146 147 # check for "} else" 148 if($l =~ /^(.*)\} *else/) { 149 checkwarn($line, length($1), $file, $l, "else after closing brace on same line"); 150 } 151 # check for "){" 152 if($l =~ /^(.*)\)\{/) { 153 checkwarn($line, length($1)+1, $file, $l, "missing space after close paren"); 154 } 155 156 # check for open brace first on line but not first column 157 # only alert if previous line ended with a close paren and wasn't a cpp 158 # line 159 if((($prevl =~ /\)\z/) && ($prevl !~ /^ *#/)) && ($l =~ /^( +)\{/)) { 160 checkwarn($line, length($1), $file, $l, "badly placed open brace"); 161 } 162 163 # if the previous line starts with if/while/for AND ends with an open 164 # brace, check that this line is indented $indent more steps, if not 165 # a cpp line 166 if($prevl =~ /^( *)(if|while|for)\(.*\{\z/) { 167 my $first = length($1); 168 169 # this line has some character besides spaces 170 if(($l !~ /^ *#/) && ($l =~ /^( *)[^ ]/)) { 171 my $second = length($1); 172 my $expect = $first+$indent; 173 if($expect != $second) { 174 my $diff = $second - $first; 175 checkwarn($line, length($1), $file, $l, 176 "not indented $indent steps, uses $diff)"); 177 178 } 179 } 180 } 181 182 $line++; 183 $prevl = $l; 184 } 185 186 if(!$copyright) { 187 checkwarn(1, 0, $file, "", "Missing copyright statement", 1); 188 } 189 190 close(R); 191 192} 193 194 195if($errors || $warnings) { 196 printf "checksrc: %d errors and %d warnings\n", $errors, $warnings; 197 exit 5; # return failure 198} 199