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