17c478bd9Sstevel@tonic-gate#!/usr/bin/perl -w 27c478bd9Sstevel@tonic-gate# 37c478bd9Sstevel@tonic-gate# CDDL HEADER START 47c478bd9Sstevel@tonic-gate# 57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the 6cdf0c1d5Smjnelson# Common Development and Distribution License (the "License"). 7cdf0c1d5Smjnelson# You may not use this file except in compliance with the License. 87c478bd9Sstevel@tonic-gate# 97c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate# and limitations under the License. 137c478bd9Sstevel@tonic-gate# 147c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate# 207c478bd9Sstevel@tonic-gate# CDDL HEADER END 217c478bd9Sstevel@tonic-gate# 2294385aa4SToomas Soome# Copyright 2015 Toomas Soome <tsoome@me.com> 230ce4971aSHans Rosenfeld# Copyright 2016 Nexenta Systems, Inc. 247c478bd9Sstevel@tonic-gate# 25cdf0c1d5Smjnelson# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 267c478bd9Sstevel@tonic-gate# Use is subject to license terms. 277c478bd9Sstevel@tonic-gate# 28c4567a61SPaul Dagnelie# Copyright (c) 2015 by Delphix. All rights reserved. 29c4567a61SPaul Dagnelie# 307c478bd9Sstevel@tonic-gate# @(#)cstyle 1.58 98/09/09 (from shannon) 317c478bd9Sstevel@tonic-gate# 327c478bd9Sstevel@tonic-gate# cstyle - check for some common stylistic errors. 337c478bd9Sstevel@tonic-gate# 347c478bd9Sstevel@tonic-gate# cstyle is a sort of "lint" for C coding style. 357c478bd9Sstevel@tonic-gate# It attempts to check for the style used in the 367c478bd9Sstevel@tonic-gate# kernel, sometimes known as "Bill Joy Normal Form". 377c478bd9Sstevel@tonic-gate# 387c478bd9Sstevel@tonic-gate# There's a lot this can't check for, like proper indentation 397c478bd9Sstevel@tonic-gate# of code blocks. There's also a lot more this could check for. 407c478bd9Sstevel@tonic-gate# 417c478bd9Sstevel@tonic-gate# A note to the non perl literate: 427c478bd9Sstevel@tonic-gate# 437c478bd9Sstevel@tonic-gate# perl regular expressions are pretty much like egrep 447c478bd9Sstevel@tonic-gate# regular expressions, with the following special symbols 457c478bd9Sstevel@tonic-gate# 467c478bd9Sstevel@tonic-gate# \s any space character 477c478bd9Sstevel@tonic-gate# \S any non-space character 487c478bd9Sstevel@tonic-gate# \w any "word" character [a-zA-Z0-9_] 497c478bd9Sstevel@tonic-gate# \W any non-word character 507c478bd9Sstevel@tonic-gate# \d a digit [0-9] 517c478bd9Sstevel@tonic-gate# \D a non-digit 527c478bd9Sstevel@tonic-gate# \b word boundary (between \w and \W) 537c478bd9Sstevel@tonic-gate# \B non-word boundary 547c478bd9Sstevel@tonic-gate# 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gaterequire 5.0; 577c478bd9Sstevel@tonic-gateuse IO::File; 587c478bd9Sstevel@tonic-gateuse Getopt::Std; 597c478bd9Sstevel@tonic-gateuse strict; 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gatemy $usage = 623c2f5c48Sjwadams"usage: cstyle [-chpvCP] [-o constructs] file ... 637c478bd9Sstevel@tonic-gate -c check continuation indentation inside functions 647c478bd9Sstevel@tonic-gate -h perform heuristic checks that are sometimes wrong 657c478bd9Sstevel@tonic-gate -p perform some of the more picky checks 667c478bd9Sstevel@tonic-gate -v verbose 677c478bd9Sstevel@tonic-gate -C don't check anything in header block comments 687c478bd9Sstevel@tonic-gate -P check for use of non-POSIX types 693c2f5c48Sjwadams -o constructs 703c2f5c48Sjwadams allow a comma-seperated list of optional constructs: 713c2f5c48Sjwadams doxygen allow doxygen-style block comments (/** /*!) 723c2f5c48Sjwadams splint allow splint-style lint comments (/*@ ... @*/) 737c478bd9Sstevel@tonic-gate"; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gatemy %opts; 767c478bd9Sstevel@tonic-gate 773c2f5c48Sjwadamsif (!getopts("cho:pvCP", \%opts)) { 787c478bd9Sstevel@tonic-gate print $usage; 79cdf0c1d5Smjnelson exit 2; 807c478bd9Sstevel@tonic-gate} 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gatemy $check_continuation = $opts{'c'}; 837c478bd9Sstevel@tonic-gatemy $heuristic = $opts{'h'}; 847c478bd9Sstevel@tonic-gatemy $picky = $opts{'p'}; 857c478bd9Sstevel@tonic-gatemy $verbose = $opts{'v'}; 867c478bd9Sstevel@tonic-gatemy $ignore_hdr_comment = $opts{'C'}; 877c478bd9Sstevel@tonic-gatemy $check_posix_types = $opts{'P'}; 887c478bd9Sstevel@tonic-gate 893c2f5c48Sjwadamsmy $doxygen_comments = 0; 903c2f5c48Sjwadamsmy $splint_comments = 0; 913c2f5c48Sjwadams 923c2f5c48Sjwadamsif (defined($opts{'o'})) { 933c2f5c48Sjwadams for my $x (split /,/, $opts{'o'}) { 943c2f5c48Sjwadams if ($x eq "doxygen") { 953c2f5c48Sjwadams $doxygen_comments = 1; 963c2f5c48Sjwadams } elsif ($x eq "splint") { 973c2f5c48Sjwadams $splint_comments = 1; 983c2f5c48Sjwadams } else { 993c2f5c48Sjwadams print "cstyle: unrecognized construct \"$x\"\n"; 1003c2f5c48Sjwadams print $usage; 101cdf0c1d5Smjnelson exit 2; 1023c2f5c48Sjwadams } 1033c2f5c48Sjwadams } 1043c2f5c48Sjwadams} 1053c2f5c48Sjwadams 1067c478bd9Sstevel@tonic-gatemy ($filename, $line, $prev); # shared globals 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gatemy $fmt; 1093c2f5c48Sjwadamsmy $hdr_comment_start; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gateif ($verbose) { 1127c478bd9Sstevel@tonic-gate $fmt = "%s: %d: %s\n%s\n"; 1137c478bd9Sstevel@tonic-gate} else { 1147c478bd9Sstevel@tonic-gate $fmt = "%s: %d: %s\n"; 1157c478bd9Sstevel@tonic-gate} 1167c478bd9Sstevel@tonic-gate 1173c2f5c48Sjwadamsif ($doxygen_comments) { 1183c2f5c48Sjwadams # doxygen comments look like "/*!" or "/**"; allow them. 1193c2f5c48Sjwadams $hdr_comment_start = qr/^\s*\/\*[\!\*]?$/; 1203c2f5c48Sjwadams} else { 1213c2f5c48Sjwadams $hdr_comment_start = qr/^\s*\/\*$/; 1223c2f5c48Sjwadams} 1233c2f5c48Sjwadams 1247c478bd9Sstevel@tonic-gate# Note, following must be in single quotes so that \s and \w work right. 1257c478bd9Sstevel@tonic-gatemy $typename = '(int|char|short|long|unsigned|float|double' . 1267c478bd9Sstevel@tonic-gate '|\w+_t|struct\s+\w+|union\s+\w+|FILE)'; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate# mapping of old types to POSIX compatible types 1297c478bd9Sstevel@tonic-gatemy %old2posix = ( 1307c478bd9Sstevel@tonic-gate 'unchar' => 'uchar_t', 1317c478bd9Sstevel@tonic-gate 'ushort' => 'ushort_t', 1327c478bd9Sstevel@tonic-gate 'uint' => 'uint_t', 1337c478bd9Sstevel@tonic-gate 'ulong' => 'ulong_t', 1347c478bd9Sstevel@tonic-gate 'u_int' => 'uint_t', 1357c478bd9Sstevel@tonic-gate 'u_short' => 'ushort_t', 1367c478bd9Sstevel@tonic-gate 'u_long' => 'ulong_t', 1377c478bd9Sstevel@tonic-gate 'u_char' => 'uchar_t', 1387c478bd9Sstevel@tonic-gate 'quad' => 'quad_t' 1397c478bd9Sstevel@tonic-gate); 1407c478bd9Sstevel@tonic-gate 1413c2f5c48Sjwadamsmy $lint_re = qr/\/\*(?: 1423c2f5c48Sjwadams ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*| 1433c2f5c48Sjwadams CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY| 1443c2f5c48Sjwadams FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*| 1453c2f5c48Sjwadams PROTOLIB[0-9]*|SCANFLIKE[0-9]*|CSTYLED.*? 1463c2f5c48Sjwadams )\*\//x; 1473c2f5c48Sjwadams 1483c2f5c48Sjwadamsmy $splint_re = qr/\/\*@.*?@\*\//x; 1493c2f5c48Sjwadams 1503c2f5c48Sjwadamsmy $warlock_re = qr/\/\*\s*(?: 1513c2f5c48Sjwadams VARIABLES\ PROTECTED\ BY| 1523c2f5c48Sjwadams MEMBERS\ PROTECTED\ BY| 1533c2f5c48Sjwadams ALL\ MEMBERS\ PROTECTED\ BY| 1543c2f5c48Sjwadams READ-ONLY\ VARIABLES:| 1553c2f5c48Sjwadams READ-ONLY\ MEMBERS:| 1563c2f5c48Sjwadams VARIABLES\ READABLE\ WITHOUT\ LOCK:| 1573c2f5c48Sjwadams MEMBERS\ READABLE\ WITHOUT\ LOCK:| 1583c2f5c48Sjwadams LOCKS\ COVERED\ BY| 1593c2f5c48Sjwadams LOCK\ UNNEEDED\ BECAUSE| 1603c2f5c48Sjwadams LOCK\ NEEDED:| 1613c2f5c48Sjwadams LOCK\ HELD\ ON\ ENTRY:| 1623c2f5c48Sjwadams READ\ LOCK\ HELD\ ON\ ENTRY:| 1633c2f5c48Sjwadams WRITE\ LOCK\ HELD\ ON\ ENTRY:| 1643c2f5c48Sjwadams LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:| 1653c2f5c48Sjwadams READ\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:| 1663c2f5c48Sjwadams WRITE\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:| 1673c2f5c48Sjwadams LOCK\ RELEASED\ AS\ SIDE\ EFFECT:| 1683c2f5c48Sjwadams LOCK\ UPGRADED\ AS\ SIDE\ EFFECT:| 1693c2f5c48Sjwadams LOCK\ DOWNGRADED\ AS\ SIDE\ EFFECT:| 1703c2f5c48Sjwadams FUNCTIONS\ CALLED\ THROUGH\ POINTER| 1713c2f5c48Sjwadams FUNCTIONS\ CALLED\ THROUGH\ MEMBER| 1723c2f5c48Sjwadams LOCK\ ORDER: 1733c2f5c48Sjwadams )/x; 1747c478bd9Sstevel@tonic-gate 175cdf0c1d5Smjnelsonmy $err_stat = 0; # exit status 176cdf0c1d5Smjnelson 1777c478bd9Sstevel@tonic-gateif ($#ARGV >= 0) { 1787c478bd9Sstevel@tonic-gate foreach my $arg (@ARGV) { 1797c478bd9Sstevel@tonic-gate my $fh = new IO::File $arg, "r"; 1807c478bd9Sstevel@tonic-gate if (!defined($fh)) { 1817c478bd9Sstevel@tonic-gate printf "%s: can not open\n", $arg; 1827c478bd9Sstevel@tonic-gate } else { 1837c478bd9Sstevel@tonic-gate &cstyle($arg, $fh); 1847c478bd9Sstevel@tonic-gate close $fh; 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate} else { 1887c478bd9Sstevel@tonic-gate &cstyle("<stdin>", *STDIN); 1897c478bd9Sstevel@tonic-gate} 190cdf0c1d5Smjnelsonexit $err_stat; 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gatemy $no_errs = 0; # set for CSTYLED-protected lines 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gatesub err($) { 1957c478bd9Sstevel@tonic-gate my ($error) = @_; 196cdf0c1d5Smjnelson unless ($no_errs) { 19794385aa4SToomas Soome if ($verbose) { 198cdf0c1d5Smjnelson printf $fmt, $filename, $., $error, $line; 19994385aa4SToomas Soome } else { 20094385aa4SToomas Soome printf $fmt, $filename, $., $error; 20194385aa4SToomas Soome } 202cdf0c1d5Smjnelson $err_stat = 1; 203cdf0c1d5Smjnelson } 2047c478bd9Sstevel@tonic-gate} 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gatesub err_prefix($$) { 2077c478bd9Sstevel@tonic-gate my ($prevline, $error) = @_; 2087c478bd9Sstevel@tonic-gate my $out = $prevline."\n".$line; 209cdf0c1d5Smjnelson unless ($no_errs) { 21094385aa4SToomas Soome if ($verbose) { 211cdf0c1d5Smjnelson printf $fmt, $filename, $., $error, $out; 21294385aa4SToomas Soome } else { 21394385aa4SToomas Soome printf $fmt, $filename, $., $error; 21494385aa4SToomas Soome } 215cdf0c1d5Smjnelson $err_stat = 1; 216cdf0c1d5Smjnelson } 2177c478bd9Sstevel@tonic-gate} 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gatesub err_prev($) { 2207c478bd9Sstevel@tonic-gate my ($error) = @_; 221cdf0c1d5Smjnelson unless ($no_errs) { 22294385aa4SToomas Soome if ($verbose) { 223cdf0c1d5Smjnelson printf $fmt, $filename, $. - 1, $error, $prev; 22494385aa4SToomas Soome } else { 22594385aa4SToomas Soome printf $fmt, $filename, $. - 1, $error; 22694385aa4SToomas Soome } 227cdf0c1d5Smjnelson $err_stat = 1; 228cdf0c1d5Smjnelson } 2297c478bd9Sstevel@tonic-gate} 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gatesub cstyle($$) { 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gatemy ($fn, $filehandle) = @_; 2347c478bd9Sstevel@tonic-gate$filename = $fn; # share it globally 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gatemy $in_cpp = 0; 2377c478bd9Sstevel@tonic-gatemy $next_in_cpp = 0; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gatemy $in_comment = 0; 2407c478bd9Sstevel@tonic-gatemy $in_header_comment = 0; 2417c478bd9Sstevel@tonic-gatemy $comment_done = 0; 2427c478bd9Sstevel@tonic-gatemy $in_warlock_comment = 0; 2437c478bd9Sstevel@tonic-gatemy $in_function = 0; 2447c478bd9Sstevel@tonic-gatemy $in_function_header = 0; 245c4567a61SPaul Dagneliemy $function_header_full_indent = 0; 2467c478bd9Sstevel@tonic-gatemy $in_declaration = 0; 2477c478bd9Sstevel@tonic-gatemy $note_level = 0; 2487c478bd9Sstevel@tonic-gatemy $nextok = 0; 2497c478bd9Sstevel@tonic-gatemy $nocheck = 0; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gatemy $in_string = 0; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gatemy ($okmsg, $comment_prefix); 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate$line = ''; 2567c478bd9Sstevel@tonic-gate$prev = ''; 2577c478bd9Sstevel@tonic-gatereset_indent(); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gateline: while (<$filehandle>) { 2607c478bd9Sstevel@tonic-gate s/\r?\n$//; # strip return and newline 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate # save the original line, then remove all text from within 2637c478bd9Sstevel@tonic-gate # double or single quotes, we do not want to check such text. 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate $line = $_; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate # 2687c478bd9Sstevel@tonic-gate # C allows strings to be continued with a backslash at the end of 2697c478bd9Sstevel@tonic-gate # the line. We translate that into a quoted string on the previous 2707c478bd9Sstevel@tonic-gate # line followed by an initial quote on the next line. 2717c478bd9Sstevel@tonic-gate # 2727c478bd9Sstevel@tonic-gate # (we assume that no-one will use backslash-continuation with character 2737c478bd9Sstevel@tonic-gate # constants) 2747c478bd9Sstevel@tonic-gate # 2757c478bd9Sstevel@tonic-gate $_ = '"' . $_ if ($in_string && !$nocheck && !$in_comment); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate # 2787c478bd9Sstevel@tonic-gate # normal strings and characters 2797c478bd9Sstevel@tonic-gate # 2807c478bd9Sstevel@tonic-gate s/'([^\\']|\\[^xX0]|\\0[0-9]*|\\[xX][0-9a-fA-F]*)'/''/g; 2817c478bd9Sstevel@tonic-gate s/"([^\\"]|\\.)*"/\"\"/g; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate # 2847c478bd9Sstevel@tonic-gate # detect string continuation 2857c478bd9Sstevel@tonic-gate # 2867c478bd9Sstevel@tonic-gate if ($nocheck || $in_comment) { 2877c478bd9Sstevel@tonic-gate $in_string = 0; 2887c478bd9Sstevel@tonic-gate } else { 2897c478bd9Sstevel@tonic-gate # 2907c478bd9Sstevel@tonic-gate # Now that all full strings are replaced with "", we check 2917c478bd9Sstevel@tonic-gate # for unfinished strings continuing onto the next line. 2927c478bd9Sstevel@tonic-gate # 2937c478bd9Sstevel@tonic-gate $in_string = 2947c478bd9Sstevel@tonic-gate (s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ || 2957c478bd9Sstevel@tonic-gate s/^("")*"([^\\"]|\\.)*\\$/""/); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate # 2997c478bd9Sstevel@tonic-gate # figure out if we are in a cpp directive 3007c478bd9Sstevel@tonic-gate # 3017c478bd9Sstevel@tonic-gate $in_cpp = $next_in_cpp || /^\s*#/; # continued or started 3027c478bd9Sstevel@tonic-gate $next_in_cpp = $in_cpp && /\\$/; # only if continued 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate # strip off trailing backslashes, which appear in long macros 3057c478bd9Sstevel@tonic-gate s/\s*\\$//; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate # an /* END CSTYLED */ comment ends a no-check block. 3087c478bd9Sstevel@tonic-gate if ($nocheck) { 3097c478bd9Sstevel@tonic-gate if (/\/\* *END *CSTYLED *\*\//) { 3107c478bd9Sstevel@tonic-gate $nocheck = 0; 3117c478bd9Sstevel@tonic-gate } else { 3127c478bd9Sstevel@tonic-gate reset_indent(); 3137c478bd9Sstevel@tonic-gate next line; 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate # a /*CSTYLED*/ comment indicates that the next line is ok. 3187c478bd9Sstevel@tonic-gate if ($nextok) { 3197c478bd9Sstevel@tonic-gate if ($okmsg) { 3207c478bd9Sstevel@tonic-gate err($okmsg); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate $nextok = 0; 3237c478bd9Sstevel@tonic-gate $okmsg = 0; 3247c478bd9Sstevel@tonic-gate if (/\/\* *CSTYLED.*\*\//) { 3257c478bd9Sstevel@tonic-gate /^.*\/\* *CSTYLED *(.*) *\*\/.*$/; 3267c478bd9Sstevel@tonic-gate $okmsg = $1; 3277c478bd9Sstevel@tonic-gate $nextok = 1; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate $no_errs = 1; 3307c478bd9Sstevel@tonic-gate } elsif ($no_errs) { 3317c478bd9Sstevel@tonic-gate $no_errs = 0; 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate # check length of line. 3357c478bd9Sstevel@tonic-gate # first, a quick check to see if there is any chance of being too long. 3367c478bd9Sstevel@tonic-gate if (($line =~ tr/\t/\t/) * 7 + length($line) > 80) { 3377c478bd9Sstevel@tonic-gate # yes, there is a chance. 3387c478bd9Sstevel@tonic-gate # replace tabs with spaces and check again. 3397c478bd9Sstevel@tonic-gate my $eline = $line; 3407c478bd9Sstevel@tonic-gate 1 while $eline =~ 3417c478bd9Sstevel@tonic-gate s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; 3427c478bd9Sstevel@tonic-gate if (length($eline) > 80) { 3437c478bd9Sstevel@tonic-gate err("line > 80 characters"); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate # ignore NOTE(...) annotations (assumes NOTE is on lines by itself). 3487c478bd9Sstevel@tonic-gate if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE 3497c478bd9Sstevel@tonic-gate s/[^()]//g; # eliminate all non-parens 3507c478bd9Sstevel@tonic-gate $note_level += s/\(//g - length; # update paren nest level 3517c478bd9Sstevel@tonic-gate next; 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate # a /* BEGIN CSTYLED */ comment starts a no-check block. 3557c478bd9Sstevel@tonic-gate if (/\/\* *BEGIN *CSTYLED *\*\//) { 3567c478bd9Sstevel@tonic-gate $nocheck = 1; 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate # a /*CSTYLED*/ comment indicates that the next line is ok. 3607c478bd9Sstevel@tonic-gate if (/\/\* *CSTYLED.*\*\//) { 3617c478bd9Sstevel@tonic-gate /^.*\/\* *CSTYLED *(.*) *\*\/.*$/; 3627c478bd9Sstevel@tonic-gate $okmsg = $1; 3637c478bd9Sstevel@tonic-gate $nextok = 1; 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate if (/\/\/ *CSTYLED/) { 3667c478bd9Sstevel@tonic-gate /^.*\/\/ *CSTYLED *(.*)$/; 3677c478bd9Sstevel@tonic-gate $okmsg = $1; 3687c478bd9Sstevel@tonic-gate $nextok = 1; 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate # universal checks; apply to everything 3727c478bd9Sstevel@tonic-gate if (/\t +\t/) { 3737c478bd9Sstevel@tonic-gate err("spaces between tabs"); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate if (/ \t+ /) { 3767c478bd9Sstevel@tonic-gate err("tabs between spaces"); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate if (/\s$/) { 3797c478bd9Sstevel@tonic-gate err("space or tab at end of line"); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) { 3827c478bd9Sstevel@tonic-gate err("comment preceded by non-blank"); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate # is this the beginning or ending of a function? 3867c478bd9Sstevel@tonic-gate # (not if "struct foo\n{\n") 387*518b16b9SDominik Hassler if (/^\{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) { 3887c478bd9Sstevel@tonic-gate $in_function = 1; 3897c478bd9Sstevel@tonic-gate $in_declaration = 1; 3907c478bd9Sstevel@tonic-gate $in_function_header = 0; 391c4567a61SPaul Dagnelie $function_header_full_indent = 0; 3927c478bd9Sstevel@tonic-gate $prev = $line; 3937c478bd9Sstevel@tonic-gate next line; 3947c478bd9Sstevel@tonic-gate } 395*518b16b9SDominik Hassler if (/^\}\s*(\/\*.*\*\/\s*)*$/) { 3967c478bd9Sstevel@tonic-gate if ($prev =~ /^\s*return\s*;/) { 3977c478bd9Sstevel@tonic-gate err_prev("unneeded return at end of function"); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate $in_function = 0; 4007c478bd9Sstevel@tonic-gate reset_indent(); # we don't check between functions 4017c478bd9Sstevel@tonic-gate $prev = $line; 4027c478bd9Sstevel@tonic-gate next line; 4037c478bd9Sstevel@tonic-gate } 4040ce4971aSHans Rosenfeld if ($in_function_header && ! /^ (\w|\.)/ ) { 405*518b16b9SDominik Hassler if (/^\{\}$/) { 406c4567a61SPaul Dagnelie $in_function_header = 0; 407c4567a61SPaul Dagnelie $function_header_full_indent = 0; 408c4567a61SPaul Dagnelie } elsif ($picky && ! (/^\t/ && $function_header_full_indent != 0)) { 409c4567a61SPaul Dagnelie err("continuation line should be indented by 4 spaces"); 410c4567a61SPaul Dagnelie } 411c4567a61SPaul Dagnelie } 412c4567a61SPaul Dagnelie 413c4567a61SPaul Dagnelie # 414c4567a61SPaul Dagnelie # If this matches something of form "foo(", it's probably a function 415c4567a61SPaul Dagnelie # definition, unless it ends with ") bar;", in which case it's a declaration 416c4567a61SPaul Dagnelie # that uses a macro to generate the type. 417c4567a61SPaul Dagnelie # 418c4567a61SPaul Dagnelie if (/^\w+\(/ && !/\) \w+;$/) { 4197c478bd9Sstevel@tonic-gate $in_function_header = 1; 420c4567a61SPaul Dagnelie if (/\($/) { 421c4567a61SPaul Dagnelie $function_header_full_indent = 1; 422c4567a61SPaul Dagnelie } 423c4567a61SPaul Dagnelie } 424*518b16b9SDominik Hassler if ($in_function_header && /^\{$/) { 425c4567a61SPaul Dagnelie $in_function_header = 0; 426c4567a61SPaul Dagnelie $function_header_full_indent = 0; 427c4567a61SPaul Dagnelie $in_function = 1; 428c4567a61SPaul Dagnelie } 429c4567a61SPaul Dagnelie if ($in_function_header && /\);$/) { 430c4567a61SPaul Dagnelie $in_function_header = 0; 431c4567a61SPaul Dagnelie $function_header_full_indent = 0; 432c4567a61SPaul Dagnelie } 433*518b16b9SDominik Hassler if ($in_function_header && /\{$/ ) { 434b1a5b4f7SRichard PALO if ($picky) { 435c4567a61SPaul Dagnelie err("opening brace on same line as function header"); 436c4567a61SPaul Dagnelie } 437c4567a61SPaul Dagnelie $in_function_header = 0; 438c4567a61SPaul Dagnelie $function_header_full_indent = 0; 439c4567a61SPaul Dagnelie $in_function = 1; 440c4567a61SPaul Dagnelie next line; 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate if ($in_warlock_comment && /\*\//) { 4447c478bd9Sstevel@tonic-gate $in_warlock_comment = 0; 4457c478bd9Sstevel@tonic-gate $prev = $line; 4467c478bd9Sstevel@tonic-gate next line; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate # a blank line terminates the declarations within a function. 4507c478bd9Sstevel@tonic-gate # XXX - but still a problem in sub-blocks. 4517c478bd9Sstevel@tonic-gate if ($in_declaration && /^$/) { 4527c478bd9Sstevel@tonic-gate $in_declaration = 0; 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate if ($comment_done) { 4567c478bd9Sstevel@tonic-gate $in_comment = 0; 4577c478bd9Sstevel@tonic-gate $in_header_comment = 0; 4587c478bd9Sstevel@tonic-gate $comment_done = 0; 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate # does this looks like the start of a block comment? 4613c2f5c48Sjwadams if (/$hdr_comment_start/) { 4623c2f5c48Sjwadams if (!/^\t*\/\*/) { 4637c478bd9Sstevel@tonic-gate err("block comment not indented by tabs"); 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate $in_comment = 1; 4663c2f5c48Sjwadams /^(\s*)\//; 4673c2f5c48Sjwadams $comment_prefix = $1; 4687c478bd9Sstevel@tonic-gate if ($comment_prefix eq "") { 4697c478bd9Sstevel@tonic-gate $in_header_comment = 1; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate $prev = $line; 4727c478bd9Sstevel@tonic-gate next line; 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate # are we still in the block comment? 4757c478bd9Sstevel@tonic-gate if ($in_comment) { 4767c478bd9Sstevel@tonic-gate if (/^$comment_prefix \*\/$/) { 4777c478bd9Sstevel@tonic-gate $comment_done = 1; 4787c478bd9Sstevel@tonic-gate } elsif (/\*\//) { 4797c478bd9Sstevel@tonic-gate $comment_done = 1; 4807c478bd9Sstevel@tonic-gate err("improper block comment close") 4817c478bd9Sstevel@tonic-gate unless ($ignore_hdr_comment && $in_header_comment); 4827c478bd9Sstevel@tonic-gate } elsif (!/^$comment_prefix \*[ \t]/ && 4837c478bd9Sstevel@tonic-gate !/^$comment_prefix \*$/) { 4847c478bd9Sstevel@tonic-gate err("improper block comment") 4857c478bd9Sstevel@tonic-gate unless ($ignore_hdr_comment && $in_header_comment); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate if ($in_header_comment && $ignore_hdr_comment) { 4907c478bd9Sstevel@tonic-gate $prev = $line; 4917c478bd9Sstevel@tonic-gate next line; 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate # check for errors that might occur in comments and in code. 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate # allow spaces to be used to draw pictures in header comments. 4977c478bd9Sstevel@tonic-gate if (/[^ ] / && !/".* .*"/ && !$in_header_comment) { 4987c478bd9Sstevel@tonic-gate err("spaces instead of tabs"); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ && 5010ce4971aSHans Rosenfeld (!/^ (\w|\.)/ || $in_function != 0)) { 5027c478bd9Sstevel@tonic-gate err("indent by spaces instead of tabs"); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate if (/^\t+ [^ \t\*]/ || /^\t+ \S/ || /^\t+ \S/) { 5057c478bd9Sstevel@tonic-gate err("continuation line not indented by 4 spaces"); 5067c478bd9Sstevel@tonic-gate } 5073c2f5c48Sjwadams if (/$warlock_re/ && !/\*\//) { 5087c478bd9Sstevel@tonic-gate $in_warlock_comment = 1; 5097c478bd9Sstevel@tonic-gate $prev = $line; 5107c478bd9Sstevel@tonic-gate next line; 5117c478bd9Sstevel@tonic-gate } 5123c2f5c48Sjwadams if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) { 5137c478bd9Sstevel@tonic-gate err("improper first line of block comment"); 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate if ($in_comment) { # still in comment, don't do further checks 5177c478bd9Sstevel@tonic-gate $prev = $line; 5187c478bd9Sstevel@tonic-gate next line; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate if ((/[^(]\/\*\S/ || /^\/\*\S/) && 5223c2f5c48Sjwadams !(/$lint_re/ || ($splint_comments && /$splint_re/))) { 5237c478bd9Sstevel@tonic-gate err("missing blank after open comment"); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate if (/\S\*\/[^)]|\S\*\/$/ && 5263c2f5c48Sjwadams !(/$lint_re/ || ($splint_comments && /$splint_re/))) { 5277c478bd9Sstevel@tonic-gate err("missing blank before close comment"); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate if (/\/\/\S/) { # C++ comments 5307c478bd9Sstevel@tonic-gate err("missing blank after start comment"); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate # check for unterminated single line comments, but allow them when 5337c478bd9Sstevel@tonic-gate # they are used to comment out the argument list of a function 5347c478bd9Sstevel@tonic-gate # declaration. 5357c478bd9Sstevel@tonic-gate if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) { 5367c478bd9Sstevel@tonic-gate err("unterminated single line comment"); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate if (/^(#else|#endif|#include)(.*)$/) { 5407c478bd9Sstevel@tonic-gate $prev = $line; 5417c478bd9Sstevel@tonic-gate if ($picky) { 5427c478bd9Sstevel@tonic-gate my $directive = $1; 5437c478bd9Sstevel@tonic-gate my $clause = $2; 5447c478bd9Sstevel@tonic-gate # Enforce ANSI rules for #else and #endif: no noncomment 5457c478bd9Sstevel@tonic-gate # identifiers are allowed after #endif or #else. Allow 5467c478bd9Sstevel@tonic-gate # C++ comments since they seem to be a fact of life. 5477c478bd9Sstevel@tonic-gate if ((($1 eq "#endif") || ($1 eq "#else")) && 5487c478bd9Sstevel@tonic-gate ($clause ne "") && 5497c478bd9Sstevel@tonic-gate (!($clause =~ /^\s+\/\*.*\*\/$/)) && 5507c478bd9Sstevel@tonic-gate (!($clause =~ /^\s+\/\/.*$/))) { 5517c478bd9Sstevel@tonic-gate err("non-comment text following " . 5527c478bd9Sstevel@tonic-gate "$directive (or malformed $directive " . 5537c478bd9Sstevel@tonic-gate "directive)"); 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate next line; 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate # 5607c478bd9Sstevel@tonic-gate # delete any comments and check everything else. Note that 5617c478bd9Sstevel@tonic-gate # ".*?" is a non-greedy match, so that we don't get confused by 5627c478bd9Sstevel@tonic-gate # multiple comments on the same line. 5637c478bd9Sstevel@tonic-gate # 5647c478bd9Sstevel@tonic-gate s/\/\*.*?\*\///g; 5657c478bd9Sstevel@tonic-gate s/\/\/.*$//; # C++ comments 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate # delete any trailing whitespace; we have already checked for that. 5687c478bd9Sstevel@tonic-gate s/\s*$//; 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate # following checks do not apply to text in comments. 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate if (/[^<>\s][!<>=]=/ || /[^<>][!<>=]=[^\s,]/ || 5737c478bd9Sstevel@tonic-gate (/[^->]>[^,=>\s]/ && !/[^->]>$/) || 5747c478bd9Sstevel@tonic-gate (/[^<]<[^,=<\s]/ && !/[^<]<$/) || 5757c478bd9Sstevel@tonic-gate /[^<\s]<[^<]/ || /[^->\s]>[^>]/) { 5767c478bd9Sstevel@tonic-gate err("missing space around relational operator"); 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ || 5797c478bd9Sstevel@tonic-gate (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) || 5807c478bd9Sstevel@tonic-gate (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) { 5817c478bd9Sstevel@tonic-gate # XXX - should only check this for C++ code 5827c478bd9Sstevel@tonic-gate # XXX - there are probably other forms that should be allowed 5837c478bd9Sstevel@tonic-gate if (!/\soperator=/) { 5847c478bd9Sstevel@tonic-gate err("missing space around assignment operator"); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate if (/[,;]\S/ && !/\bfor \(;;\)/) { 5887c478bd9Sstevel@tonic-gate err("comma or semicolon followed by non-blank"); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate # allow "for" statements to have empty "while" clauses 5917c478bd9Sstevel@tonic-gate if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) { 5927c478bd9Sstevel@tonic-gate err("comma or semicolon preceded by blank"); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate if (/^\s*(&&|\|\|)/) { 5957c478bd9Sstevel@tonic-gate err("improper boolean continuation"); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate if (/\S *(&&|\|\|)/ || /(&&|\|\|) *\S/) { 5987c478bd9Sstevel@tonic-gate err("more than one space around boolean operator"); 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate if (/\b(for|if|while|switch|sizeof|return|case)\(/) { 6017c478bd9Sstevel@tonic-gate err("missing space between keyword and paren"); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate if (/(\b(for|if|while|switch|return)\b.*){2,}/ && !/^#define/) { 6047c478bd9Sstevel@tonic-gate # multiple "case" and "sizeof" allowed 6057c478bd9Sstevel@tonic-gate err("more than one keyword on line"); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate if (/\b(for|if|while|switch|sizeof|return|case)\s\s+\(/ && 6087c478bd9Sstevel@tonic-gate !/^#if\s+\(/) { 6097c478bd9Sstevel@tonic-gate err("extra space between keyword and paren"); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate # try to detect "func (x)" but not "if (x)" or 6127c478bd9Sstevel@tonic-gate # "#define foo (x)" or "int (*func)();" 6137c478bd9Sstevel@tonic-gate if (/\w\s\(/) { 6147c478bd9Sstevel@tonic-gate my $s = $_; 6157c478bd9Sstevel@tonic-gate # strip off all keywords on the line 6167c478bd9Sstevel@tonic-gate s/\b(for|if|while|switch|return|case|sizeof)\s\(/XXX(/g; 6177c478bd9Sstevel@tonic-gate s/#elif\s\(/XXX(/g; 6187c478bd9Sstevel@tonic-gate s/^#define\s+\w+\s+\(/XXX(/; 6197c478bd9Sstevel@tonic-gate # do not match things like "void (*f)();" 6207c478bd9Sstevel@tonic-gate # or "typedef void (func_t)();" 6217c478bd9Sstevel@tonic-gate s/\w\s\(+\*/XXX(*/g; 6227c478bd9Sstevel@tonic-gate s/\b($typename|void)\s+\(+/XXX(/og; 6237c478bd9Sstevel@tonic-gate if (/\w\s\(/) { 6247c478bd9Sstevel@tonic-gate err("extra space between function name and left paren"); 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate $_ = $s; 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate # try to detect "int foo(x)", but not "extern int foo(x);" 6297c478bd9Sstevel@tonic-gate # XXX - this still trips over too many legitimate things, 6307c478bd9Sstevel@tonic-gate # like "int foo(x,\n\ty);" 6317c478bd9Sstevel@tonic-gate# if (/^(\w+(\s|\*)+)+\w+\(/ && !/\)[;,](\s|)*$/ && 6327c478bd9Sstevel@tonic-gate# !/^(extern|static)\b/) { 6337c478bd9Sstevel@tonic-gate# err("return type of function not on separate line"); 6347c478bd9Sstevel@tonic-gate# } 6357c478bd9Sstevel@tonic-gate # this is a close approximation 6367c478bd9Sstevel@tonic-gate if (/^(\w+(\s|\*)+)+\w+\(.*\)(\s|)*$/ && 6377c478bd9Sstevel@tonic-gate !/^(extern|static)\b/) { 6387c478bd9Sstevel@tonic-gate err("return type of function not on separate line"); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate if (/^#define /) { 6417c478bd9Sstevel@tonic-gate err("#define followed by space instead of tab"); 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) { 6447c478bd9Sstevel@tonic-gate err("unparenthesized return expression"); 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate if (/\bsizeof\b/ && !/\bsizeof\s*\(.*\)/) { 6477c478bd9Sstevel@tonic-gate err("unparenthesized sizeof expression"); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate if (/\(\s/) { 6507c478bd9Sstevel@tonic-gate err("whitespace after left paren"); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate # allow "for" statements to have empty "continue" clauses 6537c478bd9Sstevel@tonic-gate if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) { 6547c478bd9Sstevel@tonic-gate err("whitespace before right paren"); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate if (/^\s*\(void\)[^ ]/) { 6577c478bd9Sstevel@tonic-gate err("missing space after (void) cast"); 6587c478bd9Sstevel@tonic-gate } 65994385aa4SToomas Soome if (/\S\{/ && !/\{\{/) { 6607c478bd9Sstevel@tonic-gate err("missing space before left brace"); 6617c478bd9Sstevel@tonic-gate } 662*518b16b9SDominik Hassler if ($in_function && /^\s+\{/ && 6637c478bd9Sstevel@tonic-gate ($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) { 6647c478bd9Sstevel@tonic-gate err("left brace starting a line"); 6657c478bd9Sstevel@tonic-gate } 666*518b16b9SDominik Hassler if (/\}(else|while)/) { 6677c478bd9Sstevel@tonic-gate err("missing space after right brace"); 6687c478bd9Sstevel@tonic-gate } 669*518b16b9SDominik Hassler if (/\}\s\s+(else|while)/) { 6707c478bd9Sstevel@tonic-gate err("extra space after right brace"); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate if (/\b_VOID\b|\bVOID\b|\bSTATIC\b/) { 6737c478bd9Sstevel@tonic-gate err("obsolete use of VOID or STATIC"); 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate if (/\b$typename\*/o) { 6767c478bd9Sstevel@tonic-gate err("missing space between type name and *"); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate if (/^\s+#/) { 6797c478bd9Sstevel@tonic-gate err("preprocessor statement not in column 1"); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate if (/^#\s/) { 6827c478bd9Sstevel@tonic-gate err("blank after preprocessor #"); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate if (/!\s*(strcmp|strncmp|bcmp)\s*\(/) { 6857c478bd9Sstevel@tonic-gate err("don't use boolean ! with comparison functions"); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate # 6897c478bd9Sstevel@tonic-gate # We completely ignore, for purposes of indentation: 6907c478bd9Sstevel@tonic-gate # * lines outside of functions 6917c478bd9Sstevel@tonic-gate # * preprocessor lines 6927c478bd9Sstevel@tonic-gate # 6937c478bd9Sstevel@tonic-gate if ($check_continuation && $in_function && !$in_cpp) { 6947c478bd9Sstevel@tonic-gate process_indent($_); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate if ($picky) { 6977c478bd9Sstevel@tonic-gate # try to detect spaces after casts, but allow (e.g.) 6983c2f5c48Sjwadams # "sizeof (int) + 1", "void (*funcptr)(int) = foo;", and 6993c2f5c48Sjwadams # "int foo(int) __NORETURN;" 7003c2f5c48Sjwadams if ((/^\($typename( \*+)?\)\s/o || 7013c2f5c48Sjwadams /\W\($typename( \*+)?\)\s/o) && 7027c478bd9Sstevel@tonic-gate !/sizeof\s*\($typename( \*)?\)\s/o && 7037c478bd9Sstevel@tonic-gate !/\($typename( \*+)?\)\s+=[^=]/o) { 7047c478bd9Sstevel@tonic-gate err("space after cast"); 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate if (/\b$typename\s*\*\s/o && 7077c478bd9Sstevel@tonic-gate !/\b$typename\s*\*\s+const\b/o) { 7087c478bd9Sstevel@tonic-gate err("unary * followed by space"); 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate if ($check_posix_types) { 7127c478bd9Sstevel@tonic-gate # try to detect old non-POSIX types. 7137c478bd9Sstevel@tonic-gate # POSIX requires all non-standard typedefs to end in _t, 7147c478bd9Sstevel@tonic-gate # but historically these have been used. 7157c478bd9Sstevel@tonic-gate if (/\b(unchar|ushort|uint|ulong|u_int|u_short|u_long|u_char|quad)\b/) { 7167c478bd9Sstevel@tonic-gate err("non-POSIX typedef $1 used: use $old2posix{$1} instead"); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate if ($heuristic) { 7207c478bd9Sstevel@tonic-gate # cannot check this everywhere due to "struct {\n...\n} foo;" 7217c478bd9Sstevel@tonic-gate if ($in_function && !$in_declaration && 722*518b16b9SDominik Hassler /\}./ && !/\}\s+=/ && !/\{.*\}[;,]$/ && !/\}(\s|)*$/ && 723*518b16b9SDominik Hassler !/\} (else|while)/ && !/\}\}/) { 7247c478bd9Sstevel@tonic-gate err("possible bad text following right brace"); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate # cannot check this because sub-blocks in 7277c478bd9Sstevel@tonic-gate # the middle of code are ok 728*518b16b9SDominik Hassler if ($in_function && /^\s+\{/) { 7297c478bd9Sstevel@tonic-gate err("possible left brace starting a line"); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate if (/^\s*else\W/) { 733*518b16b9SDominik Hassler if ($prev =~ /^\s*\}$/) { 7347c478bd9Sstevel@tonic-gate err_prefix($prev, 7357c478bd9Sstevel@tonic-gate "else and right brace should be on same line"); 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate $prev = $line; 7397c478bd9Sstevel@tonic-gate} 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gateif ($prev eq "") { 7427c478bd9Sstevel@tonic-gate err("last line in file is blank"); 7437c478bd9Sstevel@tonic-gate} 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate} 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate# 7487c478bd9Sstevel@tonic-gate# Continuation-line checking 7497c478bd9Sstevel@tonic-gate# 7507c478bd9Sstevel@tonic-gate# The rest of this file contains the code for the continuation checking 7517c478bd9Sstevel@tonic-gate# engine. It's a pretty simple state machine which tracks the expression 7527c478bd9Sstevel@tonic-gate# depth (unmatched '('s and '['s). 7537c478bd9Sstevel@tonic-gate# 7547c478bd9Sstevel@tonic-gate# Keep in mind that the argument to process_indent() has already been heavily 7557c478bd9Sstevel@tonic-gate# processed; all comments have been replaced by control-A, and the contents of 7567c478bd9Sstevel@tonic-gate# strings and character constants have been elided. 7577c478bd9Sstevel@tonic-gate# 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gatemy $cont_in; # currently inside of a continuation 7607c478bd9Sstevel@tonic-gatemy $cont_off; # skipping an initializer or definition 7617c478bd9Sstevel@tonic-gatemy $cont_noerr; # suppress cascading errors 7627c478bd9Sstevel@tonic-gatemy $cont_start; # the line being continued 7637c478bd9Sstevel@tonic-gatemy $cont_base; # the base indentation 7647c478bd9Sstevel@tonic-gatemy $cont_first; # this is the first line of a statement 7657c478bd9Sstevel@tonic-gatemy $cont_multiseg; # this continuation has multiple segments 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gatemy $cont_special; # this is a C statement (if, for, etc.) 7687c478bd9Sstevel@tonic-gatemy $cont_macro; # this is a macro 7697c478bd9Sstevel@tonic-gatemy $cont_case; # this is a multi-line case 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gatemy @cont_paren; # the stack of unmatched ( and [s we've seen 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gatesub 7747c478bd9Sstevel@tonic-gatereset_indent() 7757c478bd9Sstevel@tonic-gate{ 7767c478bd9Sstevel@tonic-gate $cont_in = 0; 7777c478bd9Sstevel@tonic-gate $cont_off = 0; 7787c478bd9Sstevel@tonic-gate} 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gatesub 7817c478bd9Sstevel@tonic-gatedelabel($) 7827c478bd9Sstevel@tonic-gate{ 7837c478bd9Sstevel@tonic-gate # 7847c478bd9Sstevel@tonic-gate # replace labels with tabs. Note that there may be multiple 7857c478bd9Sstevel@tonic-gate # labels on a line. 7867c478bd9Sstevel@tonic-gate # 7877c478bd9Sstevel@tonic-gate local $_ = $_[0]; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) { 7907c478bd9Sstevel@tonic-gate my ($pre_tabs, $label, $rest) = ($1, $2, $3); 7917c478bd9Sstevel@tonic-gate $_ = $pre_tabs; 7927c478bd9Sstevel@tonic-gate while ($label =~ s/^([^\t]*)(\t+)//) { 7937c478bd9Sstevel@tonic-gate $_ .= "\t" x (length($2) + length($1) / 8); 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate $_ .= ("\t" x (length($label) / 8)).$rest; 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate return ($_); 7997c478bd9Sstevel@tonic-gate} 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gatesub 8027c478bd9Sstevel@tonic-gateprocess_indent($) 8037c478bd9Sstevel@tonic-gate{ 8047c478bd9Sstevel@tonic-gate require strict; 8057c478bd9Sstevel@tonic-gate local $_ = $_[0]; # preserve the global $_ 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate s///g; # No comments 8087c478bd9Sstevel@tonic-gate s/\s+$//; # Strip trailing whitespace 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate return if (/^$/); # skip empty lines 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate # regexps used below; keywords taking (), macros, and continued cases 8137c478bd9Sstevel@tonic-gate my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b'; 8147c478bd9Sstevel@tonic-gate my $macro = '[A-Z_][A-Z_0-9]*\('; 8157c478bd9Sstevel@tonic-gate my $case = 'case\b[^:]*$'; 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate # skip over enumerations, array definitions, initializers, etc. 8187c478bd9Sstevel@tonic-gate if ($cont_off <= 0 && !/^\s*$special/ && 819*518b16b9SDominik Hassler (/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*))\{/ || 820*518b16b9SDominik Hassler (/^\s*\{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) { 8217c478bd9Sstevel@tonic-gate $cont_in = 0; 8227c478bd9Sstevel@tonic-gate $cont_off = tr/{/{/ - tr/}/}/; 8237c478bd9Sstevel@tonic-gate return; 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate if ($cont_off) { 8267c478bd9Sstevel@tonic-gate $cont_off += tr/{/{/ - tr/}/}/; 8277c478bd9Sstevel@tonic-gate return; 8287c478bd9Sstevel@tonic-gate } 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate if (!$cont_in) { 8317c478bd9Sstevel@tonic-gate $cont_start = $line; 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate if (/^\t* /) { 8347c478bd9Sstevel@tonic-gate err("non-continuation indented 4 spaces"); 8357c478bd9Sstevel@tonic-gate $cont_noerr = 1; # stop reporting 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate $_ = delabel($_); # replace labels with tabs 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate # check if the statement is complete 8407c478bd9Sstevel@tonic-gate return if (/^\s*\}?$/); 8417c478bd9Sstevel@tonic-gate return if (/^\s*\}?\s*else\s*\{?$/); 8427c478bd9Sstevel@tonic-gate return if (/^\s*do\s*\{?$/); 843*518b16b9SDominik Hassler return if (/\{$/); 844*518b16b9SDominik Hassler return if (/\}[,;]?$/); 8457c478bd9Sstevel@tonic-gate 8466f55da5aSjwadams # Allow macros on their own lines 8476f55da5aSjwadams return if (/^\s*[A-Z_][A-Z_0-9]*$/); 8486f55da5aSjwadams 8497c478bd9Sstevel@tonic-gate # cases we don't deal with, generally non-kosher 850*518b16b9SDominik Hassler if (/\{/) { 8517c478bd9Sstevel@tonic-gate err("stuff after {"); 8527c478bd9Sstevel@tonic-gate return; 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate # Get the base line, and set up the state machine 8567c478bd9Sstevel@tonic-gate /^(\t*)/; 8577c478bd9Sstevel@tonic-gate $cont_base = $1; 8587c478bd9Sstevel@tonic-gate $cont_in = 1; 8597c478bd9Sstevel@tonic-gate @cont_paren = (); 8607c478bd9Sstevel@tonic-gate $cont_first = 1; 8617c478bd9Sstevel@tonic-gate $cont_multiseg = 0; 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate # certain things need special processing 8647c478bd9Sstevel@tonic-gate $cont_special = /^\s*$special/? 1 : 0; 8657c478bd9Sstevel@tonic-gate $cont_macro = /^\s*$macro/? 1 : 0; 8667c478bd9Sstevel@tonic-gate $cont_case = /^\s*$case/? 1 : 0; 8677c478bd9Sstevel@tonic-gate } else { 8687c478bd9Sstevel@tonic-gate $cont_first = 0; 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate # Strings may be pulled back to an earlier (half-)tabstop 8717c478bd9Sstevel@tonic-gate unless ($cont_noerr || /^$cont_base / || 8727c478bd9Sstevel@tonic-gate (/^\t*(?: )?(?:gettext\()?\"/ && !/^$cont_base\t/)) { 8737c478bd9Sstevel@tonic-gate err_prefix($cont_start, 8747c478bd9Sstevel@tonic-gate "continuation should be indented 4 spaces"); 8757c478bd9Sstevel@tonic-gate } 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate my $rest = $_; # keeps the remainder of the line 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate # 8817c478bd9Sstevel@tonic-gate # The split matches 0 characters, so that each 'special' character 8827c478bd9Sstevel@tonic-gate # is processed separately. Parens and brackets are pushed and 8837c478bd9Sstevel@tonic-gate # popped off the @cont_paren stack. For normal processing, we wait 8847c478bd9Sstevel@tonic-gate # until a ; or { terminates the statement. "special" processing 8857c478bd9Sstevel@tonic-gate # (if/for/while/switch) is allowed to stop when the stack empties, 8867c478bd9Sstevel@tonic-gate # as is macro processing. Case statements are terminated with a : 8877c478bd9Sstevel@tonic-gate # and an empty paren stack. 8887c478bd9Sstevel@tonic-gate # 8897c478bd9Sstevel@tonic-gate foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) { 8907c478bd9Sstevel@tonic-gate next if (length($_) == 0); 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate # rest contains the remainder of the line 8937c478bd9Sstevel@tonic-gate my $rxp = "[^\Q$_\E]*\Q$_\E"; 8947c478bd9Sstevel@tonic-gate $rest =~ s/^$rxp//; 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate if (/\(/ || /\[/) { 8977c478bd9Sstevel@tonic-gate push @cont_paren, $_; 8987c478bd9Sstevel@tonic-gate } elsif (/\)/ || /\]/) { 8997c478bd9Sstevel@tonic-gate my $cur = $_; 9007c478bd9Sstevel@tonic-gate tr/\)\]/\(\[/; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate my $old = (pop @cont_paren); 9037c478bd9Sstevel@tonic-gate if (!defined($old)) { 9047c478bd9Sstevel@tonic-gate err("unexpected '$cur'"); 9057c478bd9Sstevel@tonic-gate $cont_in = 0; 9067c478bd9Sstevel@tonic-gate last; 9077c478bd9Sstevel@tonic-gate } elsif ($old ne $_) { 9087c478bd9Sstevel@tonic-gate err("'$cur' mismatched with '$old'"); 9097c478bd9Sstevel@tonic-gate $cont_in = 0; 9107c478bd9Sstevel@tonic-gate last; 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate # 9147c478bd9Sstevel@tonic-gate # If the stack is now empty, do special processing 9157c478bd9Sstevel@tonic-gate # for if/for/while/switch and macro statements. 9167c478bd9Sstevel@tonic-gate # 9177c478bd9Sstevel@tonic-gate next if (@cont_paren != 0); 9187c478bd9Sstevel@tonic-gate if ($cont_special) { 919*518b16b9SDominik Hassler if ($rest =~ /^\s*\{?$/) { 9207c478bd9Sstevel@tonic-gate $cont_in = 0; 9217c478bd9Sstevel@tonic-gate last; 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate if ($rest =~ /^\s*;$/) { 9247c478bd9Sstevel@tonic-gate err("empty if/for/while body ". 9257c478bd9Sstevel@tonic-gate "not on its own line"); 9267c478bd9Sstevel@tonic-gate $cont_in = 0; 9277c478bd9Sstevel@tonic-gate last; 9287c478bd9Sstevel@tonic-gate } 9297c478bd9Sstevel@tonic-gate if (!$cont_first && $cont_multiseg == 1) { 9307c478bd9Sstevel@tonic-gate err_prefix($cont_start, 9317c478bd9Sstevel@tonic-gate "multiple statements continued ". 9327c478bd9Sstevel@tonic-gate "over multiple lines"); 9337c478bd9Sstevel@tonic-gate $cont_multiseg = 2; 9347c478bd9Sstevel@tonic-gate } elsif ($cont_multiseg == 0) { 9357c478bd9Sstevel@tonic-gate $cont_multiseg = 1; 9367c478bd9Sstevel@tonic-gate } 9377c478bd9Sstevel@tonic-gate # We've finished this section, start 9387c478bd9Sstevel@tonic-gate # processing the next. 9397c478bd9Sstevel@tonic-gate goto section_ended; 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate if ($cont_macro) { 9427c478bd9Sstevel@tonic-gate if ($rest =~ /^$/) { 9437c478bd9Sstevel@tonic-gate $cont_in = 0; 9447c478bd9Sstevel@tonic-gate last; 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate } elsif (/\;/) { 9487c478bd9Sstevel@tonic-gate if ($cont_case) { 9497c478bd9Sstevel@tonic-gate err("unexpected ;"); 9507c478bd9Sstevel@tonic-gate } elsif (!$cont_special) { 9517c478bd9Sstevel@tonic-gate err("unexpected ;") if (@cont_paren != 0); 9527c478bd9Sstevel@tonic-gate if (!$cont_first && $cont_multiseg == 1) { 9537c478bd9Sstevel@tonic-gate err_prefix($cont_start, 9547c478bd9Sstevel@tonic-gate "multiple statements continued ". 9557c478bd9Sstevel@tonic-gate "over multiple lines"); 9567c478bd9Sstevel@tonic-gate $cont_multiseg = 2; 9577c478bd9Sstevel@tonic-gate } elsif ($cont_multiseg == 0) { 9587c478bd9Sstevel@tonic-gate $cont_multiseg = 1; 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate if ($rest =~ /^$/) { 9617c478bd9Sstevel@tonic-gate $cont_in = 0; 9627c478bd9Sstevel@tonic-gate last; 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate if ($rest =~ /^\s*special/) { 9657c478bd9Sstevel@tonic-gate err("if/for/while/switch not started ". 9667c478bd9Sstevel@tonic-gate "on its own line"); 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate goto section_ended; 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate } elsif (/\{/) { 9717c478bd9Sstevel@tonic-gate err("{ while in parens/brackets") if (@cont_paren != 0); 9727c478bd9Sstevel@tonic-gate err("stuff after {") if ($rest =~ /[^\s}]/); 9737c478bd9Sstevel@tonic-gate $cont_in = 0; 9747c478bd9Sstevel@tonic-gate last; 9757c478bd9Sstevel@tonic-gate } elsif (/\}/) { 9767c478bd9Sstevel@tonic-gate err("} while in parens/brackets") if (@cont_paren != 0); 9777c478bd9Sstevel@tonic-gate if (!$cont_special && $rest !~ /^\s*(while|else)\b/) { 9787c478bd9Sstevel@tonic-gate if ($rest =~ /^$/) { 9797c478bd9Sstevel@tonic-gate err("unexpected }"); 9807c478bd9Sstevel@tonic-gate } else { 9817c478bd9Sstevel@tonic-gate err("stuff after }"); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate $cont_in = 0; 9847c478bd9Sstevel@tonic-gate last; 9857c478bd9Sstevel@tonic-gate } 9867c478bd9Sstevel@tonic-gate } elsif (/\:/ && $cont_case && @cont_paren == 0) { 9877c478bd9Sstevel@tonic-gate err("stuff after multi-line case") if ($rest !~ /$^/); 9887c478bd9Sstevel@tonic-gate $cont_in = 0; 9897c478bd9Sstevel@tonic-gate last; 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate next; 9927c478bd9Sstevel@tonic-gatesection_ended: 9937c478bd9Sstevel@tonic-gate # End of a statement or if/while/for loop. Reset 9947c478bd9Sstevel@tonic-gate # cont_special and cont_macro based on the rest of the 9957c478bd9Sstevel@tonic-gate # line. 9967c478bd9Sstevel@tonic-gate $cont_special = ($rest =~ /^\s*$special/)? 1 : 0; 9977c478bd9Sstevel@tonic-gate $cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0; 9987c478bd9Sstevel@tonic-gate $cont_case = 0; 9997c478bd9Sstevel@tonic-gate next; 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate $cont_noerr = 0 if (!$cont_in); 10027c478bd9Sstevel@tonic-gate} 1003