1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env perl 2*6236dae4SAndroid Build Coastguard Worker#*************************************************************************** 3*6236dae4SAndroid Build Coastguard Worker# _ _ ____ _ 4*6236dae4SAndroid Build Coastguard Worker# Project ___| | | | _ \| | 5*6236dae4SAndroid Build Coastguard Worker# / __| | | | |_) | | 6*6236dae4SAndroid Build Coastguard Worker# | (__| |_| | _ <| |___ 7*6236dae4SAndroid Build Coastguard Worker# \___|\___/|_| \_\_____| 8*6236dae4SAndroid Build Coastguard Worker# 9*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al. 10*6236dae4SAndroid Build Coastguard Worker# 11*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which 12*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms 13*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html. 14*6236dae4SAndroid Build Coastguard Worker# 15*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell 16*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is 17*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file. 18*6236dae4SAndroid Build Coastguard Worker# 19*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied. 21*6236dae4SAndroid Build Coastguard Worker# 22*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl 23*6236dae4SAndroid Build Coastguard Worker# 24*6236dae4SAndroid Build Coastguard Worker########################################################################### 25*6236dae4SAndroid Build Coastguard Worker 26*6236dae4SAndroid Build Coastguard Workeruse strict; 27*6236dae4SAndroid Build Coastguard Workeruse warnings; 28*6236dae4SAndroid Build Coastguard Worker 29*6236dae4SAndroid Build Coastguard Workermy $max_column = 79; 30*6236dae4SAndroid Build Coastguard Workermy $indent = 2; 31*6236dae4SAndroid Build Coastguard Worker 32*6236dae4SAndroid Build Coastguard Workermy $warnings = 0; 33*6236dae4SAndroid Build Coastguard Workermy $swarnings = 0; 34*6236dae4SAndroid Build Coastguard Workermy $errors = 0; 35*6236dae4SAndroid Build Coastguard Workermy $serrors = 0; 36*6236dae4SAndroid Build Coastguard Workermy $suppressed; # skipped problems 37*6236dae4SAndroid Build Coastguard Workermy $file; 38*6236dae4SAndroid Build Coastguard Workermy $dir="."; 39*6236dae4SAndroid Build Coastguard Workermy $wlist=""; 40*6236dae4SAndroid Build Coastguard Workermy @alist; 41*6236dae4SAndroid Build Coastguard Workermy $windows_os = $^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys'; 42*6236dae4SAndroid Build Coastguard Workermy $verbose; 43*6236dae4SAndroid Build Coastguard Workermy %skiplist; 44*6236dae4SAndroid Build Coastguard Worker 45*6236dae4SAndroid Build Coastguard Workermy %ignore; 46*6236dae4SAndroid Build Coastguard Workermy %ignore_set; 47*6236dae4SAndroid Build Coastguard Workermy %ignore_used; 48*6236dae4SAndroid Build Coastguard Workermy @ignore_line; 49*6236dae4SAndroid Build Coastguard Worker 50*6236dae4SAndroid Build Coastguard Workermy %warnings_extended = ( 51*6236dae4SAndroid Build Coastguard Worker 'COPYRIGHTYEAR' => 'copyright year incorrect', 52*6236dae4SAndroid Build Coastguard Worker 'STRERROR', => 'strerror() detected', 53*6236dae4SAndroid Build Coastguard Worker 'STRNCPY', => 'strncpy() detected', 54*6236dae4SAndroid Build Coastguard Worker 'STDERR', => 'stderr detected', 55*6236dae4SAndroid Build Coastguard Worker ); 56*6236dae4SAndroid Build Coastguard Worker 57*6236dae4SAndroid Build Coastguard Workermy %warnings = ( 58*6236dae4SAndroid Build Coastguard Worker 'ASSIGNWITHINCONDITION' => 'assignment within conditional expression', 59*6236dae4SAndroid Build Coastguard Worker 'ASTERISKNOSPACE' => 'pointer declared without space before asterisk', 60*6236dae4SAndroid Build Coastguard Worker 'ASTERISKSPACE' => 'pointer declared with space after asterisk', 61*6236dae4SAndroid Build Coastguard Worker 'BADCOMMAND' => 'bad !checksrc! instruction', 62*6236dae4SAndroid Build Coastguard Worker 'BANNEDFUNC' => 'a banned function was used', 63*6236dae4SAndroid Build Coastguard Worker 'BANNEDPREPROC' => 'a banned symbol was used on a preprocessor line', 64*6236dae4SAndroid Build Coastguard Worker 'BRACEELSE' => '} else on the same line', 65*6236dae4SAndroid Build Coastguard Worker 'BRACEPOS' => 'wrong position for an open brace', 66*6236dae4SAndroid Build Coastguard Worker 'BRACEWHILE' => 'A single space between open brace and while', 67*6236dae4SAndroid Build Coastguard Worker 'COMMANOSPACE' => 'comma without following space', 68*6236dae4SAndroid Build Coastguard Worker 'COMMENTNOSPACEEND' => 'no space before */', 69*6236dae4SAndroid Build Coastguard Worker 'COMMENTNOSPACESTART' => 'no space following /*', 70*6236dae4SAndroid Build Coastguard Worker 'COPYRIGHT' => 'file missing a copyright statement', 71*6236dae4SAndroid Build Coastguard Worker 'CPPCOMMENTS' => '// comment detected', 72*6236dae4SAndroid Build Coastguard Worker 'DOBRACE' => 'A single space between do and open brace', 73*6236dae4SAndroid Build Coastguard Worker 'EMPTYLINEBRACE' => 'Empty line before the open brace', 74*6236dae4SAndroid Build Coastguard Worker 'EQUALSNOSPACE' => 'equals sign without following space', 75*6236dae4SAndroid Build Coastguard Worker 'EQUALSNULL' => 'if/while comparison with == NULL', 76*6236dae4SAndroid Build Coastguard Worker 'EXCLAMATIONSPACE' => 'Whitespace after exclamation mark in expression', 77*6236dae4SAndroid Build Coastguard Worker 'FOPENMODE' => 'fopen needs a macro for the mode string', 78*6236dae4SAndroid Build Coastguard Worker 'INCLUDEDUP', => 'same file is included again', 79*6236dae4SAndroid Build Coastguard Worker 'INDENTATION' => 'wrong start column for code', 80*6236dae4SAndroid Build Coastguard Worker 'LONGLINE' => "Line longer than $max_column", 81*6236dae4SAndroid Build Coastguard Worker 'SPACEBEFORELABEL' => 'labels not at the start of the line', 82*6236dae4SAndroid Build Coastguard Worker 'MULTISPACE' => 'multiple spaces used when not suitable', 83*6236dae4SAndroid Build Coastguard Worker 'NOSPACEAND' => 'missing space around Logical AND operator', 84*6236dae4SAndroid Build Coastguard Worker 'NOSPACEC' => 'missing space around ternary colon operator', 85*6236dae4SAndroid Build Coastguard Worker 'NOSPACEEQUALS' => 'equals sign without preceding space', 86*6236dae4SAndroid Build Coastguard Worker 'NOSPACEQ' => 'missing space around ternary question mark operator', 87*6236dae4SAndroid Build Coastguard Worker 'NOSPACETHAN' => 'missing space around less or greater than', 88*6236dae4SAndroid Build Coastguard Worker 'NOTEQUALSZERO', => 'if/while comparison with != 0', 89*6236dae4SAndroid Build Coastguard Worker 'ONELINECONDITION' => 'conditional block on the same line as the if()', 90*6236dae4SAndroid Build Coastguard Worker 'OPENCOMMENT' => 'file ended with a /* comment still "open"', 91*6236dae4SAndroid Build Coastguard Worker 'PARENBRACE' => '){ without sufficient space', 92*6236dae4SAndroid Build Coastguard Worker 'RETURNNOSPACE' => 'return without space', 93*6236dae4SAndroid Build Coastguard Worker 'SEMINOSPACE' => 'semicolon without following space', 94*6236dae4SAndroid Build Coastguard Worker 'SIZEOFNOPAREN' => 'use of sizeof without parentheses', 95*6236dae4SAndroid Build Coastguard Worker 'SNPRINTF' => 'use of snprintf', 96*6236dae4SAndroid Build Coastguard Worker 'SPACEAFTERPAREN' => 'space after open parenthesis', 97*6236dae4SAndroid Build Coastguard Worker 'SPACEBEFORECLOSE' => 'space before a close parenthesis', 98*6236dae4SAndroid Build Coastguard Worker 'SPACEBEFORECOMMA' => 'space before a comma', 99*6236dae4SAndroid Build Coastguard Worker 'SPACEBEFOREPAREN' => 'space before an open parenthesis', 100*6236dae4SAndroid Build Coastguard Worker 'SPACESEMICOLON' => 'space before semicolon', 101*6236dae4SAndroid Build Coastguard Worker 'SPACESWITCHCOLON' => 'space before colon of switch label', 102*6236dae4SAndroid Build Coastguard Worker 'TABS' => 'TAB characters not allowed', 103*6236dae4SAndroid Build Coastguard Worker 'TRAILINGSPACE' => 'Trailing whitespace on the line', 104*6236dae4SAndroid Build Coastguard Worker 'TYPEDEFSTRUCT' => 'typedefed struct', 105*6236dae4SAndroid Build Coastguard Worker 'UNUSEDIGNORE' => 'a warning ignore was not used', 106*6236dae4SAndroid Build Coastguard Worker ); 107*6236dae4SAndroid Build Coastguard Worker 108*6236dae4SAndroid Build Coastguard Workersub readskiplist { 109*6236dae4SAndroid Build Coastguard Worker open(my $W, '<', "$dir/checksrc.skip") or return; 110*6236dae4SAndroid Build Coastguard Worker my @all=<$W>; 111*6236dae4SAndroid Build Coastguard Worker for(@all) { 112*6236dae4SAndroid Build Coastguard Worker $windows_os ? $_ =~ s/\r?\n$// : chomp; 113*6236dae4SAndroid Build Coastguard Worker $skiplist{$_}=1; 114*6236dae4SAndroid Build Coastguard Worker } 115*6236dae4SAndroid Build Coastguard Worker close($W); 116*6236dae4SAndroid Build Coastguard Worker} 117*6236dae4SAndroid Build Coastguard Worker 118*6236dae4SAndroid Build Coastguard Worker# Reads the .checksrc in $dir for any extended warnings to enable locally. 119*6236dae4SAndroid Build Coastguard Worker# Currently there is no support for disabling warnings from the standard set, 120*6236dae4SAndroid Build Coastguard Worker# and since that's already handled via !checksrc! commands there is probably 121*6236dae4SAndroid Build Coastguard Worker# little use to add it. 122*6236dae4SAndroid Build Coastguard Workersub readlocalfile { 123*6236dae4SAndroid Build Coastguard Worker my ($file) = @_; 124*6236dae4SAndroid Build Coastguard Worker my $i = 0; 125*6236dae4SAndroid Build Coastguard Worker my $rcfile; 126*6236dae4SAndroid Build Coastguard Worker 127*6236dae4SAndroid Build Coastguard Worker if(($dir eq ".") && $file =~ /\//) { 128*6236dae4SAndroid Build Coastguard Worker my $ldir; 129*6236dae4SAndroid Build Coastguard Worker if($file =~ /(.*)\//) { 130*6236dae4SAndroid Build Coastguard Worker $ldir = $1; 131*6236dae4SAndroid Build Coastguard Worker open($rcfile, "<", "$dir/$ldir/.checksrc") or return; 132*6236dae4SAndroid Build Coastguard Worker } 133*6236dae4SAndroid Build Coastguard Worker } 134*6236dae4SAndroid Build Coastguard Worker else { 135*6236dae4SAndroid Build Coastguard Worker open($rcfile, "<", "$dir/.checksrc") or return; 136*6236dae4SAndroid Build Coastguard Worker } 137*6236dae4SAndroid Build Coastguard Worker 138*6236dae4SAndroid Build Coastguard Worker while(<$rcfile>) { 139*6236dae4SAndroid Build Coastguard Worker $windows_os ? $_ =~ s/\r?\n$// : chomp; 140*6236dae4SAndroid Build Coastguard Worker $i++; 141*6236dae4SAndroid Build Coastguard Worker 142*6236dae4SAndroid Build Coastguard Worker # Lines starting with '#' are considered comments 143*6236dae4SAndroid Build Coastguard Worker if (/^\s*(#.*)/) { 144*6236dae4SAndroid Build Coastguard Worker next; 145*6236dae4SAndroid Build Coastguard Worker } 146*6236dae4SAndroid Build Coastguard Worker elsif (/^\s*enable ([A-Z]+)$/) { 147*6236dae4SAndroid Build Coastguard Worker if(!defined($warnings_extended{$1})) { 148*6236dae4SAndroid Build Coastguard Worker print STDERR "invalid warning specified in .checksrc: \"$1\"\n"; 149*6236dae4SAndroid Build Coastguard Worker next; 150*6236dae4SAndroid Build Coastguard Worker } 151*6236dae4SAndroid Build Coastguard Worker $warnings{$1} = $warnings_extended{$1}; 152*6236dae4SAndroid Build Coastguard Worker } 153*6236dae4SAndroid Build Coastguard Worker elsif (/^\s*disable ([A-Z]+)$/) { 154*6236dae4SAndroid Build Coastguard Worker if(!defined($warnings{$1})) { 155*6236dae4SAndroid Build Coastguard Worker print STDERR "invalid warning specified in .checksrc: \"$1\"\n"; 156*6236dae4SAndroid Build Coastguard Worker next; 157*6236dae4SAndroid Build Coastguard Worker } 158*6236dae4SAndroid Build Coastguard Worker # Accept-list 159*6236dae4SAndroid Build Coastguard Worker push @alist, $1; 160*6236dae4SAndroid Build Coastguard Worker } 161*6236dae4SAndroid Build Coastguard Worker else { 162*6236dae4SAndroid Build Coastguard Worker die "Invalid format in $dir/.checksrc on line $i\n"; 163*6236dae4SAndroid Build Coastguard Worker } 164*6236dae4SAndroid Build Coastguard Worker } 165*6236dae4SAndroid Build Coastguard Worker close($rcfile); 166*6236dae4SAndroid Build Coastguard Worker} 167*6236dae4SAndroid Build Coastguard Worker 168*6236dae4SAndroid Build Coastguard Workersub checkwarn { 169*6236dae4SAndroid Build Coastguard Worker my ($name, $num, $col, $file, $line, $msg, $error) = @_; 170*6236dae4SAndroid Build Coastguard Worker 171*6236dae4SAndroid Build Coastguard Worker my $w=$error?"error":"warning"; 172*6236dae4SAndroid Build Coastguard Worker my $nowarn=0; 173*6236dae4SAndroid Build Coastguard Worker 174*6236dae4SAndroid Build Coastguard Worker #if(!$warnings{$name}) { 175*6236dae4SAndroid Build Coastguard Worker # print STDERR "Dev! there's no description for $name!\n"; 176*6236dae4SAndroid Build Coastguard Worker #} 177*6236dae4SAndroid Build Coastguard Worker 178*6236dae4SAndroid Build Coastguard Worker # checksrc.skip 179*6236dae4SAndroid Build Coastguard Worker if($skiplist{$line}) { 180*6236dae4SAndroid Build Coastguard Worker $nowarn = 1; 181*6236dae4SAndroid Build Coastguard Worker } 182*6236dae4SAndroid Build Coastguard Worker # !checksrc! controlled 183*6236dae4SAndroid Build Coastguard Worker elsif($ignore{$name}) { 184*6236dae4SAndroid Build Coastguard Worker $ignore{$name}--; 185*6236dae4SAndroid Build Coastguard Worker $ignore_used{$name}++; 186*6236dae4SAndroid Build Coastguard Worker $nowarn = 1; 187*6236dae4SAndroid Build Coastguard Worker if(!$ignore{$name}) { 188*6236dae4SAndroid Build Coastguard Worker # reached zero, enable again 189*6236dae4SAndroid Build Coastguard Worker enable_warn($name, $num, $file, $line); 190*6236dae4SAndroid Build Coastguard Worker } 191*6236dae4SAndroid Build Coastguard Worker } 192*6236dae4SAndroid Build Coastguard Worker 193*6236dae4SAndroid Build Coastguard Worker if($nowarn) { 194*6236dae4SAndroid Build Coastguard Worker $suppressed++; 195*6236dae4SAndroid Build Coastguard Worker if($w) { 196*6236dae4SAndroid Build Coastguard Worker $swarnings++; 197*6236dae4SAndroid Build Coastguard Worker } 198*6236dae4SAndroid Build Coastguard Worker else { 199*6236dae4SAndroid Build Coastguard Worker $serrors++; 200*6236dae4SAndroid Build Coastguard Worker } 201*6236dae4SAndroid Build Coastguard Worker return; 202*6236dae4SAndroid Build Coastguard Worker } 203*6236dae4SAndroid Build Coastguard Worker 204*6236dae4SAndroid Build Coastguard Worker if($w) { 205*6236dae4SAndroid Build Coastguard Worker $warnings++; 206*6236dae4SAndroid Build Coastguard Worker } 207*6236dae4SAndroid Build Coastguard Worker else { 208*6236dae4SAndroid Build Coastguard Worker $errors++; 209*6236dae4SAndroid Build Coastguard Worker } 210*6236dae4SAndroid Build Coastguard Worker 211*6236dae4SAndroid Build Coastguard Worker $col++; 212*6236dae4SAndroid Build Coastguard Worker print "$file:$num:$col: $w: $msg ($name)\n"; 213*6236dae4SAndroid Build Coastguard Worker print " $line\n"; 214*6236dae4SAndroid Build Coastguard Worker 215*6236dae4SAndroid Build Coastguard Worker if($col < 80) { 216*6236dae4SAndroid Build Coastguard Worker my $pref = (' ' x $col); 217*6236dae4SAndroid Build Coastguard Worker print "${pref}^\n"; 218*6236dae4SAndroid Build Coastguard Worker } 219*6236dae4SAndroid Build Coastguard Worker} 220*6236dae4SAndroid Build Coastguard Worker 221*6236dae4SAndroid Build Coastguard Worker$file = shift @ARGV; 222*6236dae4SAndroid Build Coastguard Worker 223*6236dae4SAndroid Build Coastguard Workerwhile(defined $file) { 224*6236dae4SAndroid Build Coastguard Worker 225*6236dae4SAndroid Build Coastguard Worker if($file =~ /-D(.*)/) { 226*6236dae4SAndroid Build Coastguard Worker $dir = $1; 227*6236dae4SAndroid Build Coastguard Worker $file = shift @ARGV; 228*6236dae4SAndroid Build Coastguard Worker next; 229*6236dae4SAndroid Build Coastguard Worker } 230*6236dae4SAndroid Build Coastguard Worker elsif($file =~ /-W(.*)/) { 231*6236dae4SAndroid Build Coastguard Worker $wlist .= " $1 "; 232*6236dae4SAndroid Build Coastguard Worker $file = shift @ARGV; 233*6236dae4SAndroid Build Coastguard Worker next; 234*6236dae4SAndroid Build Coastguard Worker } 235*6236dae4SAndroid Build Coastguard Worker elsif($file =~ /-A(.+)/) { 236*6236dae4SAndroid Build Coastguard Worker push @alist, $1; 237*6236dae4SAndroid Build Coastguard Worker $file = shift @ARGV; 238*6236dae4SAndroid Build Coastguard Worker next; 239*6236dae4SAndroid Build Coastguard Worker } 240*6236dae4SAndroid Build Coastguard Worker elsif($file =~ /-i([1-9])/) { 241*6236dae4SAndroid Build Coastguard Worker $indent = $1 + 0; 242*6236dae4SAndroid Build Coastguard Worker $file = shift @ARGV; 243*6236dae4SAndroid Build Coastguard Worker next; 244*6236dae4SAndroid Build Coastguard Worker } 245*6236dae4SAndroid Build Coastguard Worker elsif($file =~ /-m([0-9]+)/) { 246*6236dae4SAndroid Build Coastguard Worker $max_column = $1 + 0; 247*6236dae4SAndroid Build Coastguard Worker $file = shift @ARGV; 248*6236dae4SAndroid Build Coastguard Worker next; 249*6236dae4SAndroid Build Coastguard Worker } 250*6236dae4SAndroid Build Coastguard Worker elsif($file =~ /^(-h|--help)/) { 251*6236dae4SAndroid Build Coastguard Worker undef $file; 252*6236dae4SAndroid Build Coastguard Worker last; 253*6236dae4SAndroid Build Coastguard Worker } 254*6236dae4SAndroid Build Coastguard Worker 255*6236dae4SAndroid Build Coastguard Worker last; 256*6236dae4SAndroid Build Coastguard Worker} 257*6236dae4SAndroid Build Coastguard Worker 258*6236dae4SAndroid Build Coastguard Workerif(!$file) { 259*6236dae4SAndroid Build Coastguard Worker print "checksrc.pl [option] <file1> [file2] ...\n"; 260*6236dae4SAndroid Build Coastguard Worker print " Options:\n"; 261*6236dae4SAndroid Build Coastguard Worker print " -A[rule] Accept this violation, can be used multiple times\n"; 262*6236dae4SAndroid Build Coastguard Worker print " -D[DIR] Directory to prepend file names\n"; 263*6236dae4SAndroid Build Coastguard Worker print " -h Show help output\n"; 264*6236dae4SAndroid Build Coastguard Worker print " -W[file] Skip the given file - ignore all its flaws\n"; 265*6236dae4SAndroid Build Coastguard Worker print " -i<n> Indent spaces. Default: 2\n"; 266*6236dae4SAndroid Build Coastguard Worker print " -m<n> Maximum line length. Default: 79\n"; 267*6236dae4SAndroid Build Coastguard Worker print "\nDetects and warns for these problems:\n"; 268*6236dae4SAndroid Build Coastguard Worker my @allw = keys %warnings; 269*6236dae4SAndroid Build Coastguard Worker push @allw, keys %warnings_extended; 270*6236dae4SAndroid Build Coastguard Worker for my $w (sort @allw) { 271*6236dae4SAndroid Build Coastguard Worker if($warnings{$w}) { 272*6236dae4SAndroid Build Coastguard Worker printf (" %-18s: %s\n", $w, $warnings{$w}); 273*6236dae4SAndroid Build Coastguard Worker } 274*6236dae4SAndroid Build Coastguard Worker else { 275*6236dae4SAndroid Build Coastguard Worker printf (" %-18s: %s[*]\n", $w, $warnings_extended{$w}); 276*6236dae4SAndroid Build Coastguard Worker } 277*6236dae4SAndroid Build Coastguard Worker } 278*6236dae4SAndroid Build Coastguard Worker print " [*] = disabled by default\n"; 279*6236dae4SAndroid Build Coastguard Worker exit; 280*6236dae4SAndroid Build Coastguard Worker} 281*6236dae4SAndroid Build Coastguard Worker 282*6236dae4SAndroid Build Coastguard Workerreadskiplist(); 283*6236dae4SAndroid Build Coastguard Workerreadlocalfile($file); 284*6236dae4SAndroid Build Coastguard Worker 285*6236dae4SAndroid Build Coastguard Workerdo { 286*6236dae4SAndroid Build Coastguard Worker if("$wlist" !~ / $file /) { 287*6236dae4SAndroid Build Coastguard Worker my $fullname = $file; 288*6236dae4SAndroid Build Coastguard Worker $fullname = "$dir/$file" if ($fullname !~ '^\.?\.?/'); 289*6236dae4SAndroid Build Coastguard Worker scanfile($fullname); 290*6236dae4SAndroid Build Coastguard Worker } 291*6236dae4SAndroid Build Coastguard Worker $file = shift @ARGV; 292*6236dae4SAndroid Build Coastguard Worker 293*6236dae4SAndroid Build Coastguard Worker} while($file); 294*6236dae4SAndroid Build Coastguard Worker 295*6236dae4SAndroid Build Coastguard Workersub accept_violations { 296*6236dae4SAndroid Build Coastguard Worker for my $r (@alist) { 297*6236dae4SAndroid Build Coastguard Worker if(!$warnings{$r}) { 298*6236dae4SAndroid Build Coastguard Worker print "'$r' is not a warning to accept!\n"; 299*6236dae4SAndroid Build Coastguard Worker exit; 300*6236dae4SAndroid Build Coastguard Worker } 301*6236dae4SAndroid Build Coastguard Worker $ignore{$r}=999999; 302*6236dae4SAndroid Build Coastguard Worker $ignore_used{$r}=0; 303*6236dae4SAndroid Build Coastguard Worker } 304*6236dae4SAndroid Build Coastguard Worker} 305*6236dae4SAndroid Build Coastguard Worker 306*6236dae4SAndroid Build Coastguard Workersub checksrc_clear { 307*6236dae4SAndroid Build Coastguard Worker undef %ignore; 308*6236dae4SAndroid Build Coastguard Worker undef %ignore_set; 309*6236dae4SAndroid Build Coastguard Worker undef @ignore_line; 310*6236dae4SAndroid Build Coastguard Worker} 311*6236dae4SAndroid Build Coastguard Worker 312*6236dae4SAndroid Build Coastguard Workersub checksrc_endoffile { 313*6236dae4SAndroid Build Coastguard Worker my ($file) = @_; 314*6236dae4SAndroid Build Coastguard Worker for(keys %ignore_set) { 315*6236dae4SAndroid Build Coastguard Worker if($ignore_set{$_} && !$ignore_used{$_}) { 316*6236dae4SAndroid Build Coastguard Worker checkwarn("UNUSEDIGNORE", $ignore_set{$_}, 317*6236dae4SAndroid Build Coastguard Worker length($_)+11, $file, 318*6236dae4SAndroid Build Coastguard Worker $ignore_line[$ignore_set{$_}], 319*6236dae4SAndroid Build Coastguard Worker "Unused ignore: $_"); 320*6236dae4SAndroid Build Coastguard Worker } 321*6236dae4SAndroid Build Coastguard Worker } 322*6236dae4SAndroid Build Coastguard Worker} 323*6236dae4SAndroid Build Coastguard Worker 324*6236dae4SAndroid Build Coastguard Workersub enable_warn { 325*6236dae4SAndroid Build Coastguard Worker my ($what, $line, $file, $l) = @_; 326*6236dae4SAndroid Build Coastguard Worker 327*6236dae4SAndroid Build Coastguard Worker # switch it back on, but warn if not triggered! 328*6236dae4SAndroid Build Coastguard Worker if(!$ignore_used{$what}) { 329*6236dae4SAndroid Build Coastguard Worker checkwarn("UNUSEDIGNORE", 330*6236dae4SAndroid Build Coastguard Worker $line, length($what) + 11, $file, $l, 331*6236dae4SAndroid Build Coastguard Worker "No warning was inhibited!"); 332*6236dae4SAndroid Build Coastguard Worker } 333*6236dae4SAndroid Build Coastguard Worker $ignore_set{$what}=0; 334*6236dae4SAndroid Build Coastguard Worker $ignore_used{$what}=0; 335*6236dae4SAndroid Build Coastguard Worker $ignore{$what}=0; 336*6236dae4SAndroid Build Coastguard Worker} 337*6236dae4SAndroid Build Coastguard Workersub checksrc { 338*6236dae4SAndroid Build Coastguard Worker my ($cmd, $line, $file, $l) = @_; 339*6236dae4SAndroid Build Coastguard Worker if($cmd =~ / *([^ ]*) *(.*)/) { 340*6236dae4SAndroid Build Coastguard Worker my ($enable, $what) = ($1, $2); 341*6236dae4SAndroid Build Coastguard Worker $what =~ s: *\*/$::; # cut off end of C comment 342*6236dae4SAndroid Build Coastguard Worker # print "ENABLE $enable WHAT $what\n"; 343*6236dae4SAndroid Build Coastguard Worker if($enable eq "disable") { 344*6236dae4SAndroid Build Coastguard Worker my ($warn, $scope)=($1, $2); 345*6236dae4SAndroid Build Coastguard Worker if($what =~ /([^ ]*) +(.*)/) { 346*6236dae4SAndroid Build Coastguard Worker ($warn, $scope)=($1, $2); 347*6236dae4SAndroid Build Coastguard Worker } 348*6236dae4SAndroid Build Coastguard Worker else { 349*6236dae4SAndroid Build Coastguard Worker $warn = $what; 350*6236dae4SAndroid Build Coastguard Worker $scope = 1; 351*6236dae4SAndroid Build Coastguard Worker } 352*6236dae4SAndroid Build Coastguard Worker # print "IGNORE $warn for SCOPE $scope\n"; 353*6236dae4SAndroid Build Coastguard Worker if($scope eq "all") { 354*6236dae4SAndroid Build Coastguard Worker $scope=999999; 355*6236dae4SAndroid Build Coastguard Worker } 356*6236dae4SAndroid Build Coastguard Worker 357*6236dae4SAndroid Build Coastguard Worker # Comparing for a literal zero rather than the scalar value zero 358*6236dae4SAndroid Build Coastguard Worker # covers the case where $scope contains the ending '*' from the 359*6236dae4SAndroid Build Coastguard Worker # comment. If we use a scalar comparison (==) we induce warnings 360*6236dae4SAndroid Build Coastguard Worker # on non-scalar contents. 361*6236dae4SAndroid Build Coastguard Worker if($scope eq "0") { 362*6236dae4SAndroid Build Coastguard Worker checkwarn("BADCOMMAND", 363*6236dae4SAndroid Build Coastguard Worker $line, 0, $file, $l, 364*6236dae4SAndroid Build Coastguard Worker "Disable zero not supported, did you mean to enable?"); 365*6236dae4SAndroid Build Coastguard Worker } 366*6236dae4SAndroid Build Coastguard Worker elsif($ignore_set{$warn}) { 367*6236dae4SAndroid Build Coastguard Worker checkwarn("BADCOMMAND", 368*6236dae4SAndroid Build Coastguard Worker $line, 0, $file, $l, 369*6236dae4SAndroid Build Coastguard Worker "$warn already disabled from line $ignore_set{$warn}"); 370*6236dae4SAndroid Build Coastguard Worker } 371*6236dae4SAndroid Build Coastguard Worker else { 372*6236dae4SAndroid Build Coastguard Worker $ignore{$warn}=$scope; 373*6236dae4SAndroid Build Coastguard Worker $ignore_set{$warn}=$line; 374*6236dae4SAndroid Build Coastguard Worker $ignore_line[$line]=$l; 375*6236dae4SAndroid Build Coastguard Worker } 376*6236dae4SAndroid Build Coastguard Worker } 377*6236dae4SAndroid Build Coastguard Worker elsif($enable eq "enable") { 378*6236dae4SAndroid Build Coastguard Worker enable_warn($what, $line, $file, $l); 379*6236dae4SAndroid Build Coastguard Worker } 380*6236dae4SAndroid Build Coastguard Worker else { 381*6236dae4SAndroid Build Coastguard Worker checkwarn("BADCOMMAND", 382*6236dae4SAndroid Build Coastguard Worker $line, 0, $file, $l, 383*6236dae4SAndroid Build Coastguard Worker "Illegal !checksrc! command"); 384*6236dae4SAndroid Build Coastguard Worker } 385*6236dae4SAndroid Build Coastguard Worker } 386*6236dae4SAndroid Build Coastguard Worker} 387*6236dae4SAndroid Build Coastguard Worker 388*6236dae4SAndroid Build Coastguard Workersub nostrings { 389*6236dae4SAndroid Build Coastguard Worker my ($str) = @_; 390*6236dae4SAndroid Build Coastguard Worker $str =~ s/\".*\"//g; 391*6236dae4SAndroid Build Coastguard Worker return $str; 392*6236dae4SAndroid Build Coastguard Worker} 393*6236dae4SAndroid Build Coastguard Worker 394*6236dae4SAndroid Build Coastguard Workersub scanfile { 395*6236dae4SAndroid Build Coastguard Worker my ($file) = @_; 396*6236dae4SAndroid Build Coastguard Worker 397*6236dae4SAndroid Build Coastguard Worker my $line = 1; 398*6236dae4SAndroid Build Coastguard Worker my $prevl=""; 399*6236dae4SAndroid Build Coastguard Worker my $prevpl=""; 400*6236dae4SAndroid Build Coastguard Worker my $l = ""; 401*6236dae4SAndroid Build Coastguard Worker my $prep = 0; 402*6236dae4SAndroid Build Coastguard Worker my $prevp = 0; 403*6236dae4SAndroid Build Coastguard Worker open(my $R, '<', $file) || die "failed to open $file"; 404*6236dae4SAndroid Build Coastguard Worker 405*6236dae4SAndroid Build Coastguard Worker my $incomment=0; 406*6236dae4SAndroid Build Coastguard Worker my @copyright=(); 407*6236dae4SAndroid Build Coastguard Worker my %includes; 408*6236dae4SAndroid Build Coastguard Worker checksrc_clear(); # for file based ignores 409*6236dae4SAndroid Build Coastguard Worker accept_violations(); 410*6236dae4SAndroid Build Coastguard Worker 411*6236dae4SAndroid Build Coastguard Worker while(<$R>) { 412*6236dae4SAndroid Build Coastguard Worker $windows_os ? $_ =~ s/\r?\n$// : chomp; 413*6236dae4SAndroid Build Coastguard Worker my $l = $_; 414*6236dae4SAndroid Build Coastguard Worker my $ol = $l; # keep the unmodified line for error reporting 415*6236dae4SAndroid Build Coastguard Worker my $column = 0; 416*6236dae4SAndroid Build Coastguard Worker 417*6236dae4SAndroid Build Coastguard Worker # check for !checksrc! commands 418*6236dae4SAndroid Build Coastguard Worker if($l =~ /\!checksrc\! (.*)/) { 419*6236dae4SAndroid Build Coastguard Worker my $cmd = $1; 420*6236dae4SAndroid Build Coastguard Worker checksrc($cmd, $line, $file, $l) 421*6236dae4SAndroid Build Coastguard Worker } 422*6236dae4SAndroid Build Coastguard Worker 423*6236dae4SAndroid Build Coastguard Worker if($l =~ /^#line (\d+) \"([^\"]*)\"/) { 424*6236dae4SAndroid Build Coastguard Worker # a #line instruction 425*6236dae4SAndroid Build Coastguard Worker $file = $2; 426*6236dae4SAndroid Build Coastguard Worker $line = $1; 427*6236dae4SAndroid Build Coastguard Worker next; 428*6236dae4SAndroid Build Coastguard Worker } 429*6236dae4SAndroid Build Coastguard Worker 430*6236dae4SAndroid Build Coastguard Worker # check for a copyright statement and save the years 431*6236dae4SAndroid Build Coastguard Worker if($l =~ /\* +copyright .* (\d\d\d\d|)/i) { 432*6236dae4SAndroid Build Coastguard Worker my $count = 0; 433*6236dae4SAndroid Build Coastguard Worker while($l =~ /([\d]{4})/g) { 434*6236dae4SAndroid Build Coastguard Worker push @copyright, { 435*6236dae4SAndroid Build Coastguard Worker year => $1, 436*6236dae4SAndroid Build Coastguard Worker line => $line, 437*6236dae4SAndroid Build Coastguard Worker col => index($l, $1), 438*6236dae4SAndroid Build Coastguard Worker code => $l 439*6236dae4SAndroid Build Coastguard Worker }; 440*6236dae4SAndroid Build Coastguard Worker $count++; 441*6236dae4SAndroid Build Coastguard Worker } 442*6236dae4SAndroid Build Coastguard Worker if(!$count) { 443*6236dae4SAndroid Build Coastguard Worker # year-less 444*6236dae4SAndroid Build Coastguard Worker push @copyright, { 445*6236dae4SAndroid Build Coastguard Worker year => -1, 446*6236dae4SAndroid Build Coastguard Worker line => $line, 447*6236dae4SAndroid Build Coastguard Worker col => index($l, $1), 448*6236dae4SAndroid Build Coastguard Worker code => $l 449*6236dae4SAndroid Build Coastguard Worker }; 450*6236dae4SAndroid Build Coastguard Worker } 451*6236dae4SAndroid Build Coastguard Worker } 452*6236dae4SAndroid Build Coastguard Worker 453*6236dae4SAndroid Build Coastguard Worker # detect long lines 454*6236dae4SAndroid Build Coastguard Worker if(length($l) > $max_column) { 455*6236dae4SAndroid Build Coastguard Worker checkwarn("LONGLINE", $line, length($l), $file, $l, 456*6236dae4SAndroid Build Coastguard Worker "Longer than $max_column columns"); 457*6236dae4SAndroid Build Coastguard Worker } 458*6236dae4SAndroid Build Coastguard Worker # detect TAB characters 459*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*)\t/) { 460*6236dae4SAndroid Build Coastguard Worker checkwarn("TABS", 461*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $l, "Contains TAB character", 1); 462*6236dae4SAndroid Build Coastguard Worker } 463*6236dae4SAndroid Build Coastguard Worker # detect trailing whitespace 464*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*)[ \t]+\z/) { 465*6236dae4SAndroid Build Coastguard Worker checkwarn("TRAILINGSPACE", 466*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $l, "Trailing whitespace"); 467*6236dae4SAndroid Build Coastguard Worker } 468*6236dae4SAndroid Build Coastguard Worker 469*6236dae4SAndroid Build Coastguard Worker # no space after comment start 470*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*)\/\*\w/) { 471*6236dae4SAndroid Build Coastguard Worker checkwarn("COMMENTNOSPACESTART", 472*6236dae4SAndroid Build Coastguard Worker $line, length($1) + 2, $file, $l, 473*6236dae4SAndroid Build Coastguard Worker "Missing space after comment start"); 474*6236dae4SAndroid Build Coastguard Worker } 475*6236dae4SAndroid Build Coastguard Worker # no space at comment end 476*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*)\w\*\//) { 477*6236dae4SAndroid Build Coastguard Worker checkwarn("COMMENTNOSPACEEND", 478*6236dae4SAndroid Build Coastguard Worker $line, length($1) + 1, $file, $l, 479*6236dae4SAndroid Build Coastguard Worker "Missing space end comment end"); 480*6236dae4SAndroid Build Coastguard Worker } 481*6236dae4SAndroid Build Coastguard Worker # ------------------------------------------------------------ 482*6236dae4SAndroid Build Coastguard Worker # Above this marker, the checks were done on lines *including* 483*6236dae4SAndroid Build Coastguard Worker # comments 484*6236dae4SAndroid Build Coastguard Worker # ------------------------------------------------------------ 485*6236dae4SAndroid Build Coastguard Worker 486*6236dae4SAndroid Build Coastguard Worker # strip off C89 comments 487*6236dae4SAndroid Build Coastguard Worker 488*6236dae4SAndroid Build Coastguard Worker comment: 489*6236dae4SAndroid Build Coastguard Worker if(!$incomment) { 490*6236dae4SAndroid Build Coastguard Worker if($l =~ s/\/\*.*\*\// /g) { 491*6236dae4SAndroid Build Coastguard Worker # full /* comments */ were removed! 492*6236dae4SAndroid Build Coastguard Worker } 493*6236dae4SAndroid Build Coastguard Worker if($l =~ s/\/\*.*//) { 494*6236dae4SAndroid Build Coastguard Worker # start of /* comment was removed 495*6236dae4SAndroid Build Coastguard Worker $incomment = 1; 496*6236dae4SAndroid Build Coastguard Worker } 497*6236dae4SAndroid Build Coastguard Worker } 498*6236dae4SAndroid Build Coastguard Worker else { 499*6236dae4SAndroid Build Coastguard Worker if($l =~ s/.*\*\///) { 500*6236dae4SAndroid Build Coastguard Worker # end of comment */ was removed 501*6236dae4SAndroid Build Coastguard Worker $incomment = 0; 502*6236dae4SAndroid Build Coastguard Worker goto comment; 503*6236dae4SAndroid Build Coastguard Worker } 504*6236dae4SAndroid Build Coastguard Worker else { 505*6236dae4SAndroid Build Coastguard Worker # still within a comment 506*6236dae4SAndroid Build Coastguard Worker $l=""; 507*6236dae4SAndroid Build Coastguard Worker } 508*6236dae4SAndroid Build Coastguard Worker } 509*6236dae4SAndroid Build Coastguard Worker 510*6236dae4SAndroid Build Coastguard Worker # ------------------------------------------------------------ 511*6236dae4SAndroid Build Coastguard Worker # Below this marker, the checks were done on lines *without* 512*6236dae4SAndroid Build Coastguard Worker # comments 513*6236dae4SAndroid Build Coastguard Worker # ------------------------------------------------------------ 514*6236dae4SAndroid Build Coastguard Worker 515*6236dae4SAndroid Build Coastguard Worker # prev line was a preprocessor **and** ended with a backslash 516*6236dae4SAndroid Build Coastguard Worker if($prep && ($prevpl =~ /\\ *\z/)) { 517*6236dae4SAndroid Build Coastguard Worker # this is still a preprocessor line 518*6236dae4SAndroid Build Coastguard Worker $prep = 1; 519*6236dae4SAndroid Build Coastguard Worker goto preproc; 520*6236dae4SAndroid Build Coastguard Worker } 521*6236dae4SAndroid Build Coastguard Worker $prep = 0; 522*6236dae4SAndroid Build Coastguard Worker 523*6236dae4SAndroid Build Coastguard Worker # crude attempt to detect // comments without too many false 524*6236dae4SAndroid Build Coastguard Worker # positives 525*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(([^"\*]*)[^:"]|)\/\//) { 526*6236dae4SAndroid Build Coastguard Worker checkwarn("CPPCOMMENTS", 527*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $l, "\/\/ comment"); 528*6236dae4SAndroid Build Coastguard Worker } 529*6236dae4SAndroid Build Coastguard Worker 530*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(\#\s*include\s+)([\">].*[>}"])/) { 531*6236dae4SAndroid Build Coastguard Worker my ($pre, $path) = ($1, $2); 532*6236dae4SAndroid Build Coastguard Worker if($includes{$path}) { 533*6236dae4SAndroid Build Coastguard Worker checkwarn("INCLUDEDUP", 534*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $l, "duplicated include"); 535*6236dae4SAndroid Build Coastguard Worker } 536*6236dae4SAndroid Build Coastguard Worker $includes{$path} = $l; 537*6236dae4SAndroid Build Coastguard Worker } 538*6236dae4SAndroid Build Coastguard Worker 539*6236dae4SAndroid Build Coastguard Worker # detect and strip preprocessor directives 540*6236dae4SAndroid Build Coastguard Worker if($l =~ /^[ \t]*\#/) { 541*6236dae4SAndroid Build Coastguard Worker # preprocessor line 542*6236dae4SAndroid Build Coastguard Worker $prep = 1; 543*6236dae4SAndroid Build Coastguard Worker goto preproc; 544*6236dae4SAndroid Build Coastguard Worker } 545*6236dae4SAndroid Build Coastguard Worker 546*6236dae4SAndroid Build Coastguard Worker my $nostr = nostrings($l); 547*6236dae4SAndroid Build Coastguard Worker # check spaces after for/if/while/function call 548*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*)(for|if|while|switch| ([a-zA-Z0-9_]+)) \((.)/) { 549*6236dae4SAndroid Build Coastguard Worker my ($leading, $word, $extra, $first)=($1,$2,$3,$4); 550*6236dae4SAndroid Build Coastguard Worker if($1 =~ / *\#/) { 551*6236dae4SAndroid Build Coastguard Worker # this is a #if, treat it differently 552*6236dae4SAndroid Build Coastguard Worker } 553*6236dae4SAndroid Build Coastguard Worker elsif(defined $3 && $3 eq "return") { 554*6236dae4SAndroid Build Coastguard Worker # return must have a space 555*6236dae4SAndroid Build Coastguard Worker } 556*6236dae4SAndroid Build Coastguard Worker elsif(defined $3 && $3 eq "case") { 557*6236dae4SAndroid Build Coastguard Worker # case must have a space 558*6236dae4SAndroid Build Coastguard Worker } 559*6236dae4SAndroid Build Coastguard Worker elsif(($first eq "*") && ($word !~ /(for|if|while|switch)/)) { 560*6236dae4SAndroid Build Coastguard Worker # A "(*" beginning makes the space OK because it wants to 561*6236dae4SAndroid Build Coastguard Worker # allow function pointer declared 562*6236dae4SAndroid Build Coastguard Worker } 563*6236dae4SAndroid Build Coastguard Worker elsif($1 =~ / *typedef/) { 564*6236dae4SAndroid Build Coastguard Worker # typedefs can use space-paren 565*6236dae4SAndroid Build Coastguard Worker } 566*6236dae4SAndroid Build Coastguard Worker else { 567*6236dae4SAndroid Build Coastguard Worker checkwarn("SPACEBEFOREPAREN", $line, length($leading)+length($word), $file, $l, 568*6236dae4SAndroid Build Coastguard Worker "$word with space"); 569*6236dae4SAndroid Build Coastguard Worker } 570*6236dae4SAndroid Build Coastguard Worker } 571*6236dae4SAndroid Build Coastguard Worker # check for '== NULL' in if/while conditions but not if the thing on 572*6236dae4SAndroid Build Coastguard Worker # the left of it is a function call 573*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*)(if|while)(\(.*?)([!=]= NULL|NULL [!=]=)/) { 574*6236dae4SAndroid Build Coastguard Worker checkwarn("EQUALSNULL", $line, 575*6236dae4SAndroid Build Coastguard Worker length($1) + length($2) + length($3), 576*6236dae4SAndroid Build Coastguard Worker $file, $l, "we prefer !variable instead of \"== NULL\" comparisons"); 577*6236dae4SAndroid Build Coastguard Worker } 578*6236dae4SAndroid Build Coastguard Worker 579*6236dae4SAndroid Build Coastguard Worker # check for '!= 0' in if/while conditions but not if the thing on 580*6236dae4SAndroid Build Coastguard Worker # the left of it is a function call 581*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*)(if|while)(\(.*[^)]) != 0[^x]/) { 582*6236dae4SAndroid Build Coastguard Worker checkwarn("NOTEQUALSZERO", $line, 583*6236dae4SAndroid Build Coastguard Worker length($1) + length($2) + length($3), 584*6236dae4SAndroid Build Coastguard Worker $file, $l, "we prefer if(rc) instead of \"rc != 0\" comparisons"); 585*6236dae4SAndroid Build Coastguard Worker } 586*6236dae4SAndroid Build Coastguard Worker 587*6236dae4SAndroid Build Coastguard Worker # check spaces in 'do {' 588*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^( *)do( *)\{/ && length($2) != 1) { 589*6236dae4SAndroid Build Coastguard Worker checkwarn("DOBRACE", $line, length($1) + 2, $file, $l, "one space after do before brace"); 590*6236dae4SAndroid Build Coastguard Worker } 591*6236dae4SAndroid Build Coastguard Worker # check spaces in 'do {' 592*6236dae4SAndroid Build Coastguard Worker elsif($nostr =~ /^( *)\}( *)while/ && length($2) != 1) { 593*6236dae4SAndroid Build Coastguard Worker checkwarn("BRACEWHILE", $line, length($1) + 2, $file, $l, "one space between brace and while"); 594*6236dae4SAndroid Build Coastguard Worker } 595*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^((.*\s)(if) *\()(.*)\)(.*)/) { 596*6236dae4SAndroid Build Coastguard Worker my $pos = length($1); 597*6236dae4SAndroid Build Coastguard Worker my $postparen = $5; 598*6236dae4SAndroid Build Coastguard Worker my $cond = $4; 599*6236dae4SAndroid Build Coastguard Worker if($cond =~ / = /) { 600*6236dae4SAndroid Build Coastguard Worker checkwarn("ASSIGNWITHINCONDITION", 601*6236dae4SAndroid Build Coastguard Worker $line, $pos+1, $file, $l, 602*6236dae4SAndroid Build Coastguard Worker "assignment within conditional expression"); 603*6236dae4SAndroid Build Coastguard Worker } 604*6236dae4SAndroid Build Coastguard Worker my $temp = $cond; 605*6236dae4SAndroid Build Coastguard Worker $temp =~ s/\(//g; # remove open parens 606*6236dae4SAndroid Build Coastguard Worker my $openc = length($cond) - length($temp); 607*6236dae4SAndroid Build Coastguard Worker 608*6236dae4SAndroid Build Coastguard Worker $temp = $cond; 609*6236dae4SAndroid Build Coastguard Worker $temp =~ s/\)//g; # remove close parens 610*6236dae4SAndroid Build Coastguard Worker my $closec = length($cond) - length($temp); 611*6236dae4SAndroid Build Coastguard Worker my $even = $openc == $closec; 612*6236dae4SAndroid Build Coastguard Worker 613*6236dae4SAndroid Build Coastguard Worker if($l =~ / *\#/) { 614*6236dae4SAndroid Build Coastguard Worker # this is a #if, treat it differently 615*6236dae4SAndroid Build Coastguard Worker } 616*6236dae4SAndroid Build Coastguard Worker elsif($even && $postparen && 617*6236dae4SAndroid Build Coastguard Worker ($postparen !~ /^ *$/) && ($postparen !~ /^ *[,{&|\\]+/)) { 618*6236dae4SAndroid Build Coastguard Worker checkwarn("ONELINECONDITION", 619*6236dae4SAndroid Build Coastguard Worker $line, length($l)-length($postparen), $file, $l, 620*6236dae4SAndroid Build Coastguard Worker "conditional block on the same line"); 621*6236dae4SAndroid Build Coastguard Worker } 622*6236dae4SAndroid Build Coastguard Worker } 623*6236dae4SAndroid Build Coastguard Worker # check spaces after open parentheses 624*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*[a-z])\( /i) { 625*6236dae4SAndroid Build Coastguard Worker checkwarn("SPACEAFTERPAREN", 626*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $l, 627*6236dae4SAndroid Build Coastguard Worker "space after open parenthesis"); 628*6236dae4SAndroid Build Coastguard Worker } 629*6236dae4SAndroid Build Coastguard Worker 630*6236dae4SAndroid Build Coastguard Worker # check spaces before Logical AND operator 631*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*)\w&&/i) { 632*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACEAND", 633*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $l, 634*6236dae4SAndroid Build Coastguard Worker "missing space before Logical AND"); 635*6236dae4SAndroid Build Coastguard Worker } 636*6236dae4SAndroid Build Coastguard Worker 637*6236dae4SAndroid Build Coastguard Worker # check spaces after Logical AND operator 638*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*&&)\w/i) { 639*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACEAND", 640*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $l, 641*6236dae4SAndroid Build Coastguard Worker "missing space after Logical AND"); 642*6236dae4SAndroid Build Coastguard Worker } 643*6236dae4SAndroid Build Coastguard Worker 644*6236dae4SAndroid Build Coastguard Worker # check spaces before colon 645*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*[^']\?[^'].*)(\w|\)|\]|')\:/i) { 646*6236dae4SAndroid Build Coastguard Worker my $m = $1; 647*6236dae4SAndroid Build Coastguard Worker my $e = $nostr; 648*6236dae4SAndroid Build Coastguard Worker $e =~ s/'(.)':'(.)'/$1:$2/g; # eliminate chars quotes that surround colon 649*6236dae4SAndroid Build Coastguard Worker $e =~ s/':'//g; # ignore these 650*6236dae4SAndroid Build Coastguard Worker if($e =~ /^(.*[^']\?[^'].*)(\w|\)|\]|')\:/i) { 651*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACEC", 652*6236dae4SAndroid Build Coastguard Worker $line, length($m)+1, $file, $l, 653*6236dae4SAndroid Build Coastguard Worker "missing space before colon"); 654*6236dae4SAndroid Build Coastguard Worker } 655*6236dae4SAndroid Build Coastguard Worker } 656*6236dae4SAndroid Build Coastguard Worker # check spaces after colon 657*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*[^'"]\?[^'"].*)\:(\w|\)|\]|')/i) { 658*6236dae4SAndroid Build Coastguard Worker my $m = $1; 659*6236dae4SAndroid Build Coastguard Worker my $e = $nostr; 660*6236dae4SAndroid Build Coastguard Worker $e =~ s/'(.)':'(.)'/$1:$2/g; # eliminate chars quotes that surround colon 661*6236dae4SAndroid Build Coastguard Worker $e =~ s/':'//g; # ignore these 662*6236dae4SAndroid Build Coastguard Worker if($e =~ /^(.*[^'"]\?[^'"].*)\:(\w|\)|\]|')/i) { 663*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACEC", 664*6236dae4SAndroid Build Coastguard Worker $line, length($m)+1, $file, $l, 665*6236dae4SAndroid Build Coastguard Worker "missing space after colon"); 666*6236dae4SAndroid Build Coastguard Worker } 667*6236dae4SAndroid Build Coastguard Worker } 668*6236dae4SAndroid Build Coastguard Worker 669*6236dae4SAndroid Build Coastguard Worker # check spaces before question mark 670*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*)(\w|\)|\]|')\?/i) { 671*6236dae4SAndroid Build Coastguard Worker my $m = $1; 672*6236dae4SAndroid Build Coastguard Worker my $e = $nostr; 673*6236dae4SAndroid Build Coastguard Worker $e =~ s/'?'//g; # ignore these 674*6236dae4SAndroid Build Coastguard Worker if($e =~ /^(.*)(\w|\)|\]|')\?/i) { 675*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACEQ", 676*6236dae4SAndroid Build Coastguard Worker $line, length($m)+1, $file, $l, 677*6236dae4SAndroid Build Coastguard Worker "missing space before question mark"); 678*6236dae4SAndroid Build Coastguard Worker } 679*6236dae4SAndroid Build Coastguard Worker } 680*6236dae4SAndroid Build Coastguard Worker # check spaces after question mark 681*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*)\?\w/i) { 682*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACEQ", 683*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $l, 684*6236dae4SAndroid Build Coastguard Worker "missing space after question mark"); 685*6236dae4SAndroid Build Coastguard Worker } 686*6236dae4SAndroid Build Coastguard Worker 687*6236dae4SAndroid Build Coastguard Worker # check spaces before less or greater than 688*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*)(\w|\)|\])[<>]/) { 689*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACETHAN", 690*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $l, 691*6236dae4SAndroid Build Coastguard Worker "missing space before less or greater than"); 692*6236dae4SAndroid Build Coastguard Worker } 693*6236dae4SAndroid Build Coastguard Worker # check spaces after less or greater than 694*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*)[^-][<>](\w|\(|\[)/) { 695*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACETHAN", 696*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $l, 697*6236dae4SAndroid Build Coastguard Worker "missing space after less or greater than"); 698*6236dae4SAndroid Build Coastguard Worker } 699*6236dae4SAndroid Build Coastguard Worker 700*6236dae4SAndroid Build Coastguard Worker # check spaces before close parentheses, unless it was a space or a 701*6236dae4SAndroid Build Coastguard Worker # close parenthesis! 702*6236dae4SAndroid Build Coastguard Worker if($l =~ /(.*[^\) ]) \)/) { 703*6236dae4SAndroid Build Coastguard Worker checkwarn("SPACEBEFORECLOSE", 704*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $l, 705*6236dae4SAndroid Build Coastguard Worker "space before close parenthesis"); 706*6236dae4SAndroid Build Coastguard Worker } 707*6236dae4SAndroid Build Coastguard Worker 708*6236dae4SAndroid Build Coastguard Worker # check spaces before comma! 709*6236dae4SAndroid Build Coastguard Worker if($l =~ /(.*[^ ]) ,/) { 710*6236dae4SAndroid Build Coastguard Worker checkwarn("SPACEBEFORECOMMA", 711*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $l, 712*6236dae4SAndroid Build Coastguard Worker "space before comma"); 713*6236dae4SAndroid Build Coastguard Worker } 714*6236dae4SAndroid Build Coastguard Worker 715*6236dae4SAndroid Build Coastguard Worker # check for "return(" without space 716*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*)return\(/) { 717*6236dae4SAndroid Build Coastguard Worker if($1 =~ / *\#/) { 718*6236dae4SAndroid Build Coastguard Worker # this is a #if, treat it differently 719*6236dae4SAndroid Build Coastguard Worker } 720*6236dae4SAndroid Build Coastguard Worker else { 721*6236dae4SAndroid Build Coastguard Worker checkwarn("RETURNNOSPACE", $line, length($1)+6, $file, $l, 722*6236dae4SAndroid Build Coastguard Worker "return without space before paren"); 723*6236dae4SAndroid Build Coastguard Worker } 724*6236dae4SAndroid Build Coastguard Worker } 725*6236dae4SAndroid Build Coastguard Worker 726*6236dae4SAndroid Build Coastguard Worker # check for "sizeof" without parenthesis 727*6236dae4SAndroid Build Coastguard Worker if(($l =~ /^(.*)sizeof *([ (])/) && ($2 ne "(")) { 728*6236dae4SAndroid Build Coastguard Worker if($1 =~ / *\#/) { 729*6236dae4SAndroid Build Coastguard Worker # this is a #if, treat it differently 730*6236dae4SAndroid Build Coastguard Worker } 731*6236dae4SAndroid Build Coastguard Worker else { 732*6236dae4SAndroid Build Coastguard Worker checkwarn("SIZEOFNOPAREN", $line, length($1)+6, $file, $l, 733*6236dae4SAndroid Build Coastguard Worker "sizeof without parenthesis"); 734*6236dae4SAndroid Build Coastguard Worker } 735*6236dae4SAndroid Build Coastguard Worker } 736*6236dae4SAndroid Build Coastguard Worker 737*6236dae4SAndroid Build Coastguard Worker # check for comma without space 738*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*),[^ \n]/) { 739*6236dae4SAndroid Build Coastguard Worker my $pref=$1; 740*6236dae4SAndroid Build Coastguard Worker my $ign=0; 741*6236dae4SAndroid Build Coastguard Worker if($pref =~ / *\#/) { 742*6236dae4SAndroid Build Coastguard Worker # this is a #if, treat it differently 743*6236dae4SAndroid Build Coastguard Worker $ign=1; 744*6236dae4SAndroid Build Coastguard Worker } 745*6236dae4SAndroid Build Coastguard Worker elsif($pref =~ /\/\*/) { 746*6236dae4SAndroid Build Coastguard Worker # this is a comment 747*6236dae4SAndroid Build Coastguard Worker $ign=1; 748*6236dae4SAndroid Build Coastguard Worker } 749*6236dae4SAndroid Build Coastguard Worker elsif($pref =~ /[\"\']/) { 750*6236dae4SAndroid Build Coastguard Worker $ign = 1; 751*6236dae4SAndroid Build Coastguard Worker # There is a quote here, figure out whether the comma is 752*6236dae4SAndroid Build Coastguard Worker # within a string or '' or not. 753*6236dae4SAndroid Build Coastguard Worker if($pref =~ /\"/) { 754*6236dae4SAndroid Build Coastguard Worker # within a string 755*6236dae4SAndroid Build Coastguard Worker } 756*6236dae4SAndroid Build Coastguard Worker elsif($pref =~ /\'$/) { 757*6236dae4SAndroid Build Coastguard Worker # a single letter 758*6236dae4SAndroid Build Coastguard Worker } 759*6236dae4SAndroid Build Coastguard Worker else { 760*6236dae4SAndroid Build Coastguard Worker $ign = 0; 761*6236dae4SAndroid Build Coastguard Worker } 762*6236dae4SAndroid Build Coastguard Worker } 763*6236dae4SAndroid Build Coastguard Worker if(!$ign) { 764*6236dae4SAndroid Build Coastguard Worker checkwarn("COMMANOSPACE", $line, length($pref)+1, $file, $l, 765*6236dae4SAndroid Build Coastguard Worker "comma without following space"); 766*6236dae4SAndroid Build Coastguard Worker } 767*6236dae4SAndroid Build Coastguard Worker } 768*6236dae4SAndroid Build Coastguard Worker 769*6236dae4SAndroid Build Coastguard Worker # check for "} else" 770*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*)\} *else/) { 771*6236dae4SAndroid Build Coastguard Worker checkwarn("BRACEELSE", 772*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $l, "else after closing brace on same line"); 773*6236dae4SAndroid Build Coastguard Worker } 774*6236dae4SAndroid Build Coastguard Worker # check for "){" 775*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*)\)\{/) { 776*6236dae4SAndroid Build Coastguard Worker checkwarn("PARENBRACE", 777*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $l, "missing space after close paren"); 778*6236dae4SAndroid Build Coastguard Worker } 779*6236dae4SAndroid Build Coastguard Worker # check for "^{" with an empty line before it 780*6236dae4SAndroid Build Coastguard Worker if(($l =~ /^\{/) && ($prevl =~ /^[ \t]*\z/)) { 781*6236dae4SAndroid Build Coastguard Worker checkwarn("EMPTYLINEBRACE", 782*6236dae4SAndroid Build Coastguard Worker $line, 0, $file, $l, "empty line before open brace"); 783*6236dae4SAndroid Build Coastguard Worker } 784*6236dae4SAndroid Build Coastguard Worker 785*6236dae4SAndroid Build Coastguard Worker # check for space before the semicolon last in a line 786*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*[^ ].*) ;$/) { 787*6236dae4SAndroid Build Coastguard Worker checkwarn("SPACESEMICOLON", 788*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, "no space before semicolon"); 789*6236dae4SAndroid Build Coastguard Worker } 790*6236dae4SAndroid Build Coastguard Worker 791*6236dae4SAndroid Build Coastguard Worker # check for space before the colon in a switch label 792*6236dae4SAndroid Build Coastguard Worker if($l =~ /^( *(case .+|default)) :/) { 793*6236dae4SAndroid Build Coastguard Worker checkwarn("SPACESWITCHCOLON", 794*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, "no space before colon of switch label"); 795*6236dae4SAndroid Build Coastguard Worker } 796*6236dae4SAndroid Build Coastguard Worker 797*6236dae4SAndroid Build Coastguard Worker if($prevl !~ /\?\z/ && $l =~ /^ +([A-Za-z_][A-Za-z0-9_]*):$/ && $1 ne 'default') { 798*6236dae4SAndroid Build Coastguard Worker checkwarn("SPACEBEFORELABEL", 799*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, "no space before label"); 800*6236dae4SAndroid Build Coastguard Worker } 801*6236dae4SAndroid Build Coastguard Worker 802*6236dae4SAndroid Build Coastguard Worker # scan for use of banned functions 803*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*\W) 804*6236dae4SAndroid Build Coastguard Worker (gmtime|localtime| 805*6236dae4SAndroid Build Coastguard Worker gets| 806*6236dae4SAndroid Build Coastguard Worker strtok| 807*6236dae4SAndroid Build Coastguard Worker v?sprintf| 808*6236dae4SAndroid Build Coastguard Worker (str|_mbs|_tcs|_wcs)n?cat| 809*6236dae4SAndroid Build Coastguard Worker LoadLibrary(Ex)?(A|W)?| 810*6236dae4SAndroid Build Coastguard Worker _?w?access) 811*6236dae4SAndroid Build Coastguard Worker \s*\( 812*6236dae4SAndroid Build Coastguard Worker /x) { 813*6236dae4SAndroid Build Coastguard Worker checkwarn("BANNEDFUNC", 814*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, 815*6236dae4SAndroid Build Coastguard Worker "use of $2 is banned"); 816*6236dae4SAndroid Build Coastguard Worker } 817*6236dae4SAndroid Build Coastguard Worker if($warnings{"STRERROR"}) { 818*6236dae4SAndroid Build Coastguard Worker # scan for use of banned strerror. This is not a BANNEDFUNC to 819*6236dae4SAndroid Build Coastguard Worker # allow for individual enable/disable of this warning. 820*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*\W)(strerror)\s*\(/x) { 821*6236dae4SAndroid Build Coastguard Worker if($1 !~ /^ *\#/) { 822*6236dae4SAndroid Build Coastguard Worker # skip preprocessor lines 823*6236dae4SAndroid Build Coastguard Worker checkwarn("STRERROR", 824*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, 825*6236dae4SAndroid Build Coastguard Worker "use of $2 is banned"); 826*6236dae4SAndroid Build Coastguard Worker } 827*6236dae4SAndroid Build Coastguard Worker } 828*6236dae4SAndroid Build Coastguard Worker } 829*6236dae4SAndroid Build Coastguard Worker if($warnings{"STRNCPY"}) { 830*6236dae4SAndroid Build Coastguard Worker # scan for use of banned strncpy. This is not a BANNEDFUNC to 831*6236dae4SAndroid Build Coastguard Worker # allow for individual enable/disable of this warning. 832*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*\W)(strncpy)\s*\(/x) { 833*6236dae4SAndroid Build Coastguard Worker if($1 !~ /^ *\#/) { 834*6236dae4SAndroid Build Coastguard Worker # skip preprocessor lines 835*6236dae4SAndroid Build Coastguard Worker checkwarn("STRNCPY", 836*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, 837*6236dae4SAndroid Build Coastguard Worker "use of $2 is banned"); 838*6236dae4SAndroid Build Coastguard Worker } 839*6236dae4SAndroid Build Coastguard Worker } 840*6236dae4SAndroid Build Coastguard Worker } 841*6236dae4SAndroid Build Coastguard Worker if($warnings{"STDERR"}) { 842*6236dae4SAndroid Build Coastguard Worker # scan for use of banned stderr. This is not a BANNEDFUNC to 843*6236dae4SAndroid Build Coastguard Worker # allow for individual enable/disable of this warning. 844*6236dae4SAndroid Build Coastguard Worker if($l =~ /^([^\"-]*\W)(stderr)[^\"_]/x) { 845*6236dae4SAndroid Build Coastguard Worker if($1 !~ /^ *\#/) { 846*6236dae4SAndroid Build Coastguard Worker # skip preprocessor lines 847*6236dae4SAndroid Build Coastguard Worker checkwarn("STDERR", 848*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, 849*6236dae4SAndroid Build Coastguard Worker "use of $2 is banned (use tool_stderr instead)"); 850*6236dae4SAndroid Build Coastguard Worker } 851*6236dae4SAndroid Build Coastguard Worker } 852*6236dae4SAndroid Build Coastguard Worker } 853*6236dae4SAndroid Build Coastguard Worker # scan for use of snprintf for curl-internals reasons 854*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*\W)(v?snprintf)\s*\(/x) { 855*6236dae4SAndroid Build Coastguard Worker checkwarn("SNPRINTF", 856*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, 857*6236dae4SAndroid Build Coastguard Worker "use of $2 is banned"); 858*6236dae4SAndroid Build Coastguard Worker } 859*6236dae4SAndroid Build Coastguard Worker 860*6236dae4SAndroid Build Coastguard Worker # scan for use of non-binary fopen without the macro 861*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(.*\W)fopen\s*\([^,]*, *\"([^"]*)/) { 862*6236dae4SAndroid Build Coastguard Worker my $mode = $2; 863*6236dae4SAndroid Build Coastguard Worker if($mode !~ /b/) { 864*6236dae4SAndroid Build Coastguard Worker checkwarn("FOPENMODE", 865*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, 866*6236dae4SAndroid Build Coastguard Worker "use of non-binary fopen without FOPEN_* macro: $mode"); 867*6236dae4SAndroid Build Coastguard Worker } 868*6236dae4SAndroid Build Coastguard Worker } 869*6236dae4SAndroid Build Coastguard Worker 870*6236dae4SAndroid Build Coastguard Worker # check for open brace first on line but not first column only alert 871*6236dae4SAndroid Build Coastguard Worker # if previous line ended with a close paren and it wasn't a cpp line 872*6236dae4SAndroid Build Coastguard Worker if(($prevl =~ /\)\z/) && ($l =~ /^( +)\{/) && !$prevp) { 873*6236dae4SAndroid Build Coastguard Worker checkwarn("BRACEPOS", 874*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, "badly placed open brace"); 875*6236dae4SAndroid Build Coastguard Worker } 876*6236dae4SAndroid Build Coastguard Worker 877*6236dae4SAndroid Build Coastguard Worker # if the previous line starts with if/while/for AND ends with an open 878*6236dae4SAndroid Build Coastguard Worker # brace, or an else statement, check that this line is indented $indent 879*6236dae4SAndroid Build Coastguard Worker # more steps, if not a cpp line 880*6236dae4SAndroid Build Coastguard Worker if(!$prevp && ($prevl =~ /^( *)((if|while|for)\(.*\{|else)\z/)) { 881*6236dae4SAndroid Build Coastguard Worker my $first = length($1); 882*6236dae4SAndroid Build Coastguard Worker # this line has some character besides spaces 883*6236dae4SAndroid Build Coastguard Worker if($l =~ /^( *)[^ ]/) { 884*6236dae4SAndroid Build Coastguard Worker my $second = length($1); 885*6236dae4SAndroid Build Coastguard Worker my $expect = $first+$indent; 886*6236dae4SAndroid Build Coastguard Worker if($expect != $second) { 887*6236dae4SAndroid Build Coastguard Worker my $diff = $second - $first; 888*6236dae4SAndroid Build Coastguard Worker checkwarn("INDENTATION", $line, length($1), $file, $ol, 889*6236dae4SAndroid Build Coastguard Worker "not indented $indent steps (uses $diff)"); 890*6236dae4SAndroid Build Coastguard Worker 891*6236dae4SAndroid Build Coastguard Worker } 892*6236dae4SAndroid Build Coastguard Worker } 893*6236dae4SAndroid Build Coastguard Worker } 894*6236dae4SAndroid Build Coastguard Worker 895*6236dae4SAndroid Build Coastguard Worker # if the previous line starts with if/while/for AND ends with a closed 896*6236dae4SAndroid Build Coastguard Worker # parenthesis and there's an equal number of open and closed 897*6236dae4SAndroid Build Coastguard Worker # parentheses, check that this line is indented $indent more steps, if 898*6236dae4SAndroid Build Coastguard Worker # not a cpp line 899*6236dae4SAndroid Build Coastguard Worker elsif(!$prevp && ($prevl =~ /^( *)(if|while|for)(\(.*\))\z/)) { 900*6236dae4SAndroid Build Coastguard Worker my $first = length($1); 901*6236dae4SAndroid Build Coastguard Worker my $op = $3; 902*6236dae4SAndroid Build Coastguard Worker my $cl = $3; 903*6236dae4SAndroid Build Coastguard Worker 904*6236dae4SAndroid Build Coastguard Worker $op =~ s/[^(]//g; 905*6236dae4SAndroid Build Coastguard Worker $cl =~ s/[^)]//g; 906*6236dae4SAndroid Build Coastguard Worker 907*6236dae4SAndroid Build Coastguard Worker if(length($op) == length($cl)) { 908*6236dae4SAndroid Build Coastguard Worker # this line has some character besides spaces 909*6236dae4SAndroid Build Coastguard Worker if($l =~ /^( *)[^ ]/) { 910*6236dae4SAndroid Build Coastguard Worker my $second = length($1); 911*6236dae4SAndroid Build Coastguard Worker my $expect = $first+$indent; 912*6236dae4SAndroid Build Coastguard Worker if($expect != $second) { 913*6236dae4SAndroid Build Coastguard Worker my $diff = $second - $first; 914*6236dae4SAndroid Build Coastguard Worker checkwarn("INDENTATION", $line, length($1), $file, $ol, 915*6236dae4SAndroid Build Coastguard Worker "not indented $indent steps (uses $diff)"); 916*6236dae4SAndroid Build Coastguard Worker } 917*6236dae4SAndroid Build Coastguard Worker } 918*6236dae4SAndroid Build Coastguard Worker } 919*6236dae4SAndroid Build Coastguard Worker } 920*6236dae4SAndroid Build Coastguard Worker 921*6236dae4SAndroid Build Coastguard Worker # check for 'char * name' 922*6236dae4SAndroid Build Coastguard Worker if(($l =~ /(^.*(char|int|long|void|CURL|CURLM|CURLMsg|[cC]url_[A-Za-z_]+|struct [a-zA-Z_]+) *(\*+)) (\w+)/) && ($4 !~ /^(const|volatile)$/)) { 923*6236dae4SAndroid Build Coastguard Worker checkwarn("ASTERISKSPACE", 924*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, 925*6236dae4SAndroid Build Coastguard Worker "space after declarative asterisk"); 926*6236dae4SAndroid Build Coastguard Worker } 927*6236dae4SAndroid Build Coastguard Worker # check for 'char*' 928*6236dae4SAndroid Build Coastguard Worker if(($l =~ /(^.*(char|int|long|void|curl_slist|CURL|CURLM|CURLMsg|curl_httppost|sockaddr_in|FILE)\*)/)) { 929*6236dae4SAndroid Build Coastguard Worker checkwarn("ASTERISKNOSPACE", 930*6236dae4SAndroid Build Coastguard Worker $line, length($1)-1, $file, $ol, 931*6236dae4SAndroid Build Coastguard Worker "no space before asterisk"); 932*6236dae4SAndroid Build Coastguard Worker } 933*6236dae4SAndroid Build Coastguard Worker 934*6236dae4SAndroid Build Coastguard Worker # check for 'void func() {', but avoid false positives by requiring 935*6236dae4SAndroid Build Coastguard Worker # both an open and closed parentheses before the open brace 936*6236dae4SAndroid Build Coastguard Worker if($l =~ /^((\w).*)\{\z/) { 937*6236dae4SAndroid Build Coastguard Worker my $k = $1; 938*6236dae4SAndroid Build Coastguard Worker $k =~ s/const *//; 939*6236dae4SAndroid Build Coastguard Worker $k =~ s/static *//; 940*6236dae4SAndroid Build Coastguard Worker if($k =~ /\(.*\)/) { 941*6236dae4SAndroid Build Coastguard Worker checkwarn("BRACEPOS", 942*6236dae4SAndroid Build Coastguard Worker $line, length($l)-1, $file, $ol, 943*6236dae4SAndroid Build Coastguard Worker "wrongly placed open brace"); 944*6236dae4SAndroid Build Coastguard Worker } 945*6236dae4SAndroid Build Coastguard Worker } 946*6236dae4SAndroid Build Coastguard Worker 947*6236dae4SAndroid Build Coastguard Worker # check for equals sign without spaces next to it 948*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /(.*)\=[a-z0-9]/i) { 949*6236dae4SAndroid Build Coastguard Worker checkwarn("EQUALSNOSPACE", 950*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $ol, 951*6236dae4SAndroid Build Coastguard Worker "no space after equals sign"); 952*6236dae4SAndroid Build Coastguard Worker } 953*6236dae4SAndroid Build Coastguard Worker # check for equals sign without spaces before it 954*6236dae4SAndroid Build Coastguard Worker elsif($nostr =~ /(.*)[a-z0-9]\=/i) { 955*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACEEQUALS", 956*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $ol, 957*6236dae4SAndroid Build Coastguard Worker "no space before equals sign"); 958*6236dae4SAndroid Build Coastguard Worker } 959*6236dae4SAndroid Build Coastguard Worker 960*6236dae4SAndroid Build Coastguard Worker # check for plus signs without spaces next to it 961*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /(.*)[^+]\+[a-z0-9]/i) { 962*6236dae4SAndroid Build Coastguard Worker checkwarn("PLUSNOSPACE", 963*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $ol, 964*6236dae4SAndroid Build Coastguard Worker "no space after plus sign"); 965*6236dae4SAndroid Build Coastguard Worker } 966*6236dae4SAndroid Build Coastguard Worker # check for plus sign without spaces before it 967*6236dae4SAndroid Build Coastguard Worker elsif($nostr =~ /(.*)[a-z0-9]\+[^+]/i) { 968*6236dae4SAndroid Build Coastguard Worker checkwarn("NOSPACEPLUS", 969*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $ol, 970*6236dae4SAndroid Build Coastguard Worker "no space before plus sign"); 971*6236dae4SAndroid Build Coastguard Worker } 972*6236dae4SAndroid Build Coastguard Worker 973*6236dae4SAndroid Build Coastguard Worker # check for semicolons without space next to it 974*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /(.*)\;[a-z0-9]/i) { 975*6236dae4SAndroid Build Coastguard Worker checkwarn("SEMINOSPACE", 976*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $ol, 977*6236dae4SAndroid Build Coastguard Worker "no space after semicolon"); 978*6236dae4SAndroid Build Coastguard Worker } 979*6236dae4SAndroid Build Coastguard Worker 980*6236dae4SAndroid Build Coastguard Worker # typedef struct ... { 981*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /^(.*)typedef struct.*{/) { 982*6236dae4SAndroid Build Coastguard Worker checkwarn("TYPEDEFSTRUCT", 983*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $ol, 984*6236dae4SAndroid Build Coastguard Worker "typedef'ed struct"); 985*6236dae4SAndroid Build Coastguard Worker } 986*6236dae4SAndroid Build Coastguard Worker 987*6236dae4SAndroid Build Coastguard Worker if($nostr =~ /(.*)! +(\w|\()/) { 988*6236dae4SAndroid Build Coastguard Worker checkwarn("EXCLAMATIONSPACE", 989*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $ol, 990*6236dae4SAndroid Build Coastguard Worker "space after exclamation mark"); 991*6236dae4SAndroid Build Coastguard Worker } 992*6236dae4SAndroid Build Coastguard Worker 993*6236dae4SAndroid Build Coastguard Worker # check for more than one consecutive space before open brace or 994*6236dae4SAndroid Build Coastguard Worker # question mark. Skip lines containing strings since they make it hard 995*6236dae4SAndroid Build Coastguard Worker # due to artificially getting multiple spaces 996*6236dae4SAndroid Build Coastguard Worker if(($l eq $nostr) && 997*6236dae4SAndroid Build Coastguard Worker $nostr =~ /^(.*(\S)) + [{?]/i) { 998*6236dae4SAndroid Build Coastguard Worker checkwarn("MULTISPACE", 999*6236dae4SAndroid Build Coastguard Worker $line, length($1)+1, $file, $ol, 1000*6236dae4SAndroid Build Coastguard Worker "multiple spaces"); 1001*6236dae4SAndroid Build Coastguard Worker } 1002*6236dae4SAndroid Build Coastguard Worker preproc: 1003*6236dae4SAndroid Build Coastguard Worker if($prep) { 1004*6236dae4SAndroid Build Coastguard Worker # scan for use of banned symbols on a preprocessor line 1005*6236dae4SAndroid Build Coastguard Worker if($l =~ /^(^|.*\W) 1006*6236dae4SAndroid Build Coastguard Worker (WIN32) 1007*6236dae4SAndroid Build Coastguard Worker (\W|$) 1008*6236dae4SAndroid Build Coastguard Worker /x) { 1009*6236dae4SAndroid Build Coastguard Worker checkwarn("BANNEDPREPROC", 1010*6236dae4SAndroid Build Coastguard Worker $line, length($1), $file, $ol, 1011*6236dae4SAndroid Build Coastguard Worker "use of $2 is banned from preprocessor lines" . 1012*6236dae4SAndroid Build Coastguard Worker (($2 eq "WIN32") ? ", use _WIN32 instead" : "")); 1013*6236dae4SAndroid Build Coastguard Worker } 1014*6236dae4SAndroid Build Coastguard Worker } 1015*6236dae4SAndroid Build Coastguard Worker $line++; 1016*6236dae4SAndroid Build Coastguard Worker $prevp = $prep; 1017*6236dae4SAndroid Build Coastguard Worker $prevl = $ol if(!$prep); 1018*6236dae4SAndroid Build Coastguard Worker $prevpl = $ol if($prep); 1019*6236dae4SAndroid Build Coastguard Worker } 1020*6236dae4SAndroid Build Coastguard Worker 1021*6236dae4SAndroid Build Coastguard Worker if(!scalar(@copyright)) { 1022*6236dae4SAndroid Build Coastguard Worker checkwarn("COPYRIGHT", 1, 0, $file, "", "Missing copyright statement", 1); 1023*6236dae4SAndroid Build Coastguard Worker } 1024*6236dae4SAndroid Build Coastguard Worker 1025*6236dae4SAndroid Build Coastguard Worker # COPYRIGHTYEAR is an extended warning so we must first see if it has been 1026*6236dae4SAndroid Build Coastguard Worker # enabled in .checksrc 1027*6236dae4SAndroid Build Coastguard Worker if(defined($warnings{"COPYRIGHTYEAR"})) { 1028*6236dae4SAndroid Build Coastguard Worker # The check for updated copyrightyear is overly complicated in order to 1029*6236dae4SAndroid Build Coastguard Worker # not punish current hacking for past sins. The copyright years are 1030*6236dae4SAndroid Build Coastguard Worker # right now a bit behind, so enforcing copyright year checking on all 1031*6236dae4SAndroid Build Coastguard Worker # files would cause hundreds of errors. Instead we only look at files 1032*6236dae4SAndroid Build Coastguard Worker # which are tracked in the Git repo and edited in the workdir, or 1033*6236dae4SAndroid Build Coastguard Worker # committed locally on the branch without being in upstream master. 1034*6236dae4SAndroid Build Coastguard Worker # 1035*6236dae4SAndroid Build Coastguard Worker # The simple and naive test is to simply check for the current year, 1036*6236dae4SAndroid Build Coastguard Worker # but updating the year even without an edit is against project policy 1037*6236dae4SAndroid Build Coastguard Worker # (and it would fail every file on January 1st). 1038*6236dae4SAndroid Build Coastguard Worker # 1039*6236dae4SAndroid Build Coastguard Worker # A rather more interesting, and correct, check would be to not test 1040*6236dae4SAndroid Build Coastguard Worker # only locally committed files but inspect all files wrt the year of 1041*6236dae4SAndroid Build Coastguard Worker # their last commit. Removing the `git rev-list origin/master..HEAD` 1042*6236dae4SAndroid Build Coastguard Worker # condition below will enforce copyright year checks against the year 1043*6236dae4SAndroid Build Coastguard Worker # the file was last committed (and thus edited to some degree). 1044*6236dae4SAndroid Build Coastguard Worker my $commityear = undef; 1045*6236dae4SAndroid Build Coastguard Worker @copyright = sort {$$b{year} cmp $$a{year}} @copyright; 1046*6236dae4SAndroid Build Coastguard Worker 1047*6236dae4SAndroid Build Coastguard Worker # if the file is modified, assume commit year this year 1048*6236dae4SAndroid Build Coastguard Worker if(`git status -s -- "$file"` =~ /^ [MARCU]/) { 1049*6236dae4SAndroid Build Coastguard Worker $commityear = (localtime(time))[5] + 1900; 1050*6236dae4SAndroid Build Coastguard Worker } 1051*6236dae4SAndroid Build Coastguard Worker else { 1052*6236dae4SAndroid Build Coastguard Worker # min-parents=1 to ignore wrong initial commit in truncated repos 1053*6236dae4SAndroid Build Coastguard Worker my $grl = `git rev-list --max-count=1 --min-parents=1 --timestamp HEAD -- "$file"`; 1054*6236dae4SAndroid Build Coastguard Worker if($grl) { 1055*6236dae4SAndroid Build Coastguard Worker chomp $grl; 1056*6236dae4SAndroid Build Coastguard Worker $commityear = (localtime((split(/ /, $grl))[0]))[5] + 1900; 1057*6236dae4SAndroid Build Coastguard Worker } 1058*6236dae4SAndroid Build Coastguard Worker } 1059*6236dae4SAndroid Build Coastguard Worker 1060*6236dae4SAndroid Build Coastguard Worker if(defined($commityear) && scalar(@copyright) && 1061*6236dae4SAndroid Build Coastguard Worker $copyright[0]{year} != $commityear) { 1062*6236dae4SAndroid Build Coastguard Worker checkwarn("COPYRIGHTYEAR", $copyright[0]{line}, $copyright[0]{col}, 1063*6236dae4SAndroid Build Coastguard Worker $file, $copyright[0]{code}, 1064*6236dae4SAndroid Build Coastguard Worker "Copyright year out of date, should be $commityear, " . 1065*6236dae4SAndroid Build Coastguard Worker "is $copyright[0]{year}", 1); 1066*6236dae4SAndroid Build Coastguard Worker } 1067*6236dae4SAndroid Build Coastguard Worker } 1068*6236dae4SAndroid Build Coastguard Worker 1069*6236dae4SAndroid Build Coastguard Worker if($incomment) { 1070*6236dae4SAndroid Build Coastguard Worker checkwarn("OPENCOMMENT", 1, 0, $file, "", "Missing closing comment", 1); 1071*6236dae4SAndroid Build Coastguard Worker } 1072*6236dae4SAndroid Build Coastguard Worker 1073*6236dae4SAndroid Build Coastguard Worker checksrc_endoffile($file); 1074*6236dae4SAndroid Build Coastguard Worker 1075*6236dae4SAndroid Build Coastguard Worker close($R); 1076*6236dae4SAndroid Build Coastguard Worker 1077*6236dae4SAndroid Build Coastguard Worker} 1078*6236dae4SAndroid Build Coastguard Worker 1079*6236dae4SAndroid Build Coastguard Worker 1080*6236dae4SAndroid Build Coastguard Workerif($errors || $warnings || $verbose) { 1081*6236dae4SAndroid Build Coastguard Worker printf "checksrc: %d errors and %d warnings\n", $errors, $warnings; 1082*6236dae4SAndroid Build Coastguard Worker if($suppressed) { 1083*6236dae4SAndroid Build Coastguard Worker printf "checksrc: %d errors and %d warnings suppressed\n", 1084*6236dae4SAndroid Build Coastguard Worker $serrors, 1085*6236dae4SAndroid Build Coastguard Worker $swarnings; 1086*6236dae4SAndroid Build Coastguard Worker } 1087*6236dae4SAndroid Build Coastguard Worker exit 5; # return failure 1088*6236dae4SAndroid Build Coastguard Worker} 1089