1*78fe7221Sdduvall#!/usr/bin/perl -w 2*78fe7221Sdduvall# 3*78fe7221Sdduvall# CDDL HEADER START 4*78fe7221Sdduvall# 5*78fe7221Sdduvall# The contents of this file are subject to the terms of the 6*78fe7221Sdduvall# Common Development and Distribution License (the "License"). 7*78fe7221Sdduvall# You may not use this file except in compliance with the License. 8*78fe7221Sdduvall# 9*78fe7221Sdduvall# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*78fe7221Sdduvall# or http://www.opensolaris.org/os/licensing. 11*78fe7221Sdduvall# See the License for the specific language governing permissions 12*78fe7221Sdduvall# and limitations under the License. 13*78fe7221Sdduvall# 14*78fe7221Sdduvall# When distributing Covered Code, include this CDDL HEADER in each 15*78fe7221Sdduvall# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*78fe7221Sdduvall# If applicable, add the following below this CDDL HEADER, with the 17*78fe7221Sdduvall# fields enclosed by brackets "[]" replaced with your own identifying 18*78fe7221Sdduvall# information: Portions Copyright [yyyy] [name of copyright owner] 19*78fe7221Sdduvall# 20*78fe7221Sdduvall# CDDL HEADER END 21*78fe7221Sdduvall# 22*78fe7221Sdduvall 23*78fe7221Sdduvall# 24*78fe7221Sdduvall# ident "%Z%%M% %I% %E% SMI" 25*78fe7221Sdduvall# 26*78fe7221Sdduvall# Copyright 2005 Sun Microsystems, Inc. All rights reserved. 27*78fe7221Sdduvall# Use is subject to license terms. 28*78fe7221Sdduvall# 29*78fe7221Sdduvall# jstyle - check for some common stylistic errors. 30*78fe7221Sdduvall# 31*78fe7221Sdduvall 32*78fe7221Sdduvallrequire 5.006; 33*78fe7221Sdduvalluse Getopt::Std; 34*78fe7221Sdduvalluse strict; 35*78fe7221Sdduvall 36*78fe7221Sdduvallmy $usage = 37*78fe7221Sdduvall"usage: jstyle [-c] [-h] [-p] [-t] [-v] [-C] file ... 38*78fe7221Sdduvall -c check continuation line indenting 39*78fe7221Sdduvall -h perform heuristic checks that are sometimes wrong 40*78fe7221Sdduvall -p perform some of the more picky checks 41*78fe7221Sdduvall -t insist on indenting by tabs 42*78fe7221Sdduvall -v verbose 43*78fe7221Sdduvall -C don't check anything in header block comments 44*78fe7221Sdduvall"; 45*78fe7221Sdduvall 46*78fe7221Sdduvallmy %opts; 47*78fe7221Sdduvall 48*78fe7221Sdduvall# Keep -s, as it's been around for a while. It just doesn't do anything 49*78fe7221Sdduvall# anymore. 50*78fe7221Sdduvallif (!getopts("chpstvC", \%opts)) { 51*78fe7221Sdduvall print $usage; 52*78fe7221Sdduvall exit 1; 53*78fe7221Sdduvall} 54*78fe7221Sdduvall 55*78fe7221Sdduvallmy $check_continuation = $opts{'c'}; 56*78fe7221Sdduvallmy $heuristic = $opts{'h'}; 57*78fe7221Sdduvallmy $picky = $opts{'p'}; 58*78fe7221Sdduvallmy $tabs = $opts{'t'}; 59*78fe7221Sdduvallmy $verbose = $opts{'v'}; 60*78fe7221Sdduvallmy $ignore_hdr_comment = $opts{'C'}; 61*78fe7221Sdduvall 62*78fe7221Sdduvallmy ($filename, $line, $prev); 63*78fe7221Sdduvall 64*78fe7221Sdduvallmy $fmt; 65*78fe7221Sdduvall 66*78fe7221Sdduvallif ($verbose) { 67*78fe7221Sdduvall $fmt = "%s: %d: %s\n%s\n"; 68*78fe7221Sdduvall} else { 69*78fe7221Sdduvall $fmt = "%s: %d: %s\n"; 70*78fe7221Sdduvall} 71*78fe7221Sdduvall 72*78fe7221Sdduvall# Note, following must be in single quotes so that \s and \w work right. 73*78fe7221Sdduvallmy $typename = '(int|char|boolean|byte|short|long|float|double)'; 74*78fe7221Sdduvallmy $keywords = '(for|if|while|switch|return|catch|synchronized|throw|assert)'; 75*78fe7221Sdduvall# See perlre(1) for the meaning of (??{ ... }) 76*78fe7221Sdduvallmy $annotations = ""; $annotations = qr/@\w+\((?:(?>[^()]+)|(??{ $annotations }))*\)/; 77*78fe7221Sdduvallmy $generics = ""; $generics = qr/<(([\s\w,.?[\]]| & )+|(??{ $generics }))*>/; 78*78fe7221Sdduvallmy $relationalops = qr/>=|<=|<|>|!=|==/; 79*78fe7221Sdduvallmy $shiftops = qr/<<<|>>>|<<|>>/; 80*78fe7221Sdduvallmy $shiftassignmentops = qr/[<>]{2,3}=/; 81*78fe7221Sdduvallmy $assignmentops = qr/[-+\/*|&^%]?=/; 82*78fe7221Sdduvall# These need to be in decreasing order of length 83*78fe7221Sdduvallmy $allops = qr/$shiftassignmentops|$shiftops|$relationalops|$assignmentops/; 84*78fe7221Sdduvall 85*78fe7221Sdduvallif ($#ARGV >= 0) { 86*78fe7221Sdduvall foreach my $arg (@ARGV) { 87*78fe7221Sdduvall if (!open(STDIN, $arg)) { 88*78fe7221Sdduvall printf "%s: can not open\n", $arg; 89*78fe7221Sdduvall } else { 90*78fe7221Sdduvall &jstyle($arg); 91*78fe7221Sdduvall close STDIN; 92*78fe7221Sdduvall } 93*78fe7221Sdduvall } 94*78fe7221Sdduvall} else { 95*78fe7221Sdduvall &jstyle("<stdin>"); 96*78fe7221Sdduvall} 97*78fe7221Sdduvall 98*78fe7221Sdduvallsub err($) { 99*78fe7221Sdduvall printf $fmt, $filename, $., $_[0], $line; 100*78fe7221Sdduvall} 101*78fe7221Sdduvall 102*78fe7221Sdduvallsub jstyle($) { 103*78fe7221Sdduvall 104*78fe7221Sdduvallmy $in_comment = 0; 105*78fe7221Sdduvallmy $in_header_comment = 0; 106*78fe7221Sdduvallmy $in_continuation = 0; 107*78fe7221Sdduvallmy $in_class = 0; 108*78fe7221Sdduvallmy $in_declaration = 0; 109*78fe7221Sdduvallmy $nextok = 0; 110*78fe7221Sdduvallmy $nocheck = 0; 111*78fe7221Sdduvallmy $expect_continuation = 0; 112*78fe7221Sdduvallmy $continuation_indent; 113*78fe7221Sdduvallmy $okmsg; 114*78fe7221Sdduvallmy $comment_prefix; 115*78fe7221Sdduvallmy $comment_done; 116*78fe7221Sdduvallmy $cpp_comment; 117*78fe7221Sdduvall 118*78fe7221Sdduvall$filename = $_[0]; 119*78fe7221Sdduvall 120*78fe7221Sdduvallline: while (<STDIN>) { 121*78fe7221Sdduvall s/\r?\n$//; # strip return and newline 122*78fe7221Sdduvall 123*78fe7221Sdduvall # save the original line, then remove all text from within 124*78fe7221Sdduvall # double or single quotes, we do not want to check such text. 125*78fe7221Sdduvall 126*78fe7221Sdduvall $line = $_; 127*78fe7221Sdduvall s/"[^"]*"/\"\"/g; 128*78fe7221Sdduvall s/'.'/''/g; 129*78fe7221Sdduvall 130*78fe7221Sdduvall # an /* END JSTYLED */ comment ends a no-check block. 131*78fe7221Sdduvall if ($nocheck) { 132*78fe7221Sdduvall if (/\/\* *END *JSTYLED *\*\//) { 133*78fe7221Sdduvall $nocheck = 0; 134*78fe7221Sdduvall } else { 135*78fe7221Sdduvall next line; 136*78fe7221Sdduvall } 137*78fe7221Sdduvall } 138*78fe7221Sdduvall 139*78fe7221Sdduvall # a /*JSTYLED*/ comment indicates that the next line is ok. 140*78fe7221Sdduvall if ($nextok) { 141*78fe7221Sdduvall if ($okmsg) { 142*78fe7221Sdduvall err($okmsg); 143*78fe7221Sdduvall } 144*78fe7221Sdduvall $nextok = 0; 145*78fe7221Sdduvall $okmsg = 0; 146*78fe7221Sdduvall if (/\/\* *JSTYLED.*\*\//) { 147*78fe7221Sdduvall /^.*\/\* *JSTYLED *(.*) *\*\/.*$/; 148*78fe7221Sdduvall $okmsg = $1; 149*78fe7221Sdduvall $nextok = 1; 150*78fe7221Sdduvall } 151*78fe7221Sdduvall $prev = $line; 152*78fe7221Sdduvall next line; 153*78fe7221Sdduvall } 154*78fe7221Sdduvall 155*78fe7221Sdduvall # remember whether we expect to be inside a continuation line. 156*78fe7221Sdduvall $in_continuation = $expect_continuation; 157*78fe7221Sdduvall 158*78fe7221Sdduvall # check for proper continuation line. blank lines 159*78fe7221Sdduvall # in the middle of the 160*78fe7221Sdduvall # continuation do not count. 161*78fe7221Sdduvall # XXX - only check within functions. 162*78fe7221Sdduvall if ($check_continuation && $expect_continuation && $in_class && 163*78fe7221Sdduvall !/^\s*$/) { 164*78fe7221Sdduvall # continuation line must start with whitespace of 165*78fe7221Sdduvall # previous line, plus either 4 spaces or a tab, but 166*78fe7221Sdduvall # do not check lines that start with a string constant 167*78fe7221Sdduvall # since they are often shifted to the left to make them 168*78fe7221Sdduvall # fit on the line. 169*78fe7221Sdduvall if (!/^$continuation_indent \S/ && 170*78fe7221Sdduvall !/^$continuation_indent\t\S/ && !/^\s*"/) { 171*78fe7221Sdduvall err("continuation line improperly indented"); 172*78fe7221Sdduvall } 173*78fe7221Sdduvall $expect_continuation = 0; 174*78fe7221Sdduvall } 175*78fe7221Sdduvall 176*78fe7221Sdduvall # a /* BEGIN JSTYLED */ comment starts a no-check block. 177*78fe7221Sdduvall if (/\/\* *BEGIN *JSTYLED *\*\//) { 178*78fe7221Sdduvall $nocheck = 1; 179*78fe7221Sdduvall } 180*78fe7221Sdduvall 181*78fe7221Sdduvall # a /*JSTYLED*/ comment indicates that the next line is ok. 182*78fe7221Sdduvall if (/\/\* *JSTYLED.*\*\//) { 183*78fe7221Sdduvall /^.*\/\* *JSTYLED *(.*) *\*\/.*$/; 184*78fe7221Sdduvall $okmsg = $1; 185*78fe7221Sdduvall $nextok = 1; 186*78fe7221Sdduvall } 187*78fe7221Sdduvall if (/\/\/ *JSTYLED/) { 188*78fe7221Sdduvall /^.*\/\/ *JSTYLED *(.*)$/; 189*78fe7221Sdduvall $okmsg = $1; 190*78fe7221Sdduvall $nextok = 1; 191*78fe7221Sdduvall } 192*78fe7221Sdduvall 193*78fe7221Sdduvall # is this the beginning or ending of a class? 194*78fe7221Sdduvall if (/^(public\s+)*\w(class|interface)\s/) { 195*78fe7221Sdduvall $in_class = 1; 196*78fe7221Sdduvall $in_declaration = 1; 197*78fe7221Sdduvall $prev = $line; 198*78fe7221Sdduvall next line; 199*78fe7221Sdduvall } 200*78fe7221Sdduvall if (/^}\s*(\/\*.*\*\/\s*)*$/) { 201*78fe7221Sdduvall $in_class = 0; 202*78fe7221Sdduvall $prev = $line; 203*78fe7221Sdduvall next line; 204*78fe7221Sdduvall } 205*78fe7221Sdduvall 206*78fe7221Sdduvall if ($comment_done) { 207*78fe7221Sdduvall $in_comment = 0; 208*78fe7221Sdduvall $in_header_comment = 0; 209*78fe7221Sdduvall $comment_done = 0; 210*78fe7221Sdduvall } 211*78fe7221Sdduvall # does this looks like the start of a block comment? 212*78fe7221Sdduvall if (/^\s*\/\*/ && !/^\s*\/\*.*\*\//) { 213*78fe7221Sdduvall if (/^\s*\/\*./ && !/^\s*\/\*\*$/) { 214*78fe7221Sdduvall err("improper first line of block comment"); 215*78fe7221Sdduvall } 216*78fe7221Sdduvall if (!/^(\t| )*\/\*/) { 217*78fe7221Sdduvall err("block comment not indented properly"); 218*78fe7221Sdduvall } 219*78fe7221Sdduvall $in_comment = 1; 220*78fe7221Sdduvall /^(\s*)\//; 221*78fe7221Sdduvall $comment_prefix = $1; 222*78fe7221Sdduvall if ($comment_prefix eq "") { 223*78fe7221Sdduvall $in_header_comment = 1; 224*78fe7221Sdduvall } 225*78fe7221Sdduvall $prev = $line; 226*78fe7221Sdduvall next line; 227*78fe7221Sdduvall } 228*78fe7221Sdduvall # are we still in the block comment? 229*78fe7221Sdduvall if ($in_comment) { 230*78fe7221Sdduvall if (/^$comment_prefix \*\/$/) { 231*78fe7221Sdduvall $comment_done = 1; 232*78fe7221Sdduvall } elsif (/\*\//) { 233*78fe7221Sdduvall $comment_done = 1; 234*78fe7221Sdduvall err("improper block comment close") 235*78fe7221Sdduvall unless ($ignore_hdr_comment && $in_header_comment); 236*78fe7221Sdduvall } elsif (!/^$comment_prefix \*[ \t]/ && 237*78fe7221Sdduvall !/^$comment_prefix \*$/) { 238*78fe7221Sdduvall err("improper block comment") 239*78fe7221Sdduvall unless ($ignore_hdr_comment && $in_header_comment); 240*78fe7221Sdduvall } 241*78fe7221Sdduvall } 242*78fe7221Sdduvall 243*78fe7221Sdduvall if ($in_header_comment && $ignore_hdr_comment) { 244*78fe7221Sdduvall $prev = $line; 245*78fe7221Sdduvall next line; 246*78fe7221Sdduvall } 247*78fe7221Sdduvall 248*78fe7221Sdduvall # check for errors that might occur in comments and in code. 249*78fe7221Sdduvall 250*78fe7221Sdduvall # check length of line. 251*78fe7221Sdduvall # first, a quick check to see if there is any chance of being too long. 252*78fe7221Sdduvall if ($line =~ tr/\t/\t/ * 7 + length($line) > 80) { 253*78fe7221Sdduvall # yes, there is a chance. 254*78fe7221Sdduvall # replace tabs with spaces and check again. 255*78fe7221Sdduvall my $eline = $line; 256*78fe7221Sdduvall 1 while $eline =~ 257*78fe7221Sdduvall s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; 258*78fe7221Sdduvall if (length($eline) > 80) { 259*78fe7221Sdduvall err("line > 80 characters"); 260*78fe7221Sdduvall } 261*78fe7221Sdduvall } 262*78fe7221Sdduvall 263*78fe7221Sdduvall # allow spaces to be used to draw pictures in header comments. 264*78fe7221Sdduvall if (/[^ ] / && !/".* .*"/ && !$in_header_comment) { 265*78fe7221Sdduvall err("spaces instead of tabs"); 266*78fe7221Sdduvall } 267*78fe7221Sdduvall if ($tabs && /^ / && !/^ \*[ \t\/]/ && !/^ \*$/ && 268*78fe7221Sdduvall (!/^ \w/ || $in_class != 0)) { 269*78fe7221Sdduvall err("indent by spaces instead of tabs"); 270*78fe7221Sdduvall } 271*78fe7221Sdduvall if (!$in_comment && (/^(\t )* {1,3}\S/ || /^(\t )* {5,7}\S/) && 272*78fe7221Sdduvall !(/^\s*[-+|&\/?:=]/ || ($prev =~ /,\s*$/))) { 273*78fe7221Sdduvall err("indent not a multiple of 4"); 274*78fe7221Sdduvall } 275*78fe7221Sdduvall if (/\s$/) { 276*78fe7221Sdduvall err("space or tab at end of line"); 277*78fe7221Sdduvall } 278*78fe7221Sdduvallif (0) { 279*78fe7221Sdduvall if (/^[\t]+ [^ \t\*]/ || /^[\t]+ \S/ || /^[\t]+ \S/) { 280*78fe7221Sdduvall err("continuation line not indented by 4 spaces"); 281*78fe7221Sdduvall } 282*78fe7221Sdduvall} 283*78fe7221Sdduvall if (/\/\//) { 284*78fe7221Sdduvall $cpp_comment = 1; 285*78fe7221Sdduvall } 286*78fe7221Sdduvall if (!$cpp_comment && /[^ \t(\/]\/\*/ && !/\w\(\/\*.*\*\/\);/) { 287*78fe7221Sdduvall err("comment preceded by non-blank"); 288*78fe7221Sdduvall } 289*78fe7221Sdduvall if (/\t +\t/) { 290*78fe7221Sdduvall err("spaces between tabs"); 291*78fe7221Sdduvall } 292*78fe7221Sdduvall if (/ \t+ /) { 293*78fe7221Sdduvall err("tabs between spaces"); 294*78fe7221Sdduvall } 295*78fe7221Sdduvall 296*78fe7221Sdduvall if ($in_comment) { # still in comment 297*78fe7221Sdduvall $prev = $line; 298*78fe7221Sdduvall next line; 299*78fe7221Sdduvall } 300*78fe7221Sdduvall 301*78fe7221Sdduvall if (!$cpp_comment && ((/\/\*\S/ && !/\/\*\*/) || /\/\*\*\S/)) { 302*78fe7221Sdduvall err("missing blank after open comment"); 303*78fe7221Sdduvall } 304*78fe7221Sdduvall if (!$cpp_comment && /\S\*\//) { 305*78fe7221Sdduvall err("missing blank before close comment"); 306*78fe7221Sdduvall } 307*78fe7221Sdduvall # check for unterminated single line comments. 308*78fe7221Sdduvall if (/\S.*\/\*/ && !/\S.*\/\*.*\*\//) { 309*78fe7221Sdduvall err("unterminated single line comment"); 310*78fe7221Sdduvall } 311*78fe7221Sdduvall 312*78fe7221Sdduvall # delete any comments and check everything else. Be sure to leave 313*78fe7221Sdduvall # //-style comments intact, and if there are multiple comments on a 314*78fe7221Sdduvall # line, preserve whatever's in between. 315*78fe7221Sdduvall s/(?<!\/)\/\*.*?\*\///g; 316*78fe7221Sdduvall # Check for //-style comments only outside of block comments 317*78fe7221Sdduvall if (m{(//(?!$))} && substr($_, $+[0], 1) !~ /[ \t]/) { 318*78fe7221Sdduvall err("missing blank after start comment"); 319*78fe7221Sdduvall } 320*78fe7221Sdduvall s/\/\/.*$//; # C++ comments 321*78fe7221Sdduvall $cpp_comment = 0; 322*78fe7221Sdduvall 323*78fe7221Sdduvall # delete any trailing whitespace; we have already checked for that. 324*78fe7221Sdduvall s/\s*$//; 325*78fe7221Sdduvall 326*78fe7221Sdduvall # We don't style (yet) what's inside annotations, so just delete them. 327*78fe7221Sdduvall s/$annotations//; 328*78fe7221Sdduvall 329*78fe7221Sdduvall # following checks do not apply to text in comments. 330*78fe7221Sdduvall 331*78fe7221Sdduvall # if it looks like an operator at the end of the line, and it is 332*78fe7221Sdduvall # not really the end of a comment (...*/), and it is not really 333*78fe7221Sdduvall # a label (done:), and it is not a case label (case FOO:), 334*78fe7221Sdduvall # or we are not in a function definition (ANSI C style) and the 335*78fe7221Sdduvall # operator is a "," (to avoid hitting "int\nfoo(\n\tint i,\n\tint j)"), 336*78fe7221Sdduvall # or we are in a function and the operator is a 337*78fe7221Sdduvall # "*" (to avoid hitting on "char*\nfunc()"). 338*78fe7221Sdduvall if ((/[-+|&\/?:=]$/ && !/\*\/$/ && !/^\s*\w*:$/ && 339*78fe7221Sdduvall !/^\s\s*case\s\s*\w*:$/) || 340*78fe7221Sdduvall /,$/ || 341*78fe7221Sdduvall ($in_class && /\*$/)) { 342*78fe7221Sdduvall $expect_continuation = 1; 343*78fe7221Sdduvall if (!$in_continuation) { 344*78fe7221Sdduvall /^(\s*)\S/; 345*78fe7221Sdduvall $continuation_indent = $1; 346*78fe7221Sdduvall } 347*78fe7221Sdduvall } 348*78fe7221Sdduvall while (/($allops)/g) { 349*78fe7221Sdduvall my $z = substr($_, $-[1] - 1); 350*78fe7221Sdduvall if ($z !~ /\s\Q$1\E(?:\s|$)/) { 351*78fe7221Sdduvall my $m = $1; 352*78fe7221Sdduvall my $shift; 353*78fe7221Sdduvall # @+ is available only in the currently active 354*78fe7221Sdduvall # dynamic scope. Assign it to a new variable 355*78fe7221Sdduvall # to pass it into the if block. 356*78fe7221Sdduvall if ($z =~ /($generics)/ && 357*78fe7221Sdduvall ($shift = $+[1])) { 358*78fe7221Sdduvall pos $_ += $shift; 359*78fe7221Sdduvall next; 360*78fe7221Sdduvall } 361*78fe7221Sdduvall 362*78fe7221Sdduvall # These need to be in decreasing order of length 363*78fe7221Sdduvall # (violable as long as there's no ambiguity) 364*78fe7221Sdduvall my $nospace = "missing space around"; 365*78fe7221Sdduvall if ($m =~ $shiftassignmentops) { 366*78fe7221Sdduvall err("$nospace assignment operator"); 367*78fe7221Sdduvall } elsif ($m =~ $shiftops) { 368*78fe7221Sdduvall err("$nospace shift operator"); 369*78fe7221Sdduvall } elsif ($m =~ $relationalops) { 370*78fe7221Sdduvall err("$nospace relational operator"); 371*78fe7221Sdduvall } elsif ($m =~ $assignmentops) { 372*78fe7221Sdduvall err("$nospace assignment operator"); 373*78fe7221Sdduvall } 374*78fe7221Sdduvall } 375*78fe7221Sdduvall } 376*78fe7221Sdduvall if (/[,;]\S/ && !/\bfor \(;;\)/) { 377*78fe7221Sdduvall err("comma or semicolon followed by non-blank"); 378*78fe7221Sdduvall } 379*78fe7221Sdduvall # allow "for" statements to have empty "while" clauses 380*78fe7221Sdduvall if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) { 381*78fe7221Sdduvall err("comma or semicolon preceded by blank"); 382*78fe7221Sdduvall } 383*78fe7221Sdduvallif (0) { 384*78fe7221Sdduvall if (/^\s*(&&|\|\|)/) { 385*78fe7221Sdduvall err("improper boolean continuation"); 386*78fe7221Sdduvall } 387*78fe7221Sdduvall} 388*78fe7221Sdduvall if ($picky && /\S *(&&|\|\|)/ || /(&&|\|\|) *\S/) { 389*78fe7221Sdduvall err("more than one space around boolean operator"); 390*78fe7221Sdduvall } 391*78fe7221Sdduvall if (/\b$keywords\(/) { 392*78fe7221Sdduvall err("missing space between keyword and paren"); 393*78fe7221Sdduvall } 394*78fe7221Sdduvall if (/(\b$keywords\b.*){2,}/ && !/\bcase\b.*/) { # "case" excepted 395*78fe7221Sdduvall err("more than one keyword on line"); 396*78fe7221Sdduvall } 397*78fe7221Sdduvall if (/\b$keywords\s\s+\(/ && 398*78fe7221Sdduvall !/^#if\s+\(/) { 399*78fe7221Sdduvall err("extra space between keyword and paren"); 400*78fe7221Sdduvall } 401*78fe7221Sdduvall # try to detect "func (x)" but not "if (x)" or 402*78fe7221Sdduvall # "int (*func)();" 403*78fe7221Sdduvall if (/\w\s\(/) { 404*78fe7221Sdduvall my $save = $_; 405*78fe7221Sdduvall # strip off all keywords on the line 406*78fe7221Sdduvall s/\b$keywords\s\(/XXX(/g; 407*78fe7221Sdduvall #s/\b($typename|void)\s+\(+/XXX(/og; 408*78fe7221Sdduvall if (/\w\s\(/) { 409*78fe7221Sdduvall err("extra space between function name and left paren"); 410*78fe7221Sdduvall } 411*78fe7221Sdduvall $_ = $save; 412*78fe7221Sdduvall } 413*78fe7221Sdduvall if (/\(\s/) { 414*78fe7221Sdduvall err("whitespace after left paren"); 415*78fe7221Sdduvall } 416*78fe7221Sdduvall # allow "for" statements to have empty "continue" clauses 417*78fe7221Sdduvall if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) { 418*78fe7221Sdduvall err("whitespace before right paren"); 419*78fe7221Sdduvall } 420*78fe7221Sdduvall if (/^\s*\(void\)[^ ]/) { 421*78fe7221Sdduvall err("missing space after (void) cast"); 422*78fe7221Sdduvall } 423*78fe7221Sdduvall if (/\S{/ && !/{{/) { 424*78fe7221Sdduvall err("missing space before left brace"); 425*78fe7221Sdduvall } 426*78fe7221Sdduvall if ($in_class && /^\s+{/ && ($prev =~ /\)\s*$/)) { 427*78fe7221Sdduvall err("left brace starting a line"); 428*78fe7221Sdduvall } 429*78fe7221Sdduvall if (/}(else|while)/) { 430*78fe7221Sdduvall err("missing space after right brace"); 431*78fe7221Sdduvall } 432*78fe7221Sdduvall if (/}\s\s+(else|while)/) { 433*78fe7221Sdduvall err("extra space after right brace"); 434*78fe7221Sdduvall } 435*78fe7221Sdduvall if (/\b$typename\*/o) { 436*78fe7221Sdduvall err("missing space between type name and *"); 437*78fe7221Sdduvall } 438*78fe7221Sdduvall if ($heuristic) { 439*78fe7221Sdduvall # cannot check this everywhere due to "struct {\n...\n} foo;" 440*78fe7221Sdduvall if ($in_class && !$in_declaration && 441*78fe7221Sdduvall /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ && 442*78fe7221Sdduvall !/} (else|while)/ && !/}}/) { 443*78fe7221Sdduvall err("possible bad text following right brace"); 444*78fe7221Sdduvall } 445*78fe7221Sdduvall # cannot check this because sub-blocks in 446*78fe7221Sdduvall # the middle of code are ok 447*78fe7221Sdduvall if ($in_class && /^\s+{/) { 448*78fe7221Sdduvall err("possible left brace starting a line"); 449*78fe7221Sdduvall } 450*78fe7221Sdduvall } 451*78fe7221Sdduvall if (/^\s*else\W/) { 452*78fe7221Sdduvall if ($prev =~ /^\s*}$/) { 453*78fe7221Sdduvall my $str = "else and right brace should be on same line"; 454*78fe7221Sdduvall printf $fmt, $filename, $., $str, $prev; 455*78fe7221Sdduvall if ($verbose) { 456*78fe7221Sdduvall printf "%s\n", $line; 457*78fe7221Sdduvall } 458*78fe7221Sdduvall } 459*78fe7221Sdduvall } 460*78fe7221Sdduvall $prev = $line; 461*78fe7221Sdduvall} 462*78fe7221Sdduvall 463*78fe7221Sdduvallif ($picky && $prev eq "") { 464*78fe7221Sdduvall err("last line in file is blank"); 465*78fe7221Sdduvall} 466*78fe7221Sdduvall 467*78fe7221Sdduvall} 468