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