xref: /aoo4110/main/xmerge/workben/jstyle.pl (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski#!/bin/sh -- # This comment tells perl not to loop!
2*b1cdbd2cSJim Jagielski#
3*b1cdbd2cSJim Jagielski#**************************************************************
4*b1cdbd2cSJim Jagielski#
5*b1cdbd2cSJim Jagielski#  Licensed to the Apache Software Foundation (ASF) under one
6*b1cdbd2cSJim Jagielski#  or more contributor license agreements.  See the NOTICE file
7*b1cdbd2cSJim Jagielski#  distributed with this work for additional information
8*b1cdbd2cSJim Jagielski#  regarding copyright ownership.  The ASF licenses this file
9*b1cdbd2cSJim Jagielski#  to you under the Apache License, Version 2.0 (the
10*b1cdbd2cSJim Jagielski#  "License"); you may not use this file except in compliance
11*b1cdbd2cSJim Jagielski#  with the License.  You may obtain a copy of the License at
12*b1cdbd2cSJim Jagielski#
13*b1cdbd2cSJim Jagielski#    http://www.apache.org/licenses/LICENSE-2.0
14*b1cdbd2cSJim Jagielski#
15*b1cdbd2cSJim Jagielski#  Unless required by applicable law or agreed to in writing,
16*b1cdbd2cSJim Jagielski#  software distributed under the License is distributed on an
17*b1cdbd2cSJim Jagielski#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18*b1cdbd2cSJim Jagielski#  KIND, either express or implied.  See the License for the
19*b1cdbd2cSJim Jagielski#  specific language governing permissions and limitations
20*b1cdbd2cSJim Jagielski#  under the License.
21*b1cdbd2cSJim Jagielski#
22*b1cdbd2cSJim Jagielski#**************************************************************
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski**
25*b1cdbd2cSJim Jagielski
26*b1cdbd2cSJim Jagielski
27*b1cdbd2cSJim Jagielskieval 'exec perl -S $0 "$@"'
28*b1cdbd2cSJim Jagielskiif 0;
29*b1cdbd2cSJim Jagielski#
30*b1cdbd2cSJim Jagielski# @(#)jstyle 1.2 98/01/08
31*b1cdbd2cSJim Jagielski#
32*b1cdbd2cSJim Jagielski# jstyle - check for some common stylistic errors.
33*b1cdbd2cSJim Jagielski#
34*b1cdbd2cSJim Jagielski#	jstyle is a sort of "lint" for Java coding style.
35*b1cdbd2cSJim Jagielski#
36*b1cdbd2cSJim Jagielski#	There's a lot this can't check for, like proper
37*b1cdbd2cSJim Jagielski#	indentation of continuation lines.  There's also
38*b1cdbd2cSJim Jagielski#	a lot more this could check for.
39*b1cdbd2cSJim Jagielski#
40*b1cdbd2cSJim Jagielski#	A note to the non perl literate:
41*b1cdbd2cSJim Jagielski#
42*b1cdbd2cSJim Jagielski#		perl regular expressions are pretty much like egrep
43*b1cdbd2cSJim Jagielski#		regular expressions, with the following special symbols
44*b1cdbd2cSJim Jagielski#
45*b1cdbd2cSJim Jagielski#		\s	any space character
46*b1cdbd2cSJim Jagielski#		\S	any non-space character
47*b1cdbd2cSJim Jagielski#		\w	any "word" character [a-zA-Z0-9_]
48*b1cdbd2cSJim Jagielski#		\W	any non-word character
49*b1cdbd2cSJim Jagielski#		\d	a digit [0-9]
50*b1cdbd2cSJim Jagielski#		\D	a non-digit
51*b1cdbd2cSJim Jagielski#		\b	word boundary (between \w and \W)
52*b1cdbd2cSJim Jagielski#		\B	non-word boundary
53*b1cdbd2cSJim Jagielski#
54*b1cdbd2cSJim Jagielski#require "getopts.pl";
55*b1cdbd2cSJim Jagielski# XXX - because some versions of perl can not find the lib directory,
56*b1cdbd2cSJim Jagielski# we just include this here.
57*b1cdbd2cSJim Jagielski;# getopts.pl - a better getopt.pl
58*b1cdbd2cSJim Jagielski
59*b1cdbd2cSJim Jagielski;# Usage:
60*b1cdbd2cSJim Jagielski;#      do Getopts("a:bc");  # -a takes arg. -b & -c not. Sets opt_* as a
61*b1cdbd2cSJim Jagielski;#                           #  side effect.
62*b1cdbd2cSJim Jagielski
63*b1cdbd2cSJim Jagielskisub Getopts {
64*b1cdbd2cSJim Jagielski    local($argumentative) = @_;
65*b1cdbd2cSJim Jagielski    local(@args,$_,$first,$rest);
66*b1cdbd2cSJim Jagielski    local($[) = 0;
67*b1cdbd2cSJim Jagielski    local($errs) = 0;
68*b1cdbd2cSJim Jagielski
69*b1cdbd2cSJim Jagielski    @args = split( / */, $argumentative );
70*b1cdbd2cSJim Jagielski    while(($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
71*b1cdbd2cSJim Jagielski	($first,$rest) = ($1,$2);
72*b1cdbd2cSJim Jagielski	$pos = index($argumentative,$first);
73*b1cdbd2cSJim Jagielski	if($pos >= $[) {
74*b1cdbd2cSJim Jagielski	    if($args[$pos+1] eq ":") {
75*b1cdbd2cSJim Jagielski		shift(@ARGV);
76*b1cdbd2cSJim Jagielski		if($rest eq "") {
77*b1cdbd2cSJim Jagielski		    $rest = shift(@ARGV);
78*b1cdbd2cSJim Jagielski		}
79*b1cdbd2cSJim Jagielski		eval "\$opt_$first = \$rest;";
80*b1cdbd2cSJim Jagielski	    }
81*b1cdbd2cSJim Jagielski	    else {
82*b1cdbd2cSJim Jagielski		eval "\$opt_$first = 1";
83*b1cdbd2cSJim Jagielski		if($rest eq "") {
84*b1cdbd2cSJim Jagielski		    shift(@ARGV);
85*b1cdbd2cSJim Jagielski		}
86*b1cdbd2cSJim Jagielski		else {
87*b1cdbd2cSJim Jagielski		    $ARGV[0] = "-$rest";
88*b1cdbd2cSJim Jagielski		}
89*b1cdbd2cSJim Jagielski	    }
90*b1cdbd2cSJim Jagielski	}
91*b1cdbd2cSJim Jagielski	else {
92*b1cdbd2cSJim Jagielski	    print STDERR "Unknown option: $first\n";
93*b1cdbd2cSJim Jagielski	    ++$errs;
94*b1cdbd2cSJim Jagielski	    if($rest ne "") {
95*b1cdbd2cSJim Jagielski		$ARGV[0] = "-$rest";
96*b1cdbd2cSJim Jagielski	    }
97*b1cdbd2cSJim Jagielski	    else {
98*b1cdbd2cSJim Jagielski		shift(@ARGV);
99*b1cdbd2cSJim Jagielski	    }
100*b1cdbd2cSJim Jagielski	}
101*b1cdbd2cSJim Jagielski    }
102*b1cdbd2cSJim Jagielski    $errs == 0;
103*b1cdbd2cSJim Jagielski}
104*b1cdbd2cSJim Jagielski
105*b1cdbd2cSJim Jagielski1;
106*b1cdbd2cSJim Jagielski# end of getopts.pl
107*b1cdbd2cSJim Jagielski
108*b1cdbd2cSJim Jagielski$usage =
109*b1cdbd2cSJim Jagielski"usage: jstyle [-c] [-h] [-p] [-s] [-t] [-v] [-C] file ...
110*b1cdbd2cSJim Jagielski	-c	check continuation line indenting
111*b1cdbd2cSJim Jagielski	-h	perform heuristic checks that are sometimes wrong
112*b1cdbd2cSJim Jagielski	-p	perform some of the more picky checks
113*b1cdbd2cSJim Jagielski	-s	check for spaces vs. tabs
114*b1cdbd2cSJim Jagielski	-t	insist on indenting by tabs
115*b1cdbd2cSJim Jagielski	-v	verbose
116*b1cdbd2cSJim Jagielski	-C	don't check anything in header block comments
117*b1cdbd2cSJim Jagielski	-S	print out overall statistics
118*b1cdbd2cSJim Jagielski";
119*b1cdbd2cSJim Jagielski
120*b1cdbd2cSJim Jagielskiif (!&Getopts("chpstvCS")) {
121*b1cdbd2cSJim Jagielski	print $usage;
122*b1cdbd2cSJim Jagielski	exit 1;
123*b1cdbd2cSJim Jagielski}
124*b1cdbd2cSJim Jagielski
125*b1cdbd2cSJim Jagielski$check_continuation = $opt_c;
126*b1cdbd2cSJim Jagielski$heuristic = $opt_h;
127*b1cdbd2cSJim Jagielski$picky = $opt_p;
128*b1cdbd2cSJim Jagielski$spaces = $opt_s;
129*b1cdbd2cSJim Jagielski$tabs = $opt_t;
130*b1cdbd2cSJim Jagielski$verbose = $opt_v;
131*b1cdbd2cSJim Jagielski$ignore_hdr_comment = $opt_C;
132*b1cdbd2cSJim Jagielski$statistics = $opt_S;
133*b1cdbd2cSJim Jagielski
134*b1cdbd2cSJim Jagielskiif ($verbose) {
135*b1cdbd2cSJim Jagielski	$fmt = "%s: %d: %s\n%s\n";
136*b1cdbd2cSJim Jagielski} else {
137*b1cdbd2cSJim Jagielski	$fmt = "%s: %d: %s\n";
138*b1cdbd2cSJim Jagielski}
139*b1cdbd2cSJim Jagielski
140*b1cdbd2cSJim Jagielski# Note, following must be in single quotes so that \s and \w work right.
141*b1cdbd2cSJim Jagielski$typename = '(int|char|boolean|byte|short|long|float|double)';
142*b1cdbd2cSJim Jagielski
143*b1cdbd2cSJim Jagielskiif ($#ARGV >= 0) {
144*b1cdbd2cSJim Jagielski	foreach $arg (@ARGV) {
145*b1cdbd2cSJim Jagielski		if (!open(STDIN, $arg)) {
146*b1cdbd2cSJim Jagielski			printf "%s: can not open\n", $arg;
147*b1cdbd2cSJim Jagielski		} else {
148*b1cdbd2cSJim Jagielski			&jstyle($arg);
149*b1cdbd2cSJim Jagielski			close STDIN;
150*b1cdbd2cSJim Jagielski		}
151*b1cdbd2cSJim Jagielski	}
152*b1cdbd2cSJim Jagielski} else {
153*b1cdbd2cSJim Jagielski	&jstyle("<stdin>");
154*b1cdbd2cSJim Jagielski}
155*b1cdbd2cSJim Jagielski
156*b1cdbd2cSJim Jagielskiif ($statistics != 0) {
157*b1cdbd2cSJim Jagielski	foreach $key (sort(keys %errcount)) {
158*b1cdbd2cSJim Jagielski		printf "%6d %s\n", $errcount{$key}, $key;
159*b1cdbd2cSJim Jagielski	}
160*b1cdbd2cSJim Jagielski	printf " -----\n";
161*b1cdbd2cSJim Jagielski	printf "%6d Total warnings\n", $tot_errcount;
162*b1cdbd2cSJim Jagielski	printf "%6d Lines of code\n", $totlines;
163*b1cdbd2cSJim Jagielski}
164*b1cdbd2cSJim Jagielski
165*b1cdbd2cSJim Jagielskisub err {
166*b1cdbd2cSJim Jagielski	if ($statistics == 0) {
167*b1cdbd2cSJim Jagielski		printf $fmt, $filename, $., $_[0], $line;
168*b1cdbd2cSJim Jagielski	} else {
169*b1cdbd2cSJim Jagielski		$msg = $_[0];
170*b1cdbd2cSJim Jagielski		$msg =~ s/ \([0-9][0-9]*\)$//;
171*b1cdbd2cSJim Jagielski		$errcount{$msg} += 1;
172*b1cdbd2cSJim Jagielski		$tot_errcount += 1;
173*b1cdbd2cSJim Jagielski	}
174*b1cdbd2cSJim Jagielski}
175*b1cdbd2cSJim Jagielski
176*b1cdbd2cSJim Jagielskisub jstyle {
177*b1cdbd2cSJim Jagielski
178*b1cdbd2cSJim Jagielski$in_comment = 0;
179*b1cdbd2cSJim Jagielski$in_header_comment = 0;
180*b1cdbd2cSJim Jagielski$in_continuation = 0;
181*b1cdbd2cSJim Jagielski$in_class = 0;
182*b1cdbd2cSJim Jagielski$in_declaration = 0;
183*b1cdbd2cSJim Jagielski$note_level = 0;
184*b1cdbd2cSJim Jagielski$nextok = 0;
185*b1cdbd2cSJim Jagielski$nocheck = 0;
186*b1cdbd2cSJim Jagielski$expect_continuation = 0;
187*b1cdbd2cSJim Jagielski$prev = '';
188*b1cdbd2cSJim Jagielski
189*b1cdbd2cSJim Jagielski$filename = $_[0];
190*b1cdbd2cSJim Jagielski
191*b1cdbd2cSJim Jagielskiline: while (<STDIN>) {
192*b1cdbd2cSJim Jagielski	++$totlines;
193*b1cdbd2cSJim Jagielski	s/\r?\n$//;	# strip return and newline
194*b1cdbd2cSJim Jagielski
195*b1cdbd2cSJim Jagielski	# save the original line, then remove all text from within
196*b1cdbd2cSJim Jagielski	# double or single quotes, we do not want to check such text.
197*b1cdbd2cSJim Jagielski
198*b1cdbd2cSJim Jagielski	$line = $_;
199*b1cdbd2cSJim Jagielski	s/"[^"]*"/\"\"/g;
200*b1cdbd2cSJim Jagielski	s/'.'/''/g;
201*b1cdbd2cSJim Jagielski
202*b1cdbd2cSJim Jagielski	# an /* END JSTYLED */ comment ends a no-check block.
203*b1cdbd2cSJim Jagielski	if ($nocheck) {
204*b1cdbd2cSJim Jagielski		if (/\/\* *END *JSTYLED *\*\//) {
205*b1cdbd2cSJim Jagielski			$nocheck = 0;
206*b1cdbd2cSJim Jagielski		} else {
207*b1cdbd2cSJim Jagielski			next line;
208*b1cdbd2cSJim Jagielski		}
209*b1cdbd2cSJim Jagielski	}
210*b1cdbd2cSJim Jagielski
211*b1cdbd2cSJim Jagielski	# a /*JSTYLED*/ comment indicates that the next line is ok.
212*b1cdbd2cSJim Jagielski	if ($nextok) {
213*b1cdbd2cSJim Jagielski		if ($okmsg) {
214*b1cdbd2cSJim Jagielski			do err($okmsg);
215*b1cdbd2cSJim Jagielski		}
216*b1cdbd2cSJim Jagielski		$nextok = 0;
217*b1cdbd2cSJim Jagielski		$okmsg = 0;
218*b1cdbd2cSJim Jagielski		if (/\/\* *JSTYLED.*\*\//) {
219*b1cdbd2cSJim Jagielski			/^.*\/\* *JSTYLED *(.*) *\*\/.*$/;
220*b1cdbd2cSJim Jagielski			$okmsg = $1;
221*b1cdbd2cSJim Jagielski			$nextok = 1;
222*b1cdbd2cSJim Jagielski		}
223*b1cdbd2cSJim Jagielski		$prev = $line;
224*b1cdbd2cSJim Jagielski		next line;
225*b1cdbd2cSJim Jagielski	}
226*b1cdbd2cSJim Jagielski
227*b1cdbd2cSJim Jagielski	# check length of line.
228*b1cdbd2cSJim Jagielski	# first, a quick check to see if there is any chance of being too long.
229*b1cdbd2cSJim Jagielski	if ($line =~ tr/\t/\t/ * 7 + length($line) > 100) {
230*b1cdbd2cSJim Jagielski		# yes, there is a chance.
231*b1cdbd2cSJim Jagielski		# replace tabs with spaces and check again.
232*b1cdbd2cSJim Jagielski		$eline = $line;
233*b1cdbd2cSJim Jagielski		1 while $eline =~
234*b1cdbd2cSJim Jagielski		    s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
235*b1cdbd2cSJim Jagielski		$l = length($eline);
236*b1cdbd2cSJim Jagielski		if (length($eline) > 100) {
237*b1cdbd2cSJim Jagielski			do err("line > 100 characters ($l)");
238*b1cdbd2cSJim Jagielski		}
239*b1cdbd2cSJim Jagielski	}
240*b1cdbd2cSJim Jagielski#	this is the fastest way to check line length,
241*b1cdbd2cSJim Jagielski#	but it doesnt work with perl 3.0.
242*b1cdbd2cSJim Jagielski#	if ($line =~ tr/\t/\t/ * 7 + length($line) > 80) {
243*b1cdbd2cSJim Jagielski#		$pos = $oldp = $p = 0;
244*b1cdbd2cSJim Jagielski#		while (($p = index($line, "\t", $p)) >= 0) {
245*b1cdbd2cSJim Jagielski#			$pos = ($pos + $p - $oldp + 8) & ~7;
246*b1cdbd2cSJim Jagielski#			$oldp = ++$p;
247*b1cdbd2cSJim Jagielski#		}
248*b1cdbd2cSJim Jagielski#		$pos += length($line) - $oldp;
249*b1cdbd2cSJim Jagielski#		if ($pos > 80) {
250*b1cdbd2cSJim Jagielski#			do err("line > 80 characters");
251*b1cdbd2cSJim Jagielski#		}
252*b1cdbd2cSJim Jagielski#	}
253*b1cdbd2cSJim Jagielski
254*b1cdbd2cSJim Jagielski	# remember whether we expect to be inside a continuation line.
255*b1cdbd2cSJim Jagielski	$in_continuation = $expect_continuation;
256*b1cdbd2cSJim Jagielski
257*b1cdbd2cSJim Jagielski	# check for proper continuation line.  blank lines
258*b1cdbd2cSJim Jagielski	# in the middle of the
259*b1cdbd2cSJim Jagielski	# continuation do not count.
260*b1cdbd2cSJim Jagielski	# XXX - only check within functions.
261*b1cdbd2cSJim Jagielski	if ($check_continuation && $expect_continuation && $in_class &&
262*b1cdbd2cSJim Jagielski	    !/^\s*$/) {
263*b1cdbd2cSJim Jagielski		# continuation line must start with whitespace of
264*b1cdbd2cSJim Jagielski		# previous line, plus either 4 spaces or a tab, but
265*b1cdbd2cSJim Jagielski		# do not check lines that start with a string constant
266*b1cdbd2cSJim Jagielski		# since they are often shifted to the left to make them
267*b1cdbd2cSJim Jagielski		# fit on the line.
268*b1cdbd2cSJim Jagielski		if (!/^$continuation_indent    \S/ &&
269*b1cdbd2cSJim Jagielski		    !/^$continuation_indent\t\S/ && !/^\s*"/) {
270*b1cdbd2cSJim Jagielski			do err("continuation line improperly indented");
271*b1cdbd2cSJim Jagielski		}
272*b1cdbd2cSJim Jagielski		$expect_continuation = 0;
273*b1cdbd2cSJim Jagielski	}
274*b1cdbd2cSJim Jagielski
275*b1cdbd2cSJim Jagielski	# a /* BEGIN JSTYLED */ comment starts a no-check block.
276*b1cdbd2cSJim Jagielski	if (/\/\* *BEGIN *JSTYLED *\*\//) {
277*b1cdbd2cSJim Jagielski		$nocheck = 1;
278*b1cdbd2cSJim Jagielski	}
279*b1cdbd2cSJim Jagielski
280*b1cdbd2cSJim Jagielski	# a /*JSTYLED*/ comment indicates that the next line is ok.
281*b1cdbd2cSJim Jagielski	if (/\/\* *JSTYLED.*\*\//) {
282*b1cdbd2cSJim Jagielski		/^.*\/\* *JSTYLED *(.*) *\*\/.*$/;
283*b1cdbd2cSJim Jagielski		$okmsg = $1;
284*b1cdbd2cSJim Jagielski		$nextok = 1;
285*b1cdbd2cSJim Jagielski	}
286*b1cdbd2cSJim Jagielski	if (/\/\/ *JSTYLED/) {
287*b1cdbd2cSJim Jagielski		/^.*\/\/ *JSTYLED *(.*)$/;
288*b1cdbd2cSJim Jagielski		$okmsg = $1;
289*b1cdbd2cSJim Jagielski		$nextok = 1;
290*b1cdbd2cSJim Jagielski	}
291*b1cdbd2cSJim Jagielski
292*b1cdbd2cSJim Jagielski	# is this the beginning or ending of a class?
293*b1cdbd2cSJim Jagielski	if (/^(public\s+)*\w(class|interface)\s/) {
294*b1cdbd2cSJim Jagielski		$in_class = 1;
295*b1cdbd2cSJim Jagielski		$in_declaration = 1;
296*b1cdbd2cSJim Jagielski		$prev = $line;
297*b1cdbd2cSJim Jagielski		next line;
298*b1cdbd2cSJim Jagielski	}
299*b1cdbd2cSJim Jagielski	if (/^}\s*(\/\*.*\*\/\s*)*$/) {
300*b1cdbd2cSJim Jagielski		$in_class = 0;
301*b1cdbd2cSJim Jagielski		$prev = $line;
302*b1cdbd2cSJim Jagielski		next line;
303*b1cdbd2cSJim Jagielski	}
304*b1cdbd2cSJim Jagielski
305*b1cdbd2cSJim Jagielski	if (!$spaces) {
306*b1cdbd2cSJim Jagielski		# strip trailing spaces
307*b1cdbd2cSJim Jagielski		s/\s*$//;
308*b1cdbd2cSJim Jagielski	}
309*b1cdbd2cSJim Jagielski
310*b1cdbd2cSJim Jagielski	# does this looks like the start of a block comment?
311*b1cdbd2cSJim Jagielski	if (/^\s*\/\*(\*|)$/) {
312*b1cdbd2cSJim Jagielski		if (!/^(\t|    )*\/\*(\*|)$/) {
313*b1cdbd2cSJim Jagielski			do err("block comment not indented properly");
314*b1cdbd2cSJim Jagielski		}
315*b1cdbd2cSJim Jagielski		$in_comment = 1;
316*b1cdbd2cSJim Jagielski		s/\/\*(\*|)/ /;
317*b1cdbd2cSJim Jagielski		$comment_prefix = $_;
318*b1cdbd2cSJim Jagielski		if ($comment_prefix eq " ") {
319*b1cdbd2cSJim Jagielski			$in_header_comment = 1;
320*b1cdbd2cSJim Jagielski		}
321*b1cdbd2cSJim Jagielski		$prev = $line;
322*b1cdbd2cSJim Jagielski		next line;
323*b1cdbd2cSJim Jagielski	}
324*b1cdbd2cSJim Jagielski	if (/^\s*\/\*./ && !/^\s*\/\*\*$/ && !/^\s*\/\*.*\*\//) {
325*b1cdbd2cSJim Jagielski		do err("improper first line of block comment");
326*b1cdbd2cSJim Jagielski		# it's a bad one, but it still is one.
327*b1cdbd2cSJim Jagielski		# avoid ripple effect of not recognizing this.
328*b1cdbd2cSJim Jagielski		if (!/^(\t|    )*\/\*(\*|)/) {
329*b1cdbd2cSJim Jagielski			do err("block comment not indented properly");
330*b1cdbd2cSJim Jagielski		}
331*b1cdbd2cSJim Jagielski		$in_comment = 1;
332*b1cdbd2cSJim Jagielski		s/\/\*.*/ /;
333*b1cdbd2cSJim Jagielski		$comment_prefix = $_;
334*b1cdbd2cSJim Jagielski		if ($comment_prefix eq " ") {
335*b1cdbd2cSJim Jagielski			$in_header_comment = 1;
336*b1cdbd2cSJim Jagielski		}
337*b1cdbd2cSJim Jagielski		$prev = $line;
338*b1cdbd2cSJim Jagielski		next line;
339*b1cdbd2cSJim Jagielski	}
340*b1cdbd2cSJim Jagielski	# are we still in the block comment?
341*b1cdbd2cSJim Jagielski	if ($in_comment && !/^$comment_prefix\*/) {
342*b1cdbd2cSJim Jagielski		# assume out of comment
343*b1cdbd2cSJim Jagielski		$in_comment = 0;
344*b1cdbd2cSJim Jagielski		$in_header_comment = 0;
345*b1cdbd2cSJim Jagielski	}
346*b1cdbd2cSJim Jagielski
347*b1cdbd2cSJim Jagielski	if ($in_header_comment && $ignore_hdr_comment) {
348*b1cdbd2cSJim Jagielski		$prev = $line;
349*b1cdbd2cSJim Jagielski		next line;
350*b1cdbd2cSJim Jagielski	}
351*b1cdbd2cSJim Jagielski
352*b1cdbd2cSJim Jagielski	# check for errors that might occur in comments and in code.
353*b1cdbd2cSJim Jagielski
354*b1cdbd2cSJim Jagielski	# allow spaces to be used to draw pictures in header comments.
355*b1cdbd2cSJim Jagielski	if ($spaces && /[^ ]     / && !/".*     .*"/ && !$in_header_comment) {
356*b1cdbd2cSJim Jagielski		do err("spaces instead of tabs");
357*b1cdbd2cSJim Jagielski	}
358*b1cdbd2cSJim Jagielski	if ($tabs && /^ / && !/^ \*[ \t\/]/ && !/^ \*$/ &&
359*b1cdbd2cSJim Jagielski	    (!/^    \w/ || $in_class != 0)) {
360*b1cdbd2cSJim Jagielski		do err("indent by spaces instead of tabs");
361*b1cdbd2cSJim Jagielski	}
362*b1cdbd2cSJim Jagielski	if (!$in_comment && (/^(\t    )* {1,3}\S/ || /^(\t    )* {5,7}\S/) &&
363*b1cdbd2cSJim Jagielski	    !(/^\s*[-+|&\/?:=]/ || ($prev =~ /,\s*$/))) {
364*b1cdbd2cSJim Jagielski		do err("indent not a multiple of 4");
365*b1cdbd2cSJim Jagielski	}
366*b1cdbd2cSJim Jagielski	if ($spaces && /\s$/) {
367*b1cdbd2cSJim Jagielski		do err("space or tab at end of line");
368*b1cdbd2cSJim Jagielski	}
369*b1cdbd2cSJim Jagielskiif (0) {
370*b1cdbd2cSJim Jagielski	if (/^[\t]+ [^ \t\*]/ || /^[\t]+  \S/ || /^[\t]+   \S/) {
371*b1cdbd2cSJim Jagielski		do err("continuation line not indented by 4 spaces");
372*b1cdbd2cSJim Jagielski	}
373*b1cdbd2cSJim Jagielski}
374*b1cdbd2cSJim Jagielski	if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) {
375*b1cdbd2cSJim Jagielski		do err("comment preceded by non-blank");
376*b1cdbd2cSJim Jagielski	}
377*b1cdbd2cSJim Jagielski	if ($spaces && /\t[ ]+\t/) {
378*b1cdbd2cSJim Jagielski		do err("spaces between tabs");
379*b1cdbd2cSJim Jagielski	}
380*b1cdbd2cSJim Jagielski	if ($spaces && / [\t]+ /) {
381*b1cdbd2cSJim Jagielski		do err("tabs between spaces");
382*b1cdbd2cSJim Jagielski	}
383*b1cdbd2cSJim Jagielski
384*b1cdbd2cSJim Jagielski	if ($in_comment) {	# still in comment
385*b1cdbd2cSJim Jagielski		$prev = $line;
386*b1cdbd2cSJim Jagielski		next line;
387*b1cdbd2cSJim Jagielski	}
388*b1cdbd2cSJim Jagielski
389*b1cdbd2cSJim Jagielski	if ((/\/\*\S/ && !/\/\*\*/) || /\/\*\*\S/) {
390*b1cdbd2cSJim Jagielski		do err("missing blank after open comment");
391*b1cdbd2cSJim Jagielski	}
392*b1cdbd2cSJim Jagielski	if (/\S\*\//) {
393*b1cdbd2cSJim Jagielski		do err("missing blank before close comment");
394*b1cdbd2cSJim Jagielski	}
395*b1cdbd2cSJim Jagielski	# allow // at beginnging of line, often used to comment out code
396*b1cdbd2cSJim Jagielski	if (/.\/\/\S/) {		# C++ comments
397*b1cdbd2cSJim Jagielski		do err("missing blank after start comment");
398*b1cdbd2cSJim Jagielski	}
399*b1cdbd2cSJim Jagielski	# check for unterminated single line comments.
400*b1cdbd2cSJim Jagielski	if (/\S.*\/\*/ && !/\S.*\/\*.*\*\//) {
401*b1cdbd2cSJim Jagielski		do err("unterminated single line comment");
402*b1cdbd2cSJim Jagielski	}
403*b1cdbd2cSJim Jagielski
404*b1cdbd2cSJim Jagielski	# delete any comments and check everything else.
405*b1cdbd2cSJim Jagielski	s/\/\*.*\*\///g;
406*b1cdbd2cSJim Jagielski	s/\/\/.*$//;		# C++ comments
407*b1cdbd2cSJim Jagielski
408*b1cdbd2cSJim Jagielski	# delete any trailing whitespace; we have already checked for that.
409*b1cdbd2cSJim Jagielski	s/\s*$//;
410*b1cdbd2cSJim Jagielski
411*b1cdbd2cSJim Jagielski	# following checks do not apply to text in comments.
412*b1cdbd2cSJim Jagielski
413*b1cdbd2cSJim Jagielski	# if it looks like an operator at the end of the line, and it is
414*b1cdbd2cSJim Jagielski	# not really the end of a comment (...*/), and it is not really
415*b1cdbd2cSJim Jagielski	# a label (done:), and it is not a case label (case FOO:),
416*b1cdbd2cSJim Jagielski	# or we are not in a function definition (ANSI C style) and the
417*b1cdbd2cSJim Jagielski	# operator is a "," (to avoid hitting "int\nfoo(\n\tint i,\n\tint j)"),
418*b1cdbd2cSJim Jagielski	# or we are in a function and the operator is a
419*b1cdbd2cSJim Jagielski	# "*" (to avoid hitting on "char*\nfunc()").
420*b1cdbd2cSJim Jagielski	if ((/[-+|&\/?:=]$/ && !/\*\/$/ && !/^\s*\w*:$/ &&
421*b1cdbd2cSJim Jagielski	    !/^\s\s*case\s\s*\w*:$/) ||
422*b1cdbd2cSJim Jagielski	    /,$/ ||
423*b1cdbd2cSJim Jagielski	    ($in_class && /\*$/)) {
424*b1cdbd2cSJim Jagielski		$expect_continuation = 1;
425*b1cdbd2cSJim Jagielski		if (!$in_continuation) {
426*b1cdbd2cSJim Jagielski			/^(\s*)\S/;
427*b1cdbd2cSJim Jagielski			$continuation_indent = $1;
428*b1cdbd2cSJim Jagielski		}
429*b1cdbd2cSJim Jagielski	}
430*b1cdbd2cSJim Jagielski	if (/[^<>\s][!<>=]=/ || /[^<>][!<>=]=\S/ ||
431*b1cdbd2cSJim Jagielski	    (/[^->]>[^=>\s]/ && !/[^->]>$/) || (/[^<]<[^=<\s]/ && !/[^<]<$/) ||
432*b1cdbd2cSJim Jagielski	    /[^<\s]<[^<]/ || /[^->\s]>[^>]/) {
433*b1cdbd2cSJim Jagielski		do err("missing space around relational operator");
434*b1cdbd2cSJim Jagielski	}
435*b1cdbd2cSJim Jagielski	if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ ||
436*b1cdbd2cSJim Jagielski	    (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) ||
437*b1cdbd2cSJim Jagielski	    (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) {
438*b1cdbd2cSJim Jagielski		do err("missing space around assignment operator");
439*b1cdbd2cSJim Jagielski	}
440*b1cdbd2cSJim Jagielski	if (/[,;]\S/ && !/\bfor \(;;\)/) {
441*b1cdbd2cSJim Jagielski		do err("comma or semicolon followed by non-blank");
442*b1cdbd2cSJim Jagielski	}
443*b1cdbd2cSJim Jagielski	# allow "for" statements to have empty "while" clauses
444*b1cdbd2cSJim Jagielski	if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) {
445*b1cdbd2cSJim Jagielski		do err("comma or semicolon preceded by blank");
446*b1cdbd2cSJim Jagielski	}
447*b1cdbd2cSJim Jagielskiif (0) {
448*b1cdbd2cSJim Jagielski	if (/^\s*(&&|\|\|)/) {
449*b1cdbd2cSJim Jagielski		do err("improper boolean continuation");
450*b1cdbd2cSJim Jagielski	}
451*b1cdbd2cSJim Jagielski}
452*b1cdbd2cSJim Jagielski	if ($picky && /\S   *(&&|\|\|)/ || /(&&|\|\|)   *\S/) {
453*b1cdbd2cSJim Jagielski		do err("more than one space around boolean operator");
454*b1cdbd2cSJim Jagielski	}
455*b1cdbd2cSJim Jagielski	if (/\b(for|if|while|switch|return|case|catch|synchronized)\(/) {
456*b1cdbd2cSJim Jagielski		do err("missing space between keyword and paren");
457*b1cdbd2cSJim Jagielski	}
458*b1cdbd2cSJim Jagielski	if (/(\b(for|if|while|switch|return|catch|synchronized)\b.*){2,}/) {
459*b1cdbd2cSJim Jagielski		# multiple "case" allowed
460*b1cdbd2cSJim Jagielski		do err("more than one keyword on line");
461*b1cdbd2cSJim Jagielski	}
462*b1cdbd2cSJim Jagielski	if (/\b(for|if|while|switch|return|case|catch|synchronized)\s\s+\(/ &&
463*b1cdbd2cSJim Jagielski	    !/^#if\s+\(/) {
464*b1cdbd2cSJim Jagielski		do err("extra space between keyword and paren");
465*b1cdbd2cSJim Jagielski	}
466*b1cdbd2cSJim Jagielski	# try to detect "func (x)" but not "if (x)" or
467*b1cdbd2cSJim Jagielski	# "int (*func)();"
468*b1cdbd2cSJim Jagielski	if (/\w\s\(/) {
469*b1cdbd2cSJim Jagielski		$s = $_;
470*b1cdbd2cSJim Jagielski		# strip off all keywords on the line
471*b1cdbd2cSJim Jagielski		s/\b(for|if|while|switch|return|case|catch|synchronized)\s\(/XXX(/g;
472*b1cdbd2cSJim Jagielski		#s/\b($typename|void)\s+\(+/XXX(/og;
473*b1cdbd2cSJim Jagielski		if (/\w\s\(/) {
474*b1cdbd2cSJim Jagielski			do err("extra space between function name and left paren");
475*b1cdbd2cSJim Jagielski		}
476*b1cdbd2cSJim Jagielski		$_ = $s;
477*b1cdbd2cSJim Jagielski	}
478*b1cdbd2cSJim Jagielski	if (/\(\s/) {
479*b1cdbd2cSJim Jagielski		do err("whitespace after left paren");
480*b1cdbd2cSJim Jagielski	}
481*b1cdbd2cSJim Jagielski	# allow "for" statements to have empty "continue" clauses
482*b1cdbd2cSJim Jagielski	if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) {
483*b1cdbd2cSJim Jagielski		do err("whitespace before right paren");
484*b1cdbd2cSJim Jagielski	}
485*b1cdbd2cSJim Jagielski	if (/^\s*\(void\)[^ ]/) {
486*b1cdbd2cSJim Jagielski		do err("missing space after (void) cast");
487*b1cdbd2cSJim Jagielski	}
488*b1cdbd2cSJim Jagielski	if (/\S{/ && !/{{/) {
489*b1cdbd2cSJim Jagielski		do err("missing space before left brace");
490*b1cdbd2cSJim Jagielski	}
491*b1cdbd2cSJim Jagielski	if ($in_class && /^\s+{/ && ($prev =~ /\)\s*$/)) {
492*b1cdbd2cSJim Jagielski		do err("left brace starting a line");
493*b1cdbd2cSJim Jagielski	}
494*b1cdbd2cSJim Jagielski	if (/}(else|while)/) {
495*b1cdbd2cSJim Jagielski		do err("missing space after right brace");
496*b1cdbd2cSJim Jagielski	}
497*b1cdbd2cSJim Jagielski	if (/}\s\s+(else|while)/) {
498*b1cdbd2cSJim Jagielski		do err("extra space after right brace");
499*b1cdbd2cSJim Jagielski	}
500*b1cdbd2cSJim Jagielski	if (/\b$typename\*/o) {
501*b1cdbd2cSJim Jagielski		do err("missing space between type name and *");
502*b1cdbd2cSJim Jagielski	}
503*b1cdbd2cSJim Jagielski	if ($heuristic) {
504*b1cdbd2cSJim Jagielski		# cannot check this everywhere due to "struct {\n...\n} foo;"
505*b1cdbd2cSJim Jagielski		if ($in_class && !$in_declaration &&
506*b1cdbd2cSJim Jagielski		    /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ &&
507*b1cdbd2cSJim Jagielski		    !/} (else|while)/ && !/}}/) {
508*b1cdbd2cSJim Jagielski			do err("possible bad text following right brace");
509*b1cdbd2cSJim Jagielski		}
510*b1cdbd2cSJim Jagielski		# cannot check this because sub-blocks in
511*b1cdbd2cSJim Jagielski		# the middle of code are ok
512*b1cdbd2cSJim Jagielski		if ($in_class && /^\s+{/) {
513*b1cdbd2cSJim Jagielski			do err("possible left brace starting a line");
514*b1cdbd2cSJim Jagielski		}
515*b1cdbd2cSJim Jagielski	}
516*b1cdbd2cSJim Jagielski	if (/^\s*else\W/) {
517*b1cdbd2cSJim Jagielski		if ($prev =~ /^\s*}$/) {
518*b1cdbd2cSJim Jagielski			$str = "else and right brace should be on same line";
519*b1cdbd2cSJim Jagielski			if ($statistics == 0) {
520*b1cdbd2cSJim Jagielski				printf $fmt, $filename, $., $str, $prev;
521*b1cdbd2cSJim Jagielski				if ($verbose) {
522*b1cdbd2cSJim Jagielski					printf "%s\n", $line;
523*b1cdbd2cSJim Jagielski				}
524*b1cdbd2cSJim Jagielski			} else {
525*b1cdbd2cSJim Jagielski				$errcount{$str} += 1;
526*b1cdbd2cSJim Jagielski				$tot_errcount += 1;
527*b1cdbd2cSJim Jagielski			}
528*b1cdbd2cSJim Jagielski		}
529*b1cdbd2cSJim Jagielski	}
530*b1cdbd2cSJim Jagielski	$prev = $line;
531*b1cdbd2cSJim Jagielski}
532*b1cdbd2cSJim Jagielski
533*b1cdbd2cSJim Jagielskiif ($picky && $prev eq "") {
534*b1cdbd2cSJim Jagielski	do err("last line in file is blank");
535*b1cdbd2cSJim Jagielski}
536*b1cdbd2cSJim Jagielski
537*b1cdbd2cSJim Jagielski}
538