178fe7221Sdduvall#!/usr/bin/perl -w 278fe7221Sdduvall# 378fe7221Sdduvall# CDDL HEADER START 478fe7221Sdduvall# 578fe7221Sdduvall# The contents of this file are subject to the terms of the 678fe7221Sdduvall# Common Development and Distribution License (the "License"). 778fe7221Sdduvall# You may not use this file except in compliance with the License. 878fe7221Sdduvall# 978fe7221Sdduvall# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1078fe7221Sdduvall# or http://www.opensolaris.org/os/licensing. 1178fe7221Sdduvall# See the License for the specific language governing permissions 1278fe7221Sdduvall# and limitations under the License. 1378fe7221Sdduvall# 1478fe7221Sdduvall# When distributing Covered Code, include this CDDL HEADER in each 1578fe7221Sdduvall# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1678fe7221Sdduvall# If applicable, add the following below this CDDL HEADER, with the 1778fe7221Sdduvall# fields enclosed by brackets "[]" replaced with your own identifying 1878fe7221Sdduvall# information: Portions Copyright [yyyy] [name of copyright owner] 1978fe7221Sdduvall# 2078fe7221Sdduvall# CDDL HEADER END 2178fe7221Sdduvall# 2278fe7221Sdduvall 2378fe7221Sdduvall# 2478fe7221Sdduvall# ident "%Z%%M% %I% %E% SMI" 2578fe7221Sdduvall# 26*cdf0c1d5Smjnelson# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2778fe7221Sdduvall# Use is subject to license terms. 2878fe7221Sdduvall# 2978fe7221Sdduvall# jstyle - check for some common stylistic errors. 3078fe7221Sdduvall# 3178fe7221Sdduvall 3278fe7221Sdduvallrequire 5.006; 3378fe7221Sdduvalluse Getopt::Std; 3478fe7221Sdduvalluse strict; 3578fe7221Sdduvall 3678fe7221Sdduvallmy $usage = 3778fe7221Sdduvall"usage: jstyle [-c] [-h] [-p] [-t] [-v] [-C] file ... 3878fe7221Sdduvall -c check continuation line indenting 3978fe7221Sdduvall -h perform heuristic checks that are sometimes wrong 4078fe7221Sdduvall -p perform some of the more picky checks 4178fe7221Sdduvall -t insist on indenting by tabs 4278fe7221Sdduvall -v verbose 4378fe7221Sdduvall -C don't check anything in header block comments 4478fe7221Sdduvall"; 4578fe7221Sdduvall 4678fe7221Sdduvallmy %opts; 4778fe7221Sdduvall 4878fe7221Sdduvall# Keep -s, as it's been around for a while. It just doesn't do anything 4978fe7221Sdduvall# anymore. 5078fe7221Sdduvallif (!getopts("chpstvC", \%opts)) { 5178fe7221Sdduvall print $usage; 52*cdf0c1d5Smjnelson exit 2; 5378fe7221Sdduvall} 5478fe7221Sdduvall 5578fe7221Sdduvallmy $check_continuation = $opts{'c'}; 5678fe7221Sdduvallmy $heuristic = $opts{'h'}; 5778fe7221Sdduvallmy $picky = $opts{'p'}; 5878fe7221Sdduvallmy $tabs = $opts{'t'}; 5978fe7221Sdduvallmy $verbose = $opts{'v'}; 6078fe7221Sdduvallmy $ignore_hdr_comment = $opts{'C'}; 6178fe7221Sdduvall 6278fe7221Sdduvallmy ($filename, $line, $prev); 63*cdf0c1d5Smjnelsonmy $err_stat = 0; # Exit status 6478fe7221Sdduvall 6578fe7221Sdduvallmy $fmt; 6678fe7221Sdduvall 6778fe7221Sdduvallif ($verbose) { 6878fe7221Sdduvall $fmt = "%s: %d: %s\n%s\n"; 6978fe7221Sdduvall} else { 7078fe7221Sdduvall $fmt = "%s: %d: %s\n"; 7178fe7221Sdduvall} 7278fe7221Sdduvall 7378fe7221Sdduvall# Note, following must be in single quotes so that \s and \w work right. 7478fe7221Sdduvallmy $typename = '(int|char|boolean|byte|short|long|float|double)'; 7578fe7221Sdduvallmy $keywords = '(for|if|while|switch|return|catch|synchronized|throw|assert)'; 7678fe7221Sdduvall# See perlre(1) for the meaning of (??{ ... }) 7778fe7221Sdduvallmy $annotations = ""; $annotations = qr/@\w+\((?:(?>[^()]+)|(??{ $annotations }))*\)/; 7878fe7221Sdduvallmy $generics = ""; $generics = qr/<(([\s\w,.?[\]]| & )+|(??{ $generics }))*>/; 7978fe7221Sdduvallmy $relationalops = qr/>=|<=|<|>|!=|==/; 8078fe7221Sdduvallmy $shiftops = qr/<<<|>>>|<<|>>/; 8178fe7221Sdduvallmy $shiftassignmentops = qr/[<>]{2,3}=/; 8278fe7221Sdduvallmy $assignmentops = qr/[-+\/*|&^%]?=/; 8378fe7221Sdduvall# These need to be in decreasing order of length 8478fe7221Sdduvallmy $allops = qr/$shiftassignmentops|$shiftops|$relationalops|$assignmentops/; 8578fe7221Sdduvall 8678fe7221Sdduvallif ($#ARGV >= 0) { 8778fe7221Sdduvall foreach my $arg (@ARGV) { 8878fe7221Sdduvall if (!open(STDIN, $arg)) { 8978fe7221Sdduvall printf "%s: can not open\n", $arg; 9078fe7221Sdduvall } else { 9178fe7221Sdduvall &jstyle($arg); 9278fe7221Sdduvall close STDIN; 9378fe7221Sdduvall } 9478fe7221Sdduvall } 9578fe7221Sdduvall} else { 9678fe7221Sdduvall &jstyle("<stdin>"); 9778fe7221Sdduvall} 98*cdf0c1d5Smjnelsonexit $err_stat; 9978fe7221Sdduvall 10078fe7221Sdduvallsub err($) { 10178fe7221Sdduvall printf $fmt, $filename, $., $_[0], $line; 102*cdf0c1d5Smjnelson $err_stat = 1; 10378fe7221Sdduvall} 10478fe7221Sdduvall 10578fe7221Sdduvallsub jstyle($) { 10678fe7221Sdduvall 10778fe7221Sdduvallmy $in_comment = 0; 10878fe7221Sdduvallmy $in_header_comment = 0; 10978fe7221Sdduvallmy $in_continuation = 0; 11078fe7221Sdduvallmy $in_class = 0; 11178fe7221Sdduvallmy $in_declaration = 0; 11278fe7221Sdduvallmy $nextok = 0; 11378fe7221Sdduvallmy $nocheck = 0; 11478fe7221Sdduvallmy $expect_continuation = 0; 11578fe7221Sdduvallmy $continuation_indent; 11678fe7221Sdduvallmy $okmsg; 11778fe7221Sdduvallmy $comment_prefix; 11878fe7221Sdduvallmy $comment_done; 11978fe7221Sdduvallmy $cpp_comment; 12078fe7221Sdduvall 12178fe7221Sdduvall$filename = $_[0]; 12278fe7221Sdduvall 12378fe7221Sdduvallline: while (<STDIN>) { 12478fe7221Sdduvall s/\r?\n$//; # strip return and newline 12578fe7221Sdduvall 12678fe7221Sdduvall # save the original line, then remove all text from within 12778fe7221Sdduvall # double or single quotes, we do not want to check such text. 12878fe7221Sdduvall 12978fe7221Sdduvall $line = $_; 13078fe7221Sdduvall s/"[^"]*"/\"\"/g; 13178fe7221Sdduvall s/'.'/''/g; 13278fe7221Sdduvall 13378fe7221Sdduvall # an /* END JSTYLED */ comment ends a no-check block. 13478fe7221Sdduvall if ($nocheck) { 13578fe7221Sdduvall if (/\/\* *END *JSTYLED *\*\//) { 13678fe7221Sdduvall $nocheck = 0; 13778fe7221Sdduvall } else { 13878fe7221Sdduvall next line; 13978fe7221Sdduvall } 14078fe7221Sdduvall } 14178fe7221Sdduvall 14278fe7221Sdduvall # a /*JSTYLED*/ comment indicates that the next line is ok. 14378fe7221Sdduvall if ($nextok) { 14478fe7221Sdduvall if ($okmsg) { 14578fe7221Sdduvall err($okmsg); 14678fe7221Sdduvall } 14778fe7221Sdduvall $nextok = 0; 14878fe7221Sdduvall $okmsg = 0; 14978fe7221Sdduvall if (/\/\* *JSTYLED.*\*\//) { 15078fe7221Sdduvall /^.*\/\* *JSTYLED *(.*) *\*\/.*$/; 15178fe7221Sdduvall $okmsg = $1; 15278fe7221Sdduvall $nextok = 1; 15378fe7221Sdduvall } 15478fe7221Sdduvall $prev = $line; 15578fe7221Sdduvall next line; 15678fe7221Sdduvall } 15778fe7221Sdduvall 15878fe7221Sdduvall # remember whether we expect to be inside a continuation line. 15978fe7221Sdduvall $in_continuation = $expect_continuation; 16078fe7221Sdduvall 16178fe7221Sdduvall # check for proper continuation line. blank lines 16278fe7221Sdduvall # in the middle of the 16378fe7221Sdduvall # continuation do not count. 16478fe7221Sdduvall # XXX - only check within functions. 16578fe7221Sdduvall if ($check_continuation && $expect_continuation && $in_class && 16678fe7221Sdduvall !/^\s*$/) { 16778fe7221Sdduvall # continuation line must start with whitespace of 16878fe7221Sdduvall # previous line, plus either 4 spaces or a tab, but 16978fe7221Sdduvall # do not check lines that start with a string constant 17078fe7221Sdduvall # since they are often shifted to the left to make them 17178fe7221Sdduvall # fit on the line. 17278fe7221Sdduvall if (!/^$continuation_indent \S/ && 17378fe7221Sdduvall !/^$continuation_indent\t\S/ && !/^\s*"/) { 17478fe7221Sdduvall err("continuation line improperly indented"); 17578fe7221Sdduvall } 17678fe7221Sdduvall $expect_continuation = 0; 17778fe7221Sdduvall } 17878fe7221Sdduvall 17978fe7221Sdduvall # a /* BEGIN JSTYLED */ comment starts a no-check block. 18078fe7221Sdduvall if (/\/\* *BEGIN *JSTYLED *\*\//) { 18178fe7221Sdduvall $nocheck = 1; 18278fe7221Sdduvall } 18378fe7221Sdduvall 18478fe7221Sdduvall # a /*JSTYLED*/ comment indicates that the next line is ok. 18578fe7221Sdduvall if (/\/\* *JSTYLED.*\*\//) { 18678fe7221Sdduvall /^.*\/\* *JSTYLED *(.*) *\*\/.*$/; 18778fe7221Sdduvall $okmsg = $1; 18878fe7221Sdduvall $nextok = 1; 18978fe7221Sdduvall } 19078fe7221Sdduvall if (/\/\/ *JSTYLED/) { 19178fe7221Sdduvall /^.*\/\/ *JSTYLED *(.*)$/; 19278fe7221Sdduvall $okmsg = $1; 19378fe7221Sdduvall $nextok = 1; 19478fe7221Sdduvall } 19578fe7221Sdduvall 19678fe7221Sdduvall # is this the beginning or ending of a class? 19778fe7221Sdduvall if (/^(public\s+)*\w(class|interface)\s/) { 19878fe7221Sdduvall $in_class = 1; 19978fe7221Sdduvall $in_declaration = 1; 20078fe7221Sdduvall $prev = $line; 20178fe7221Sdduvall next line; 20278fe7221Sdduvall } 20378fe7221Sdduvall if (/^}\s*(\/\*.*\*\/\s*)*$/) { 20478fe7221Sdduvall $in_class = 0; 20578fe7221Sdduvall $prev = $line; 20678fe7221Sdduvall next line; 20778fe7221Sdduvall } 20878fe7221Sdduvall 20978fe7221Sdduvall if ($comment_done) { 21078fe7221Sdduvall $in_comment = 0; 21178fe7221Sdduvall $in_header_comment = 0; 21278fe7221Sdduvall $comment_done = 0; 21378fe7221Sdduvall } 21478fe7221Sdduvall # does this looks like the start of a block comment? 21578fe7221Sdduvall if (/^\s*\/\*/ && !/^\s*\/\*.*\*\//) { 21678fe7221Sdduvall if (/^\s*\/\*./ && !/^\s*\/\*\*$/) { 21778fe7221Sdduvall err("improper first line of block comment"); 21878fe7221Sdduvall } 21978fe7221Sdduvall if (!/^(\t| )*\/\*/) { 22078fe7221Sdduvall err("block comment not indented properly"); 22178fe7221Sdduvall } 22278fe7221Sdduvall $in_comment = 1; 22378fe7221Sdduvall /^(\s*)\//; 22478fe7221Sdduvall $comment_prefix = $1; 22578fe7221Sdduvall if ($comment_prefix eq "") { 22678fe7221Sdduvall $in_header_comment = 1; 22778fe7221Sdduvall } 22878fe7221Sdduvall $prev = $line; 22978fe7221Sdduvall next line; 23078fe7221Sdduvall } 23178fe7221Sdduvall # are we still in the block comment? 23278fe7221Sdduvall if ($in_comment) { 23378fe7221Sdduvall if (/^$comment_prefix \*\/$/) { 23478fe7221Sdduvall $comment_done = 1; 23578fe7221Sdduvall } elsif (/\*\//) { 23678fe7221Sdduvall $comment_done = 1; 23778fe7221Sdduvall err("improper block comment close") 23878fe7221Sdduvall unless ($ignore_hdr_comment && $in_header_comment); 23978fe7221Sdduvall } elsif (!/^$comment_prefix \*[ \t]/ && 24078fe7221Sdduvall !/^$comment_prefix \*$/) { 24178fe7221Sdduvall err("improper block comment") 24278fe7221Sdduvall unless ($ignore_hdr_comment && $in_header_comment); 24378fe7221Sdduvall } 24478fe7221Sdduvall } 24578fe7221Sdduvall 24678fe7221Sdduvall if ($in_header_comment && $ignore_hdr_comment) { 24778fe7221Sdduvall $prev = $line; 24878fe7221Sdduvall next line; 24978fe7221Sdduvall } 25078fe7221Sdduvall 25178fe7221Sdduvall # check for errors that might occur in comments and in code. 25278fe7221Sdduvall 25378fe7221Sdduvall # check length of line. 25478fe7221Sdduvall # first, a quick check to see if there is any chance of being too long. 25578fe7221Sdduvall if ($line =~ tr/\t/\t/ * 7 + length($line) > 80) { 25678fe7221Sdduvall # yes, there is a chance. 25778fe7221Sdduvall # replace tabs with spaces and check again. 25878fe7221Sdduvall my $eline = $line; 25978fe7221Sdduvall 1 while $eline =~ 26078fe7221Sdduvall s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; 26178fe7221Sdduvall if (length($eline) > 80) { 26278fe7221Sdduvall err("line > 80 characters"); 26378fe7221Sdduvall } 26478fe7221Sdduvall } 26578fe7221Sdduvall 266dd2b4cceSdduvall # Allow spaces to be used to draw pictures in header comments, but 267dd2b4cceSdduvall # disallow blocks of spaces almost everywhere else. In particular, 268dd2b4cceSdduvall # five spaces are also allowed at the end of a line's indentation 269dd2b4cceSdduvall # if the rest of the line belongs to a block comment. 270dd2b4cceSdduvall if (!$in_header_comment && 271dd2b4cceSdduvall /[^ ] / && 272dd2b4cceSdduvall !(/^\t* \*/ && !/^\t* \*.* /)) { 27378fe7221Sdduvall err("spaces instead of tabs"); 27478fe7221Sdduvall } 27578fe7221Sdduvall if ($tabs && /^ / && !/^ \*[ \t\/]/ && !/^ \*$/ && 27678fe7221Sdduvall (!/^ \w/ || $in_class != 0)) { 27778fe7221Sdduvall err("indent by spaces instead of tabs"); 27878fe7221Sdduvall } 27978fe7221Sdduvall if (!$in_comment && (/^(\t )* {1,3}\S/ || /^(\t )* {5,7}\S/) && 28078fe7221Sdduvall !(/^\s*[-+|&\/?:=]/ || ($prev =~ /,\s*$/))) { 28178fe7221Sdduvall err("indent not a multiple of 4"); 28278fe7221Sdduvall } 28378fe7221Sdduvall if (/\s$/) { 28478fe7221Sdduvall err("space or tab at end of line"); 28578fe7221Sdduvall } 28678fe7221Sdduvallif (0) { 28778fe7221Sdduvall if (/^[\t]+ [^ \t\*]/ || /^[\t]+ \S/ || /^[\t]+ \S/) { 28878fe7221Sdduvall err("continuation line not indented by 4 spaces"); 28978fe7221Sdduvall } 29078fe7221Sdduvall} 29178fe7221Sdduvall if (/\/\//) { 29278fe7221Sdduvall $cpp_comment = 1; 29378fe7221Sdduvall } 29478fe7221Sdduvall if (!$cpp_comment && /[^ \t(\/]\/\*/ && !/\w\(\/\*.*\*\/\);/) { 29578fe7221Sdduvall err("comment preceded by non-blank"); 29678fe7221Sdduvall } 29778fe7221Sdduvall if (/\t +\t/) { 29878fe7221Sdduvall err("spaces between tabs"); 29978fe7221Sdduvall } 30078fe7221Sdduvall if (/ \t+ /) { 30178fe7221Sdduvall err("tabs between spaces"); 30278fe7221Sdduvall } 30378fe7221Sdduvall 30478fe7221Sdduvall if ($in_comment) { # still in comment 30578fe7221Sdduvall $prev = $line; 30678fe7221Sdduvall next line; 30778fe7221Sdduvall } 30878fe7221Sdduvall 30978fe7221Sdduvall if (!$cpp_comment && ((/\/\*\S/ && !/\/\*\*/) || /\/\*\*\S/)) { 31078fe7221Sdduvall err("missing blank after open comment"); 31178fe7221Sdduvall } 31278fe7221Sdduvall if (!$cpp_comment && /\S\*\//) { 31378fe7221Sdduvall err("missing blank before close comment"); 31478fe7221Sdduvall } 31578fe7221Sdduvall # check for unterminated single line comments. 31678fe7221Sdduvall if (/\S.*\/\*/ && !/\S.*\/\*.*\*\//) { 31778fe7221Sdduvall err("unterminated single line comment"); 31878fe7221Sdduvall } 31978fe7221Sdduvall 32078fe7221Sdduvall # delete any comments and check everything else. Be sure to leave 32178fe7221Sdduvall # //-style comments intact, and if there are multiple comments on a 32278fe7221Sdduvall # line, preserve whatever's in between. 32378fe7221Sdduvall s/(?<!\/)\/\*.*?\*\///g; 32478fe7221Sdduvall # Check for //-style comments only outside of block comments 32578fe7221Sdduvall if (m{(//(?!$))} && substr($_, $+[0], 1) !~ /[ \t]/) { 32678fe7221Sdduvall err("missing blank after start comment"); 32778fe7221Sdduvall } 32878fe7221Sdduvall s/\/\/.*$//; # C++ comments 32978fe7221Sdduvall $cpp_comment = 0; 33078fe7221Sdduvall 33178fe7221Sdduvall # delete any trailing whitespace; we have already checked for that. 33278fe7221Sdduvall s/\s*$//; 33378fe7221Sdduvall 33478fe7221Sdduvall # We don't style (yet) what's inside annotations, so just delete them. 33578fe7221Sdduvall s/$annotations//; 33678fe7221Sdduvall 33778fe7221Sdduvall # following checks do not apply to text in comments. 33878fe7221Sdduvall 33978fe7221Sdduvall # if it looks like an operator at the end of the line, and it is 34078fe7221Sdduvall # not really the end of a comment (...*/), and it is not really 34178fe7221Sdduvall # a label (done:), and it is not a case label (case FOO:), 34278fe7221Sdduvall # or we are not in a function definition (ANSI C style) and the 34378fe7221Sdduvall # operator is a "," (to avoid hitting "int\nfoo(\n\tint i,\n\tint j)"), 34478fe7221Sdduvall # or we are in a function and the operator is a 34578fe7221Sdduvall # "*" (to avoid hitting on "char*\nfunc()"). 34678fe7221Sdduvall if ((/[-+|&\/?:=]$/ && !/\*\/$/ && !/^\s*\w*:$/ && 34778fe7221Sdduvall !/^\s\s*case\s\s*\w*:$/) || 34878fe7221Sdduvall /,$/ || 34978fe7221Sdduvall ($in_class && /\*$/)) { 35078fe7221Sdduvall $expect_continuation = 1; 35178fe7221Sdduvall if (!$in_continuation) { 35278fe7221Sdduvall /^(\s*)\S/; 35378fe7221Sdduvall $continuation_indent = $1; 35478fe7221Sdduvall } 35578fe7221Sdduvall } 35678fe7221Sdduvall while (/($allops)/g) { 35778fe7221Sdduvall my $z = substr($_, $-[1] - 1); 35878fe7221Sdduvall if ($z !~ /\s\Q$1\E(?:\s|$)/) { 35978fe7221Sdduvall my $m = $1; 36078fe7221Sdduvall my $shift; 36178fe7221Sdduvall # @+ is available only in the currently active 36278fe7221Sdduvall # dynamic scope. Assign it to a new variable 36378fe7221Sdduvall # to pass it into the if block. 36478fe7221Sdduvall if ($z =~ /($generics)/ && 36578fe7221Sdduvall ($shift = $+[1])) { 36678fe7221Sdduvall pos $_ += $shift; 36778fe7221Sdduvall next; 36878fe7221Sdduvall } 36978fe7221Sdduvall 37078fe7221Sdduvall # These need to be in decreasing order of length 37178fe7221Sdduvall # (violable as long as there's no ambiguity) 37278fe7221Sdduvall my $nospace = "missing space around"; 37378fe7221Sdduvall if ($m =~ $shiftassignmentops) { 37478fe7221Sdduvall err("$nospace assignment operator"); 37578fe7221Sdduvall } elsif ($m =~ $shiftops) { 37678fe7221Sdduvall err("$nospace shift operator"); 37778fe7221Sdduvall } elsif ($m =~ $relationalops) { 37878fe7221Sdduvall err("$nospace relational operator"); 37978fe7221Sdduvall } elsif ($m =~ $assignmentops) { 38078fe7221Sdduvall err("$nospace assignment operator"); 38178fe7221Sdduvall } 38278fe7221Sdduvall } 38378fe7221Sdduvall } 38478fe7221Sdduvall if (/[,;]\S/ && !/\bfor \(;;\)/) { 38578fe7221Sdduvall err("comma or semicolon followed by non-blank"); 38678fe7221Sdduvall } 38778fe7221Sdduvall # allow "for" statements to have empty "while" clauses 38878fe7221Sdduvall if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) { 38978fe7221Sdduvall err("comma or semicolon preceded by blank"); 39078fe7221Sdduvall } 39178fe7221Sdduvallif (0) { 39278fe7221Sdduvall if (/^\s*(&&|\|\|)/) { 39378fe7221Sdduvall err("improper boolean continuation"); 39478fe7221Sdduvall } 39578fe7221Sdduvall} 39678fe7221Sdduvall if ($picky && /\S *(&&|\|\|)/ || /(&&|\|\|) *\S/) { 39778fe7221Sdduvall err("more than one space around boolean operator"); 39878fe7221Sdduvall } 39978fe7221Sdduvall if (/\b$keywords\(/) { 40078fe7221Sdduvall err("missing space between keyword and paren"); 40178fe7221Sdduvall } 40278fe7221Sdduvall if (/(\b$keywords\b.*){2,}/ && !/\bcase\b.*/) { # "case" excepted 40378fe7221Sdduvall err("more than one keyword on line"); 40478fe7221Sdduvall } 40578fe7221Sdduvall if (/\b$keywords\s\s+\(/ && 40678fe7221Sdduvall !/^#if\s+\(/) { 40778fe7221Sdduvall err("extra space between keyword and paren"); 40878fe7221Sdduvall } 40978fe7221Sdduvall # try to detect "func (x)" but not "if (x)" or 41078fe7221Sdduvall # "int (*func)();" 41178fe7221Sdduvall if (/\w\s\(/) { 41278fe7221Sdduvall my $save = $_; 41378fe7221Sdduvall # strip off all keywords on the line 41478fe7221Sdduvall s/\b$keywords\s\(/XXX(/g; 41578fe7221Sdduvall #s/\b($typename|void)\s+\(+/XXX(/og; 41678fe7221Sdduvall if (/\w\s\(/) { 41778fe7221Sdduvall err("extra space between function name and left paren"); 41878fe7221Sdduvall } 41978fe7221Sdduvall $_ = $save; 42078fe7221Sdduvall } 42178fe7221Sdduvall if (/\(\s/) { 42278fe7221Sdduvall err("whitespace after left paren"); 42378fe7221Sdduvall } 42478fe7221Sdduvall # allow "for" statements to have empty "continue" clauses 42578fe7221Sdduvall if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) { 42678fe7221Sdduvall err("whitespace before right paren"); 42778fe7221Sdduvall } 42878fe7221Sdduvall if (/^\s*\(void\)[^ ]/) { 42978fe7221Sdduvall err("missing space after (void) cast"); 43078fe7221Sdduvall } 43178fe7221Sdduvall if (/\S{/ && !/{{/) { 43278fe7221Sdduvall err("missing space before left brace"); 43378fe7221Sdduvall } 43478fe7221Sdduvall if ($in_class && /^\s+{/ && ($prev =~ /\)\s*$/)) { 43578fe7221Sdduvall err("left brace starting a line"); 43678fe7221Sdduvall } 43778fe7221Sdduvall if (/}(else|while)/) { 43878fe7221Sdduvall err("missing space after right brace"); 43978fe7221Sdduvall } 44078fe7221Sdduvall if (/}\s\s+(else|while)/) { 44178fe7221Sdduvall err("extra space after right brace"); 44278fe7221Sdduvall } 44378fe7221Sdduvall if (/\b$typename\*/o) { 44478fe7221Sdduvall err("missing space between type name and *"); 44578fe7221Sdduvall } 44678fe7221Sdduvall if ($heuristic) { 44778fe7221Sdduvall # cannot check this everywhere due to "struct {\n...\n} foo;" 44878fe7221Sdduvall if ($in_class && !$in_declaration && 44978fe7221Sdduvall /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ && 45078fe7221Sdduvall !/} (else|while)/ && !/}}/) { 45178fe7221Sdduvall err("possible bad text following right brace"); 45278fe7221Sdduvall } 45378fe7221Sdduvall # cannot check this because sub-blocks in 45478fe7221Sdduvall # the middle of code are ok 45578fe7221Sdduvall if ($in_class && /^\s+{/) { 45678fe7221Sdduvall err("possible left brace starting a line"); 45778fe7221Sdduvall } 45878fe7221Sdduvall } 45978fe7221Sdduvall if (/^\s*else\W/) { 46078fe7221Sdduvall if ($prev =~ /^\s*}$/) { 46178fe7221Sdduvall my $str = "else and right brace should be on same line"; 46278fe7221Sdduvall printf $fmt, $filename, $., $str, $prev; 46378fe7221Sdduvall if ($verbose) { 46478fe7221Sdduvall printf "%s\n", $line; 46578fe7221Sdduvall } 46678fe7221Sdduvall } 46778fe7221Sdduvall } 46878fe7221Sdduvall $prev = $line; 46978fe7221Sdduvall} 47078fe7221Sdduvall 47178fe7221Sdduvallif ($picky && $prev eq "") { 47278fe7221Sdduvall err("last line in file is blank"); 47378fe7221Sdduvall} 47478fe7221Sdduvall 47578fe7221Sdduvall} 476